DINOv3 dino.txt 零样本语义分割:不训练,一张街景图直接出 19 类结果
【免费下载链接】dinov3Reference PyTorch implementation and models for DINOv3项目地址: https://gitcode.com/GitHub_Trending/di/dinov3
手里只有一批街景照片,没有逐像素标注,也不想为每个类别各跑一遍训练——DINOv3 的 dino.txt 能直接给出零样本分割:输入类别名,输出每个像素的类别图,全程不训练。
没有标注数据,也能做语义分割
传统语义分割要先标好每类像素,再对网络做监督训练;类别一变,标注重来、训练重来。dino.txt 换了条路:把类别名写成自然语言喂给模型,模型按名字找区域。Cityscapes 的 19 个街景类、ADE20K 的 150 个场景类,都能按名字直接分,不需要为它们准备一份标注。
它凭什么可行:图文对齐
dino.txt 本质是一组图文对比模型。视觉侧用 ViT-L/16 骨干,把图切成小块再逐块出特征;文本侧用 24 层、维度 1280 的文本塔把类名编码成向量。两侧落在同一个 2048 维空间里,于是"某块像不像某个词"就能用余弦相似度衡量——两个向量夹角越小越匹配。加载入口在 hub/dinotxt.py:
from dinov3.hub.dinotxt import dinov3_vitl16_dinotxt_tet1280d20h24l model, tokenizer = dinov3_vitl16_dinotxt_tet1280d20h24l() model.to("cuda").eval() tokenizer = tokenizer.tokenize这个函数一次返回模型和分词器,函数名里的 1280/20/24 正对应文本塔的维度、头数、层数,改名字不用改代码。
装环境、跑通第一张图
按官方 conda.yaml 建环境即可,pretrained=True时权重自动下载,无需手动搬文件。
git clone https://gitcode.com/GitHub_Trending/di/dinov3 cd dinov3 micromamba env create -f conda.yaml micromamba activate dinov3环境装好后,把上面三行加载代码粘进脚本,model就绪。完整参考实现在 分割推理 notebook,里面的encode_image会把图 resize 到 patch_size(16)的整数倍再取 patch 特征。
把类别名变成向量
每个类别先用一批提示模板(参考 CLIP,约 80 条,如 "a photo of a {0}.")包一层再编码、平均,得到一个归一化向量;模板越多,向量对措辞越不敏感。
text_feats = [] for name in class_names: texts = [t.format(name) for t in PROMPT_TEMPLATES] tokens = tokenizer(texts).to("cuda") feats = model.encode_text(tokens) feats = feats[:, feats.shape[1] // 2:] # 丢掉对应 CLS 的前半段 feats = F.normalize(feats, p=2, dim=-1) feats = F.normalize(feats.mean(dim=0), p=2, dim=-1) text_feats.append(feats) text_feats = torch.stack(text_feats) # [num_classes, D]产出是一张 [类别数, 维度] 的表,每行代表一个类;类别一多,这段只需算一次,后面逐张图复用。
全图 vs 滑动窗口:推理模式怎么选
中等分辨率用全图:整图过一遍,patch 特征与文本特征做点积,得到 [类别数, h, w] 的低分辨率相似度图,再插值回原分辨率取 argmax。
def predict_whole(model, img, text_feats): _, blocks = encode_image(model, img.unsqueeze(0)) # [1, H/16, W/16, D] blocks = F.normalize(blocks.squeeze(0), p=2, dim=-1) cos = torch.einsum("cd,hwd->chw", text_feats, blocks) return cos # [num_classes, h, w]高分辨率大图走滑动窗口:notebook 里 side=384、stride=192,每个窗口内算相似度、做 softmax,再按重叠次数平均累积到原分辨率,避免大图显存爆。两种模式切换只改一个配置项mode(whole/slide)。
效果怎么验证:mIoU
官方用多类 Jaccard 指数(mIoU,宏平均)打分,忽略索引 255 的背景,和"有没有训练"直接可比。
from torchmetrics.classification import MulticlassJaccardIndex miou = MulticlassJaccardIndex(len(class_names), average="macro", ignore_index=255) for img, target in dataloader: pred = predict_whole(model, img.cuda(), text_feats) pred = F.interpolate(pred[None], size=target.shape, mode="bilinear") miou.update(pred.squeeze().argmax(0)[None], target[None].cuda()) print(f"mIoU: {100 * miou.compute().item()}")在 Cityscapes 或 ADE20K 验证集上跑完,打印的就是百分制 mIoU,越高说明按名字分的区域越准。
跑之前先避开这几个坑
- 图像尺寸要落在 16 的整数倍上,
encode_image会自己补,但提前 resize 更稳。 encode_text返回的向量是两倍宽:前半段对应 CLS,真正要用后半段。- 滑窗的 side/stride 直接决定显存和速度,大图别硬上全图。
- 类别名用英文小写、和标注体系对齐,名字对不上就会漏类。
想继续读实现,看 hub/dinotxt.py 的加载逻辑和 文本塔 的编码细节。
【免费下载链接】dinov3Reference PyTorch implementation and models for DINOv3项目地址: https://gitcode.com/GitHub_Trending/di/dinov3
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考