30分钟跑通 DINOv3 零样本语义分割:dinotxt 部署实战教程
2026/9/15 15:57:38 网站建设 项目流程

30分钟跑通 DINOv3 零样本语义分割:dinotxt 部署实战教程

【免费下载链接】dinov3Reference PyTorch implementation and models for DINOv3项目地址: https://gitcode.com/GitHub_Trending/di/dinov3

DINOv3 零样本语义分割实战教程,主题是 dinotxt 部署:传入类别名,直接输出像素级 mask,不训练、不用标注数据。下文按最短路径跑通、整图与滑窗推理怎么选、提示模板、mIoU 评估怎么读的顺序展开。

🖼️ 先看效果:零样本分割输出什么

先说清楚零样本分割的输入输出,建立预期:

  • 不训练:没有标注数据,没有要微调的 head,模型参数不动。
  • 输入:一张图 + 一组类别名,例如("road", "car", "sky")
  • 输出:每个类别一张得分图,沿类别维取 argmax 就是逐像素 mask。

官方仓库自带一份可直接运行的推理 notebook:notebooks/dinotxt_segmentation_inference.ipynb,里面写好了 Cityscapes 19 类和 ADE20K 150 类的类别定义、两种推理模式与指标统计。本文所有代码都取自这份 notebook,照着交叉阅读即可。

🧰 环境搭建与最短路径跑通

第一步,clone 仓库并用 conda.yaml 建环境:

git clone https://gitcode.com/GitHub_Trending/di/dinov3 && cd dinov3 micromamba env create -f conda.yaml micromamba activate dinov3

conda.yaml 固定了 python 3.11、torch/torchmetrics,以及 dino.txt 依赖的 ftfy 和 regex。验证方式:新环境里执行python -c "import torch",打印版本号即成功。

两点提醒:

  • dinotxt 入口会同时加载 ViT-L/16 主干权重,权重需先按 README 的 Pretrained models 一节申请下载;已有本地权重时用backbone_weights参数传入。
  • 图像要按 ImageNet 均值方差归一化,且 H、W 拉伸到 16(patch 大小)的整数倍,这两步在 notebook 的encode_imageShortSideResize里。

第二步,一个脚本完成加载、文本编码、图像编码和取 mask:

model, tokenizer = dinov3_vitl16_dinotxt_tet1280d20h24l() model.to("cuda").eval() tokenizer = tokenizer.tokenize feats = model.encode_text(tokenizer(["a photo of a road.", "a photo of a car."]).to("cuda")) text_feats = F.normalize(feats[:, feats.shape[1]//2:], dim=-1) # [2, D] h, w = img.shape[-2]//16, img.shape[-1]//16 grid = F.normalize(model.visual_model.get_class_and_patch_tokens(img[None])[2].reshape(h, w, -1), dim=-1) mask = torch.einsum("cd,hwd->chw", text_feats, grid).argmax(0)

这段做的事:dinov3_vitl16_dinotxt_tet1280d20h24l()返回模型和分词器;encode_text的输出一半对应 CLS token(丢弃)一半对应 patch 侧,取后半并归一化即得文本特征;get_class_and_patch_tokens的第三个返回值是骨干的 patch token,reshape 成网格就是图像侧特征;einsum算余弦相似度后逐点 argmax。mask形状是[h, w],即每个 16×16 块一个类别判断,双线性插值到原图尺寸就是最终 mask;如果全图只判出一类,先检查归一化和 16 倍数拉伸。

原理一句话版:mask 是怎么来的

整个机制只有一条:dinotxt 用图文对比的方式训练,视觉端给每个 16×16 patch 输出一个向量,文本端给每个类别名输出一个向量,两者落在同一特征空间,余弦相似度就是"这块像这个类别"的分数,分割 = 全图像素逐个 argmax。

由此有两个直接推论:

  • 不需要额外分类头,mask 质量完全由骨干的密集特征决定。
  • 类别列表可以运行时任意增删,不用动模型;换场景只改那组字符串。

⚡ 整图与滑窗推理怎么选

两种模式对应两种分辨率场景:

  • 整图(predict_whole):整张图一次过模型,输出低分辨率得分图再插值放大。快、稳,短边 512 以内的图选它。
  • 滑窗(predict_slide):按side×side的窗口、stride步长切片,每块走一遍整图流程,再按重叠加权拼回原图分辨率。细节更好,短边 1024 以上的街景、遥感图选它。

notebook 的参考参数是side=384, stride=192(50% 重叠)。显存紧张时优先调小side,而不是压缩类别数。跑滑窗前先用短边 512 的 resize 把图缩小,最终 mask 分辨率与输入图一致。调用本身是一行:predict_slide(model, img, text_feats, side=384, stride=192),返回与输入同尺寸的逐像素得分,argmax 即 mask。

提示模板怎么写与组合

为什么模板有用:单句 "a photo of a car" 只覆盖一种说法,类别表示容易被措辞带偏。notebook 用 80 条模板变体(模糊照片、渲染图、特写、涂鸦、黑白照等)分别编码后取平均,类别表示更稳、覆盖面更全。

组合方式:

  • 默认全量使用,notebook 报数字就是这个配置。
  • 时间紧时挑 8~10 条,覆盖"普通照片 / 低画质 / 渲染"三类即可。
  • 类别名保持名词,不要塞颜色、尺寸修饰词。
  • 平均之后必须重新归一化,否则余弦相似度退化成模长比较。

📊 mIoU 怎么看

评估只看一个指标:mIoU,即各类别 IoU(交并比)的宏平均,是语义分割的标准口径。notebook 用 torchmetrics 的MulticlassJaccardIndex(num_classes, average="macro", ignore_index=255)统计,255 是忽略标签。

看数三点:

  • 总分定"能不能用",分类别看"哪里不行"。
  • 小目标类别(如交通标志)通常拖分,总分高不代表安全。
  • 对比不同配置的数字前,先固定 resize、side、stride,否则不可比。

关键文件索引

  • dinov3/eval/text/dinotxt_model.py:组装 visual_model 与 text_model 两个塔,encode_text与 patch 提取入口。
  • dinov3/eval/text/vision_tower.py:视觉端定义,骨干加两个附加块。
  • dinov3/hub/dinotxt.py:模型加载入口,weightsbackbone_weights参数在这里。

能力边界:街景、室内等常见场景零样本直接可用;长尾领域与极小目标上,训练过的模型仍更强。 下一步:先复现 notebook 的 Cityscapes 数字,再换自己的类别列表;需要训练侧看dinov3/eval/text/train_dinotxt.py

【免费下载链接】dinov3Reference PyTorch implementation and models for DINOv3项目地址: https://gitcode.com/GitHub_Trending/di/dinov3

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询