自动标注三件套:Grounded-SAM、autodistill、X-AnyLabeling 实战
标注工作最磨人的不是画框这个动作本身而是“重复、量大、还得保证质量”。我去年把整套标注流程彻底重写了一遍从原来靠人在 X-AnyLabeling 里一张张手工拉框到后来引入 Grounded-SAM 自动出掩膜、再用 autodistill 做主动学习迭代整个数据生产线才算真正转起来。这篇文章就把这条链路完整拆开来讲包含环境搭建、提示词设计、批量跑图、人工校验、格式转换和各类翻车实录适合正在做目标检测、实例分割数据集或者被标注成本压得喘不过气的算法工程师、数据工程师参考。1. 整体思路三件套各管一段组合成一条自动标注流水线1.1 为什么是这三个工具先理清一个认知市面上没有任何单一工具能包办“自动标注”这件事。自动标注本质上是一条流水线至少需要三个环节自动生成粗标注、模型辅助迭代标注、人工精修兜底。我把这块拆成三件套对应关系非常明确。Grounded-SAM负责“从零生成粗标注”。它把 GroundingDINO 的文本检测能力和 SAM 的分割能力串起来只要输入一句“car. person. traffic light.”就能输出相应的检测框和分割掩膜。它的价值在于零样本、开箱即用不用先准备训练集。autodistill负责“用小模型跟上大模型的节奏”。Grounded-SAM 这种大模型推理速度慢大批量跑图跑不起而 autodistill 的核心思路是用大模型当 teacher先自动标注一批数据再训练一个小模型当 student之后让小模型接手大部分推理工作形成主动学习闭环。X-AnyLabeling负责“人工精修与格式落地”。自动标注出来的结果永远带瑕疵——漏检、误检、边缘毛糙、类别错位必须有一个顺手的工具让人快速修正。X-AnyLabeling 内置了多种模型推理引擎支持交互式分割、半自动标注、关键点标注还能直接导入导出 YOLO、COCO、VOC 等格式是流水线最后一道闸门。这三个工具在职责上几乎没有重叠刚好组成一个金字塔Grounded-SAM 是地基autodistill 是自动化的加速器X-AnyLabeling 是质量控制的终结者。1.2 整体标注流程长什么样用一个实际项目的执行顺序来说明更直观。假设我要做一个“街边小物体检测”数据集类别包括“椅子、雨伞、自行车、垃圾桶”四类先用 Grounded-SAM 在原始图片上跑一轮文本提示词自动生成包含 bbox 和 mask 的标注文件。把 Grounded-SAM 的输出导成 COCO JSON 格式喂给 autodistill用它训练一个 lightweight student 模型比如 YOLOv8n。再用 student 模型对另一批未标注图片做批量预测把置信度低的样本挑出来交给人工精修。最后把所有这些结果放进 X-AnyLabeling由标注员用快捷键逐张核验、删改、补漏导出最终数据集。这套流程的精髓是“把人的精力只放在疑难样本上”。高质量样本让模型自动过低质量样本才需要人去处理标注成本能压缩到原来的三分之一甚至更低。2. X-AnyLabeling安装、配置与快捷键体系2.1 环境搭建与 Linux 注意事项X-AnyLabeling 有两种常见装法直接下 release 包或者源码编译。Windows 用户直接去官方 GitHub release 下载编译好的压缩包解压即用。但 Linux 下不能靠一个二进制包走天下得手动处理依赖链。我是在 Ubuntu 22.04 上搭建的踩了几个坑后总结出一套稳定的安装路径。# 1. 先创建独立的 conda 环境避免和系统 Python 打架 conda create -n anylabeling python3.10 -y conda activate anylabeling # 2. 安装 PyQt5 基础依赖 sudo apt update sudo apt install libgl1 libglib2.0-0 libsm6 libxext6 libxrender1 \ libgomp1 libegl1 mesa-utils -y # 3. 克隆源码并安装 git clone https://github.com/vietanhdev/anylabeling.git cd anylabeling pip install -r requirements.txt python anylabeling/app.pyLinux 上最容易踩的坑有两个。第一个是 libGL.so.1 缺失PyQt5 和无头显卡环境经常遇到启动时报ImportError: libGL.so.1: cannot open shared object file执行sudo apt install libgl1就能解决。第二个坑是 OpenCV 版本冲突如果系统里已经装了 opencv-python-headless而 anylabeling 依赖的是完整版 opencv两边的视频解码后端会互相干扰典型的症状是导入图片正常、打开视频异常。处理方法很简单先卸载 headless 版本再重装普通版。pip uninstall opencv-python-headless -y pip install opencv-python4.8.1.78注意X-AnyLabeling 对 torch 的版本没有硬性要求但如果你要用内置的 SAM 模型做交互式分割建议单独装一个 torch 环境不要把 torch 装进 anylabeling 的 conda 环境里否则每次启动程序都要等 torch 加载光是初始化就慢 20 秒。我习惯把 anylabeling 保持轻量需要跑模型时直接调用命令行推理脚本两边互不干扰。2.2 快捷键体系提效的核心武器X-AnyLabeling 的快捷键设计是我见过那么多标注工具里比较合理的。它不只是“画框快”而是把“画框、切图、查漏、改错”整套动作都做成了单手操作。最常用的几组我列出来操作目的快捷键说明画矩形标注W按一次进入画框状态拖动即可画多边形标注P适合精细轮廓标注点一次加一个顶点智能分割D激活内置 SAM / YOLOSAM单击目标即可出掩膜切换下一张图D或N按工具版本略有差异我常用D确认当前图后立即切下一张删除当前标注CtrlD/Delete删除当前选中的框或多边形撤销上一步CtrlZ误操作兜底画错顶点赶紧撤销复制标注到下一张CtrlC/CtrlV视频帧或相似场景下能省一半时间放大缩小画布/-看细碎小目标时非常关键自适应窗口F一键回到全局视图方便对比前后帧我实测下来效率最高的操作组合是W 画框 → D 切下一张 → W 画框这个循环里右手完全不需要离开鼠标左手配合快捷键切图每小时处理的图片数量比纯手工画框高两到三倍。还有一个被很多人忽略的功能形状复制粘贴。在连续帧标注中比如视频抽帧的数据集物体往往只在原位置做轻微移动我通常是第一帧画好框第二帧直接 CtrlC / CtrlV 粘贴再轻微拖拽调整位置。这种“先复制再微调”的打法比每帧重新画效率高得多。2.3 内置 AI 推理引擎的正确打开方式X-AnyLabeling 最亮眼的设计是内置了一批推理引擎包括 YOLOv8、YOLOv5、SAM、MobileSAM、RT-DETR 等可以不写代码直接在软件里跑模型推理。但我不建议一上来就把所有模型都加载一遍。我的实际使用原则是日常画框场景只加载一个小型模型比如 yolov8n用于“AI 辅助自动画框”。点击模型后工具会先在后台对所有目标出框标注员只需要核验是否有漏检和误检。精细分割场景才切换 SAM 系列模型。SAM 靠单击提示词就能分割出目标轮廓适合做实例分割数据集但推理速度慢不能全程开着。我的经验是先让内置模型预标注再人工逐张检查而不是直接信任模型的全部输出。模型出的框有个规律大类目标很准小目标和遮挡严重的漏检率高。人工检查的节奏就是把漏检补上、把误检删掉而不是从零开始画。3. Grounded-SAM从文本提示到自动掩膜3.1 环境搭建与权重准备Grounded-SAM 并不是一个独立模型它是“GroundingDINO SAM”的组合流水线官方仓库也明确说明需要分别准备两个模型的权重。环境搭建我建议直接用官方给的environment.yml或者自己用 conda 控制依赖版本。git clone https://github.com/IDEA-Research/Grounded-SAM.git cd Grounded-SAM conda env create -f environment.yml conda activate grounded-sam python -m pip install -e .权重文件方面需要准备两个GroundingDINO 权重从官方仓库 release 下载我使用的是groundingdino_swint_ogc适合通用目标检测。如果你有特定场景可以选用经过微调的 checkpoint。SAM ViT-H 权重从 SAM 官方仓库下载sam_vit_h_4b8939.pth。如果显卡显存不够也可以用 ViT-B / ViT-L 版本但分割精细度会略降。启动推理可以用官方示例脚本但官方脚本只处理单张图片。对大规模批量标注来说我更建议写一个简单的 shell 循环把图片一张张喂进去并自动记录耗时和输出路径。3.2 提示词模板设计一句话决定标注质量Grounded-SAM 的检测效果很大程度取决于提示词的写法。我总结出的经验是提示词不是越短越好也不是越长越好而是要覆盖“类别范围 排除歧义”。以“车辆”这个大类为例我的提示词写作方式对比提示词效果说明car只检出小轿车卡车、公交车全部漏掉过窄vehicle可能检出部分但不是全部通用词在 GroundingDINO 上表现不稳定car. truck. bus. motorcycle. bicycle.各类别都能稳定检出推荐a photo of a car, truck and bus部分类别丢失句子结构可能干扰 DINO 的 grounding 能力关键规律是每个类别用单独的点号隔开不要人为加复杂定状语句。GroundingDINO 的文本编码器对“名词短语”的响应最好你用自然语言描述反而会稀释它的注意力。提示词中尽量加入场景限定词。比如做街景标注时提示词写成pedestrian on the crosswalk. chair on the sidewalk.比直接写person. chair.效果更好因为 GroundingDINO 在复杂场景下容易把小的人影或远处的斑马线误判为目标。3.3 批量跑图与输出解析我设计了一套批量跑图的脚本模板核心思路是每隔几张图自动保存一次结果方便中断续跑。#!/bin/bash # 批量跑 Grounded-SAM 标注脚本图片放在 ./images 中结果输出到 ./labels IMG_DIR./images OUT_DIR./labels mkdir -p $OUT_DIR for img in $IMG_DIR/*.jpg; do echo Processing: $img python grounding_dino_sam_inference.py \ --config GroundingDINO/groundingdino/config/GroundingDINO_SwinT_OGC.py \ --grounded_checkpoint ./weights/groundingdino_swint_ogc.pth \ --sam_h_checkpoint ./weights/sam_vit_h_4b8939.pth \ --input_image $img \ --output_json $OUT_DIR/$(basename $img .jpg).json \ --prompt car. person. traffic light. bicycle. motorcycle. sleep 1 done跑出来的 JSON 里核心字段有两个boxes和masks。boxes 是 xyxy 格式的检测框masks 是 RLE 编码的分割掩膜。注意不要直接用这个 JSON 当数据集还得转换一次。我的习惯是先把 RLE 掩膜解码成 PNG 透明图再转成 COCO JSON这样后道工序的校验工具和训练脚本都能通用。批量跑图的节奏也有讲究。Grounded-SAM 跑单张 1024x1024 的图片在 RTX 3090 上大约需要 2-3 秒一张一张跑问题不大。但如果图很多可以开多进程并行每个进程指定不同的 GPU速度几乎线性提升。跑任务前先随机挑 10 张测试一下推理结果确认提示词没有大问题再全量跑否则 2 万张图跑完才发现类别错位就得全部重来。4. autodistill用主动学习让标注量持续下降4.1 autodistill 的工作原理autodistill 是一个很有意思的框架。它的核心机制是用一个大模型当 teacher自动标注未标记数据然后训练一个小模型当 student。它的思想非常朴素如果一个大模型已经能把任务解决得很好那我何必用昂贵的人力去标注直接让大模型生成标签然后让一个小模型去学习大模型的泛化能力最后在推理阶段用小模型替代大模型速度和成本都能大幅下降。这个框架支持把 Grounded-SAM、YOLO-World 等模型当作 teacher也支持把 YOLOv8、YOLOv5 等模型当作 student。安装非常简单pip install autodistill autodistill-grounded-sam autodistill-yolov84.2 一个典型的主动学习迭代流程我实际跑过的完整流程是这样的初始化准备 5000 张无标注图片。Teacher 标注用 Grounded-SAM 把 5000 张图片全部自动标注导出 COCO JSON。Student 训练用 autodistill 把标注结果转成 YOLOv8 格式训练一个 yolov8n 模型。Student 推理用训练好的小模型对下一批 5000 张图做推理。置信度过滤小模型输出的检测框若置信度高于 0.9直接视为可信标注置信度在 0.5 到 0.9 之间进入人工精修低于 0.5 的大概率是错检或漏检要么删掉要么进人工资重新标注。重复训练把人工修正过的数据合并到训练集训练下一个版本的 student 模型。到第二轮后十之八九的图片已经可以直接用 student 模型的输出不再需要经过 Grounded-SAM 或人工标注成本直线下降。这一步有个非常重要的量化衡指标我建议每次迭代后记录“student 模型自动标注的可信率”。如果第一轮是 60%第二轮升到 80%说明主动学习生效了如果提升很慢大概率是类别体系设计有问题或者标签噪声太大需要回头检查 teacher 的标注质量。4.3 autodistill 的实操经验与回灌机制autodistill 的 API 设计简洁但有个地方容易踩坑默认只支持 maximal 的检测框输出mask 信息会被丢弃。如果后续做实例分割任务需要在 grounded-sam 的模块里额外保留 mask 数据或改用直接调用 Grounded-SAM 底层接口。autodistill 训练出来的标签怎么回灌进 X-AnyLabeling我习惯的做法是autodistill 训练后用 student 模型对未标注图片批量预测输出为 YOLO txt 格式。进入 X-AnyLabeling 前先把 YOLO txt 转成 X-AnyLabeling 支持的标签文件。转换的原理很简单X-AnyLabeling 的标准格式是一个图片对应一个同名.txtYOLO 分割格式或者在labels目录下的 JSON 文件把类别编号和归一化坐标填对就行。在 X-AnyLabeling 里对自动标注结果进行人工修改保存后重新导出成 YOLO 格式回到训练集。我最开始的理解是 autodistill 能完全替代人工校验。但实测后我发现它替代的是“画标注”这个动作替代不了“查缺补漏”这个动作。低置信度的样本永远需要人来看而自动标注的价值是把人从 100% 的工作量压缩到 15%而不是压缩到 0%。5. 实战流程从原始图片到最终可用数据集5.1 设定标签体系标签体系设计直接影响整个标注流程的体验。我在做自动标注项目时总结出一条核心准则类别尽量合并避免过度拆分。比如做车辆检测car和sedan不要拆成两类做动物识别dog和puppy也不要拆。因为 Grounded-SAM 对细粒度的类别区分能力有限拆得太细模型和人都容易混淆标签噪声指数级上升。标签体系设计完成后我建议先在 X-AnyLabeling 里手动标注 50 张图作为“标准答案”。这个标准答案集有三个用途一是验证标签体系是否合理二是用来测试自动标注工具的输出质量三是作为后续人工精修时的参照模板。5.2 数据准备与目录组织数据集目录结构我建议这样组织dataset/ ├── images/ # 原始图片 │ ├── train/ │ ├── val/ │ └── test/ ├── auto_labels/ # 自动标注结果Grounded-SAM / autodistill 输出 │ ├── train/ │ ├── val/ │ └── test/ ├── human_labels/ # 人工精修后的最终标注 │ ├── train/ │ ├── val/ │ └── test/ └── scripts/ # 中间转换脚本图片统一命名规则很重要。我踩过最大的坑是从不同渠道收集的图片文件名可能是中文、包含空格甚至同一张图被重复命名。自动标注脚本基于文件名映射标签一旦文件名搞混后期合并数据时整个数据集直接报废。我的做法是进数据集之前统一改名为 8 位数字 短横线编号比如00000001.jpg彻底规避编码问题。5.3 一次完整的端到端实操演示以下是我这边跑通的一个“零样本标注 主动学习 人工校验”的完整流程记录任务给 8000 张无人机航拍的工地图片标注person. helmet. excavator. truck.四类。第一步Grounded-SAM 自动标注。我写的提示词是person. helmet. excavator. truck.跑完后生成了 8000 个 JSON耗时约 6 小时单卡 RTX 3090。第二步转换格式。写一个 Python 脚本把 JSON 转换成 YOLO 格式过滤掉面积过小的框比如小于 2% 图片面积的目标基本都是误检再输出为 COCO JSON 和 YOLO txt 双份格式。第三步autodistill 训练 student。这个环节我提前把 Grounded-SAM 标注结果转成了 autodistill 的输入格式然后训练 yolov8n大概 20 分钟一个 epoch跑 50 个 epoch得到一个 mAP 50 约 0.65 的小模型。第四步student 模型继续生产。用这个模型对新收集的 5000 张未标注图片推理统计置信度分布。置信度 0.9 的占比约 35%0.5-0.9 占 45%低置信度占 20%。第五步X-AnyLabeling 人工精修。把低置信度的 1000 张图、中置信度的 2250 张图抽样 10% 放进标注工具人工修改再回灌到训练集。这一步用快捷键组合两个人两天就完成了。最终这个 13000 张的数据集人工实际参与精修的只有大概 2600 张图有效人工工时压缩到原先的 20% 左右。5.4 格式转换脚本要点格式转换是数据链路里最容易翻车的环节。三种常见格式的转换关系如下Grounded-SAM 的 JSON包含 xyxy 框与 RLE 掩膜需要解码成 numpy 掩膜数组才能转成其他格式。COCO JSON需要维护一个categories列表并且支持一个目标多标签或遮挡的复杂度适合做实例分割。YOLO txt每行一个目标格式是类ID x_center y_center width height值均为归一化到 0-1 的浮点数。我提供一段我常用的转换脚本能直接把 Grounded-SAM 的检测结果转成 YOLO 分割格式import json import numpy as np import pycocotools.mask as mask_util from pathlib import Path def grounded_sam_json_to_yolo(json_path, class_mapping, out_txt_path, img_w, img_h): with open(json_path, r) as f: data json.load(f) lines [] for item in data[annotations]: category item[category] if category not in class_mapping: continue class_id class_mapping[category] # mask 是 RLE 编码解码为多边形 mask mask_util.decode(item[mask]) ys, xs np.where(mask 0) if len(xs) 0: continue # 计算掩膜的外接多边形这里简化为外接矩形归一化 x1, x2 xs.min(), xs.max() y1, y2 ys.min(), ys.max() box_w, box_h x2 - x1, y2 - y1 x_center (x1 x2) / 2 / img_w y_center (y1 y2) / 2 / img_h w, h box_w / img_w, box_h / img_h lines.append(f{class_id} {x_center:.6f} {y_center:.6f} {w:.6f} {h:.6f}) with open(out_txt_path, w) as f: f.write(\n.join(lines))这段脚本的简化处理是把掩膜变成外接矩形这在大规模自动标注中完全可以接受。如果需要精细分割标签则要输出多边形顶点序列代码量会更大但原理相同先解码掩膜再用cv2.findContours提取多边形轮廓。6. 常见问题与避坑实录6.1 内存爆掉与推理速度慢自动标注流水线最容易崩的环节是 Grounded-SAM 批量推理。SAM 模型非常吃显存ViT-H 在 8GB 显存下基本跑不了 1024 分辨率以上的图会直接 OOM。我的解决思路是降低输入分辨率。对标注任务来说大部分目标在 640 分辨率下依然清晰把图片 resize 到 640x640 后再喂给模型显存占用能降一半以上。开启半精度。fp16 推理在显存占用上提升明显精度损失对于标注任务基本无感。分批处理。不要一次性把几千张图塞进内存而是每处理 100 张输出一次结果中间清理显存缓存。另一个容易忽略的内存问题是 X-AnyLabeling 自身。当一张图片分辨率特别大比如 5000x3000 的航拍图工具加载时会很卡。我的建议是先把大图切瓦片分块标注再合并回整图或者先下采样到 2000 像素再标注。6.2 漏检与误检自动标注结果质量问题漏检和误检永远是自动标注最核心的问题我的处理经验分两层漏检的修正漏检多发生在小目标、遮挡目标和远处目标。处理办法是加跑一遍针对小目标的提示词轮次比如把图片放大 1.5 倍后再跑一次 Grounded-SAM然后合并两次结果。如果还是漏说明是类别本身与背景对比度太低这类样本只能靠人工补。误检的清理误检的典型特征是置信度偏低、目标尺寸偏小或尺寸过大。我在转换脚本里加入了基于面积的过滤规则目标面积占图片面积 0.5% 以下或 95% 以上直接丢弃。这个规则能过滤掉大部分把纹理背景误判成目标的情况。注意过度的面积过滤会把真正的小目标一并删掉。实际项目里我会先跑一个统计脚本输出所有检测框的面积分布看一眼数据分布再设定过滤阈值而不是拍脑袋定 0.5%。6.3 标签管理混乱类别ID与标签名错位这是多人协作时最严重的坑。自动标注输出的类别顺序和 X-AnyLabeling 的类别顺序不一致训练时类别 ID 就会错位看起来模型训练正常实际 ap 计算出来全是零。我的解决办法是用一个统一的classes.txt并且把它固定在数据集根目录所有脚本和工具都从这个文件读类别列表。任何工具、任何脚本、任何中间层都不允许自己另写一份类别清单。这样即使标注过程跨多个平台类别顺序也完全可控。6.4 中文路径与文件编码问题很多标注工具和深度学习框架对中文路径支持不友好Windows 上尤其明显。如果数据集路径里包含中文或特殊字符轻则程序报警告重则直接无法读取图片或保存标注。我的铁律是数据集根目录和所有子目录只用英文字母、数字、下划线。个人头像里那些稀奇古怪的字符就别拿来做数据集了。还有一个我踩过的坑某些自动标注脚本生成的 JSON 里包含 Unicode 转义字符在 Linux 上看是\uXXXX用 Python 读取没问题但用记事本打开就是乱码。遇到这种情况不要手动改文件直接在转换脚本里用ensure_asciiFalse处理输出。6.5 快捷操作反人类重新绑定X-AnyLabeling 允许自定义快捷键。默认的D键既是“智能分割”又是“下一张图”取决于当前是否处于编辑状态这经常让我刚画完一个框就误跳到下一张图。我的解决思路很直接进入设置面板把智能分割改为S把下一张图保留为D这样手指分布的肌肉记忆更舒服。还有一个高效技巧开启“自动保存”后切图时会自动保存当前标注但手动CtrlS仍然保险。因为自动保存偶尔会遇到图片加载失败的情况这时未保存的标注会丢失手动保存能在关键时刻兜底。这套三件套组合的强势之处不在于任何单一工具而在于“大模型自动标注 小模型迭代 人工只处理难点”的循环结构。我在实际项目里最大的感受是技术选型不难难的是把每个环节的数据流打通让标注结果能顺畅地从一个工具流向另一个工具任何一个环节出现格式断层整条流水线就卡死。如果你也想引入自动标注我建议先拿几百张图小规模跑通全流程确认标注质量、成本、工具稳定性都达标后再放心铺开到全量数据。
上一篇/下一篇内容由系统自动关联
返回资讯列表 →