告别手动标注!Grounding DINO + SAM:用嘴“指挥”视觉 AI,开启具身智能零样本分割新纪元!

代码仓库:
https://github.com/IDEA-Research/Grounded-Segment-Anything
告别繁琐的图片标注,让机器人像人类一样通过“直觉”锁定万物:本文将带你深度实操 Grounding DINO + SAM 这一视觉神技,拆解从文字指令到精准像素掩码的感知全过程,为你的具身智能项目安上一双“听得懂人话”的眼睛。
认识 Grounding DINO + SAM:
视觉界的“黄金搭档”
它们是什么?
Grounding DINO:一个“文本检测”模型。你给它一张图和一句话(比如 "handle of the teapot"),它能返回一个矩形框 (Bounding Box)。
SAM (Segment Anything Model):Meta 开发的“万物皆可分割”模型。它极其擅长抠图,但它不知道该抠什么。它需要一个“提示”(比如一个点或一个框)。
为什么要一起使用?
单一的模型都有缺陷:DINO 只有框,不够精准(机器人抓取需要像素级位置);SAM 没“大脑”,不知道哪个才是用户想要的。
两者结合,就实现了:文字指令 $\rightarrow$ 锁定目标框 $\rightarrow$ 生成精准掩码 (Mask)。
新手实战
第一步:准备你的环境
这个项目对硬件有一定要求。GPU 强烈推荐,Grounding DINO 和 SAM 在 CPU 上也可以运行,但速度会很慢(单张图可能需要几分钟),用于学习调试是可以的。推荐配置是 NVIDIA GPU(显存 ≥ 6GB),以及 CUDA 11.7 或以上版本。
软件环境方面,建议使用 Python 3.8–3.10(3.11 可能有少数兼容问题)。强烈建议使用 Conda 创建独立虚拟环境,避免与其他项目产生依赖冲突:
# 创建并激活一个名为 grounded-sam 的环境
conda create -n grounded-sam python=3.9 -y
conda activate grounded-sam
# 安装 PyTorch(以 CUDA 11.8 为例,请根据你的实际 CUDA 版本调整)
pip install torch torchvision --index-url https://download.pytorch.org/whl/cu118如果你没有 GPU,也可以先在 Google Colab 上跑通流程,那里有免费的 T4 GPU,非常适合学习。
第二步:克隆项目仓库
社区已经有一个整合好的项目 Grounded-Segment-Anything,你不需要自己从头拼接两个模型:
# 克隆主项目
git clone https://github.com/IDEA-Research/Grounded-Segment-Anything.git
cd Grounded-Segment-Anything
# 安装 Grounding DINO 的依赖
pip install -e .
# 安装 SAM
pip install git+https://github.com/facebookresearch/segment-anything.git
# 安装其他依赖
pip install -r requirements.txt第三步:下载模型权重
这一步需要下载两个预训练模型的权重文件,是所有"魔法"的真正来源:
# 在项目目录下创建一个 weights 文件夹
mkdir -p weights
cd weights
# 下载 Grounding DINO 的权重(约 694MB)
wget -q https://github.com/IDEA-Research/GroundingDINO/releases/download/v0.1.0-alpha/groundingdino_swint_ogc.pth
# 下载 SAM 的 ViT-H 权重(约 2.4GB)
# 如果下载缓慢,也可以手动从 Hugging Face 下载
wget -q https://dl.fbaipublicfiles.com/segment_anything/sam_vit_h_4b8939.pth
cd ..下载完成后,weights/ 目录下应该有两个 .pth 文件。
第四步:运行你的第一个推理
现在到了最激动人心的一步。我们来写一个完整的推理脚本,把一张图片和一个文本描述传进去,看看效果:
import torch
from PIL import Image
import numpy as np
import matplotlib.pyplot as plt
# 导入 Grounding DINO
from groundingdino.util.inference import load_model, load_image, predict, annotate
# 导入 SAM
from segment_anything import sam_model_registry, SamPredictor
# ── 1. 加载模型 ──
print("正在加载模型,请稍候...")
# 加载 Grounding DINO(需要配置文件路径和权重路径)
grounding_dino_model = load_model(
"groundingdino/config/GroundingDINO_SwinT_OGC.py", # 配置文件
"weights/groundingdino_swint_ogc.pth" # 权重文件
)
# 加载 SAM
sam = sam_model_registry["vit_h"](checkpoint="weights/sam_vit_h_4b8939.pth")
sam.to(device="cuda" if torch.cuda.is_available() else "cpu")
sam_predictor = SamPredictor(sam)
print("模型加载完成!")
# ── 2. 设定输入 ──
IMAGE_PATH = "path/to/your/image.jpg" # 替换成你的图片路径
TEXT_PROMPT = "dog . cat ." # 用句号分隔多个目标描述
BOX_THRESHOLD = 0.35 # 边界框的置信度阈值,越高越严格
TEXT_THRESHOLD = 0.25 # 文本匹配的阈值
# ── 3. 第一阶段:Grounding DINO 检测边界框 ──
image_source, image = load_image(IMAGE_PATH)
boxes, logits, phrases = predict(
model=grounding_dino_model,
image=image,
caption=TEXT_PROMPT,
box_threshold=BOX_THRESHOLD,
text_threshold=TEXT_THRESHOLD
)
print(f"检测到 {len(boxes)} 个目标:{phrases}")
# ── 4. 第二阶段:SAM 精细分割 ──
# 将原始图像设为 SAM 的输入
sam_predictor.set_image(np.array(image_source))
# 将边界框坐标转换为 SAM 需要的格式
H, W, _ = np.array(image_source).shape
boxes_xyxy = boxes * torch.Tensor([W, H, W, H])
# 转换为 (x1, y1, x2, y2) 格式
from groundingdino.util import box_ops
boxes_xyxy = box_ops.box_cxcywh_to_xyxy(boxes_xyxy)
# 批量推理得到分割掩码
transformed_boxes = sam_predictor.transform.apply_boxes_torch(
boxes_xyxy, image_source.size[::-1]
)
masks, _, _ = sam_predictor.predict_torch(
point_coords=None,
point_labels=None,
boxes=transformed_boxes,
multimask_output=False, # 每个框只输出一个最佳掩码
)
print(f"分割完成,得到 {masks.shape[0]} 个掩码")
# ── 5. 可视化结果 ──
def show_masks(image, masks, labels):
fig, ax = plt.subplots(1, 1, figsize=(10, 8))
ax.imshow(image)
colors = plt.cm.Set1(np.linspace(0, 1, len(masks)))
for i, (mask, label) in enumerate(zip(masks, labels)):
m = mask[0].cpu().numpy()
colored_mask = np.zeros((*m.shape, 4))
colored_mask[m] = [*colors[i][:3], 0.5] # 半透明着色
ax.imshow(colored_mask)
# 在掩码中心标注标签
y, x = np.where(m)
if len(y) > 0:
ax.text(x.mean(), y.mean(), label,
color='white', fontsize=12, ha='center',
bbox=dict(boxstyle='round', facecolor='black', alpha=0.6))
ax.axis('off')
plt.tight_layout()
plt.savefig("result.png", dpi=150)
plt.show()
show_masks(image_source, masks, phrases)
print("结果已保存至 result.png")运行过程总结

避坑指南
CUDA 版本冲突(最常见)
Grounding DINO 在安装时会编译 CUDA 扩展(MultiScaleDeformableAttention),如果你的 PyTorch 版本和系统 CUDA 版本不匹配,这一步就会报错。解决方法是先运行 nvcc --version 确认你的 CUDA 版本,再去 PyTorch 官网的安装页面选择对应版本的安装命令。如果实在搞不定编译,可以尝试安装预编译的 CPU 版本先跑通逻辑,GPU 版本再慢慢解决。
文字描述格式错误导致检测失败
Grounding DINO 对文本 prompt 的格式有一定要求。多个目标必须用英文句号分隔,例如 "dog . cat . person ." 而不是 "dog, cat, person" 或 "dog and cat"。此外,描述语言应简洁清晰,过于复杂的描述(如长句子)反而会降低检测效果。建议使用英文名词短语,暂时不要使用中文(虽然 Grounding DINO 有一定的多语言能力,但在中文下效果不如英文稳定)。
阈值设置不当
BOX_THRESHOLD 和 TEXT_THRESHOLD 是两个极其关键的超参数,却经常被新手忽略。阈值过高(如 0.6 以上)会导致漏检,很多真实目标被过滤掉;阈值过低(如 0.1)则会产生大量误检,把不相关的区域也框出来。推荐的起始值是 0.3–0.35,然后根据你的图片质量和描述内容逐步调整。可以先设低一点观察检测结果,再逐步收紧。
总结
希望这篇教程能帮助你顺利上手 Grounding DINO + SAM!这个项目融合了两个当下最强的视觉基础模型,是学习现代计算机视觉方法的绝佳切入点。
环境配置确实是这类项目最难的一关,但一旦跑通,后面的探索会越来越有趣。
