尧图精选

X-AnyLabeling+autodistill+Grounded-SAM:半自动数据标注流水线实战

🕒 发布时间:2026/10/2 14:35:43 📁 来源:尧图网络
数据标注这件事干过的人都知道它有多磨人。一个中等规模的检测项目几千张图起步纯手工框下来眼睛花、手腕酸标注质量还随着疲劳程度直线下降。更别提模型迭代时每加一个新类别就得重新返工一批数据。这两年自动标注和数据飞轮的概念被反复提起但真正落到实操层面能把工具链串起来跑通的人并不多。我最近完整走了一遍X-AnyLabeling autodistill Grounded-SAM的组合流程从零标注冷启动到半自动批量产出踩了不少坑也总结出一套相对稳定的打法。这篇就把整个链路拆开讲清楚这套组合各自解决什么问题、怎么装、怎么配、怎么串起来跑以及哪些环节最容易翻车。不管你是刚接触标注的新手还是想给团队搭一套半自动流水线的老手都能从里面找到能直接抄的部分。1. 为什么是这三个工具凑一起而不是单用一个1.1 三个工具各自的定位与能力边界先把这三个东西的角色理清楚不然很容易混着用最后发现哪个都没用到位。X-AnyLabeling是一个带图形界面的标注客户端本质上是 LabelMe 那类工具的进化版但它内置了 AI 辅助能力——你可以加载检测、分割、姿态等各类模型让模型先给出预标注结果人工只需要做修正。它的强项是交互式标注和人工精修适合作为整个流程的最后一公里。autodistill是一个自动蒸馏框架核心思路是用一个大模型基础模型去给未标注数据打伪标签然后用这些伪标签训练一个小模型目标模型。它解决的是批量、无人值守的自动标注问题适合处理海量图片的初筛。Grounded-SAM是把 Grounding DINO 和 SAM 拼在一起的组合模型。Grounding DINO 负责用文字描述找到目标框SAM 负责把框内的物体精确分割出来。它解决的是开放词汇检测与分割问题——你不需要预先训练直接输入personcardefect这类文本提示它就能把对应目标框出来甚至抠出来。把三者串起来逻辑就通了Grounded-SAM 提供零样本的检测分割能力autodistill 用它批量生成伪标签并蒸馏出轻量模型X-AnyLabeling 则作为人工介入的终端加载蒸馏后的模型做交互式精修。这是一条从零标注到高质量数据集再到可迭代模型的完整数据飞轮。1.2 单用某一个工具会卡在哪我一开始图省事只用了 X-AnyLabeling 加载一个现成的检测模型。结果发现两个问题一是模型只认它训练过的类别我项目里有些特殊目标它根本不认识二是每张图都要等模型推理几千张图跑下来人工等待的时间比标注本身还长。后来单独试 autodistill批量跑确实快但它生成的伪标签质量参差不齐尤其是小目标和密集目标框得歪歪扭扭直接拿去训练会把模型带偏。而 Grounded-SAM 单独用精度不错但它是一问一答式的你给一个提示它标一类面对几十个类别、几千张图手动一张张跑不现实。所以这三个工具的关系不是替代而是互补Grounded-SAM 负责从无到有地认识新类别autodistill 负责从少到多地批量铺开X-AnyLabeling 负责从粗到精地人工兜底。缺了任何一环流程都会在某个环节卡住。1.3 数据飞轮的完整闭环长什么样所谓数据飞轮说白了就是让数据自己滚起来。具体到这套工具链闭环是这样的拿一批完全没标注的原始图用 Grounded-SAM 配合文本提示生成第一批伪标签把这批伪标签喂给 autodistill蒸馏出一个轻量检测模型在 X-AnyLabeling 里加载这个轻量模型对剩余图片做预标注人工快速修正修正后的高质量数据再拿去训练模型变强下一轮预标注更准循环往复人工介入的比例越来越低。这个闭环里第一轮的伪标签质量决定了整个飞轮能不能转起来。如果第一轮错得离谱后面全是垃圾进垃圾出。这也是为什么 Grounded-SAM 这一环特别关键——它的零样本能力直接决定了冷启动的质量上限。2. 环境搭建那些文档里不会写的坑2.1 依赖版本冲突是最大的拦路虎这三个工具对 Python 和 CUDA 版本的要求并不完全一致装的时候最容易出问题的就是依赖冲突。我实测下来比较稳的组合是 Python 3.10 CUDA 11.8 PyTorch 2.1.x。Python 3.11 及以上在装某些分割库时会遇到编译问题3.9 又偏老部分新特性用不了。建议直接用 conda 建独立环境别在系统环境里折腾conda create -n autolabel python3.10 -y conda activate autolabel装 PyTorch 的时候一定要去官网查对应 CUDA 版本的安装命令别直接pip install torch那样装到的可能是 CPU 版本跑起来慢到怀疑人生。装完用下面这行验证import torch print(torch.__version__) print(torch.cuda.is_available())如果cuda.is_available()返回 False说明装成 CPU 版了卸载重装。2.2 Grounded-SAM 的权重下载与目录结构Grounded-SAM 需要两个权重Grounding DINO 的权重和 SAM 的权重。这两个文件加起来好几个 G下载慢是常态。我的经验是提前用下载工具挂后台下别等到跑代码时现下。目录结构建议这样组织后面配置路径时不容易乱project/ ├── weights/ │ ├── groundingdino_swint_ogc.pth │ └── sam_vit_h_4b8939.pth ├── data/ │ ├── raw/ # 原始未标注图 │ └── labeled/ # 标注结果 └── configs/SAM 的权重有好几个版本vit_h精度最高但最吃显存vit_b最轻量。如果你显存只有 8G建议先用vit_b跑通流程确认没问题再换大的。我一开始硬上vit_h结果显存爆了排查半天才发现是权重选大了。2.3 X-AnyLabeling 的安装方式选择X-AnyLabeling 提供了两种安装方式一种是直接下打包好的可执行文件双击就能用另一种是从源码装。如果你只是想快速用起来直接下可执行文件最省事。但如果你需要自定义模型、改源码那就得从源码装。从源码装的话注意它的依赖里有些包版本卡得比较死建议单独建一个环境别和 autodistill 共用否则容易打架。我试过共用一个环境结果 X-AnyLabeling 起不来报了一堆 Qt 相关的错最后分开环境才解决。提示X-AnyLabeling 在 Linux 下跑需要图形界面支持如果是纯命令行的服务器得配好 X11 转发或者用 VNC否则界面起不来。快捷键方面常用的有 W 画框、E 编辑、D 下一张、A 上一张熟练之后效率能提升不少。3. 用 Grounded-SAM 做零样本冷启动3.1 文本提示词怎么写才准Grounded-SAM 的核心是文本提示提示词写得好不好直接决定检测结果。这里有几个实操经验第一用英文且用具体名词。Grounding DINO 是在英文语料上训练的中文提示效果会打折扣。而且要用具体的类别名比如 traffic light 而不是 lightsafety helmet 而不是 hat。第二多个类别用点号分隔。Grounded-SAM 的提示格式是category1 . category2 . category3注意中间的点号两边要有空格。我一开始没加空格结果它把整句话当成一个类别什么都没检测出来。第三框阈值和文本阈值要调。box_threshold控制检测框的置信度门槛text_threshold控制文本匹配的严格程度。默认值往往偏保守检测不全。我的经验是box_threshold从 0.3 起调text_threshold从 0.25 起调根据实际效果微调。阈值太低会引入大量误检太高又漏检需要拿几张典型图试出来。3.2 批量推理的脚本化改造Grounded-SAM 官方给的是单张图的 demo实际项目里必须改成批量。核心思路就是遍历文件夹对每张图跑一遍推理把结果存成标注格式。下面是一个简化版的批量脚本骨架import os import cv2 import torch from groundingdino.util.inference import load_model, predict from segment_anything import sam_model_registry, SamPredictor # 加载模型 grounding_model load_model(configs/GroundingDINO_SwinT_OGC.py, weights/groundingdino_swint_ogc.pth) sam sam_model_registry[vit_b](checkpointweights/sam_vit_b_01ec64.pth) sam.to(devicecuda) predictor SamPredictor(sam) TEXT_PROMPT person . car . dog BOX_THRESHOLD 0.3 TEXT_THRESHOLD 0.25 raw_dir data/raw out_dir data/labeled os.makedirs(out_dir, exist_okTrue) for img_name in os.listdir(raw_dir): img_path os.path.join(raw_dir, img_name) image cv2.imread(img_path) image_rgb cv2.cvtColor(image, cv2.COLOR_BGR2RGB) boxes, logits, phrases predict( modelgrounding_model, imageimage_rgb, captionTEXT_PROMPT, box_thresholdBOX_THRESHOLD, text_thresholdTEXT_THRESHOLD, ) # 用 SAM 精修每个框 predictor.set_image(image_rgb) # ... 后续把 boxes 转成 SAM 需要的格式逐个分割 # ... 保存为 json 或 txt 标注这段代码的关键在于Grounded DINO 给出的框只是粗略定位用 SAM 再分割一遍能得到像素级的掩码质量提升明显。但 SAM 分割比较慢如果只是要检测框可以跳过 SAM 直接存框速度快很多。3.3 冷启动阶段的质量把控第一轮伪标签出来之后千万别直接拿去训练。一定要人工抽检一批看看误检和漏检的情况。我一般会随机抽 50 到 100 张逐张看统计一下几类问题问题类型典型表现处理方式漏检目标存在但没框出来降低 box_threshold或补充提示词误检框到了背景或其他物体提高阈值或换更具体的提示词框不准框偏大偏小用 SAM 精修或人工修正类别混淆把 A 类标成 B 类检查提示词是否有歧义抽检之后如果整体准确率能到 70% 以上就可以进入下一环。如果低于 50%说明提示词或阈值有问题得回去调别硬着头皮往下走。4. autodistill 蒸馏把大模型的能力压缩进小模型4.1 蒸馏的基本原理与为什么值得做蒸馏这个词听起来玄乎其实逻辑很朴素大模型老师能力强但跑得慢、吃资源小模型学生跑得快但能力弱。蒸馏就是让大模型给大量数据打标签再用这些标签去训练小模型让小模型学会大模型的判断方式。为什么值得做因为 Grounded-SAM 虽然强但它推理一张图要好几秒几千张图跑下来就是几个小时。而蒸馏出来的小模型比如 YOLO 系列推理一张图只要几十毫秒速度快几十倍。一旦蒸馏完成后续所有批量预标注都可以用这个小模型效率天差地别。autodistill 的价值就在于它把这套流程封装好了你只需要指定用哪个基础模型和训练哪个目标模型中间的伪标签生成、数据格式转换、训练调用它都帮你串起来。4.2 配置 autodistill 对接 Grounded-SAMautodistill 支持多种基础模型对接 Grounded-SAM 需要装对应的扩展包。基本用法是这样from autodistill_grounded_sam import GroundedSAM from autodistill.detection import CaptionOntology from autodistill_yolov8 import YOLOv8 # 定义本体文本提示到类别名的映射 ontology CaptionOntology({ person: person, car: car, dog: dog, }) # 基础模型 base_model GroundedSAM(ontologyontology) # 目标模型 target_model YOLOv8(yolov8n.pt) # 一键蒸馏 target_model.train( ./data/raw, epochs50, imgsz640, )这里最关键的是CaptionOntology的配置。左边是给 Grounded-SAM 的文本提示右边是你数据集里的类别名。两者可以不一样比如提示写 safety helmet类别名写 helmet这样映射更灵活。4.3 蒸馏过程中的参数取舍蒸馏训练本质就是一次普通的目标检测训练但有几个参数值得特别注意epochs 不要设太大。因为伪标签本身有噪声训练太久容易过拟合到噪声上。我一般设 50 到 100 轮看验证集指标早停。imgsz 要和实际推理尺寸一致。如果你后续推理用 640训练就用 640别训练用 1280 推理用 640那样精度会掉。数据增强别开太猛。伪标签的框本身可能就不太准再叠加剧烈的几何变换噪声会被放大。Mosaic、MixUp 这类强增强建议先关掉等模型稳定了再逐步开。类别不平衡要处理。如果某些类别样本特别少蒸馏出来的模型对这些类别会很弱。可以在 autodistill 生成伪标签后手动检查一下各类别数量少的类别补充一些原始图重新生成。注意蒸馏出来的模型只认识你本体里定义的类别它不具备 Grounded-SAM 的开放词汇能力。所以蒸馏前一定要把类别列表定清楚后期加类别就得重新蒸馏。5. X-AnyLabeling 交互式精修人工介入的正确姿势5.1 加载自定义模型做预标注X-AnyLabeling 支持加载自定义模型这是它区别于普通标注工具的核心。把上一步蒸馏出来的 YOLO 模型配置进去打开图片时它就会自动跑一遍推理把预测框显示出来你只需要拖拽修正。配置模型需要在设置里指定模型路径和配置文件。YOLO 系列的配置相对简单指定.pt权重和类别文件即可。加载成功后每张图打开时会自动预标注人工修正的工作量比纯手工小得多。这里有个效率技巧批量预标注和人工修正分开做。先用模型把所有图跑一遍结果存下来然后再人工逐张过。这样避免了打开一张等一次推理的等待人工修正时可以连续操作节奏更顺。5.2 快捷键与批量操作提效X-AnyLabeling 的快捷键设计得比较合理熟练之后效率提升明显。常用的几个W画矩形框E编辑当前选中的框D下一张A上一张Ctrl S保存Delete删除选中的框批量操作方面它支持复制上一张的标注功能对于连续帧或者相似场景的图片特别有用。比如视频抽帧出来的图相邻帧目标位置变化很小直接复制上一张的标注再微调比重新画快得多。另外它的自动保存建议打开避免手滑关掉没保存。我踩过一次坑标了半小时没保存软件崩了全白干。5.3 人工修正的质量标准人工修正不是随便拖拖框就完事得有个标准不然修出来的数据质量参差不齐。我的经验是定几条硬规则框要贴紧目标边缘不留大空隙也不切掉目标的一部分遮挡目标按可见部分标注如果遮挡超过 70%考虑标为忽略或直接不标密集目标逐个标不要用一个大框圈一堆类别判断有疑问的标记为待定别硬猜后期统一处理。这些规则最好在团队里统一不然不同人标出来的数据风格不一致训练时反而添乱。6. 串起来跑完整流程的编排与踩坑记录6.1 从原始图到可用数据集的完整命令流把前面几环串起来一个完整的批次处理流程大概是这样原始图放进data/raw跑 Grounded-SAM 批量脚本生成第一轮伪标签到data/labeled_v1人工抽检data/labeled_v1调阈值和提示词直到质量达标用 autodistill 基于data/raw和本体配置蒸馏出 YOLO 模型在 X-AnyLabeling 里加载蒸馏模型对data/raw做预标注人工逐张修正结果存到data/labeled_final用data/labeled_final训练正式模型进入下一轮迭代。这个流程里第 2 步和第 4 步都是自动的可以挂后台跑。真正耗人工的是第 6 步但因为有了预标注工作量比纯手工小很多。6.2 我踩过的三个典型坑坑一路径里有中文或空格。Grounded-SAM 和 autodistill 底层有些库对路径处理不严谨路径里有中文或空格会报莫名其妙的错。解决办法很简单所有路径用英文别带空格。坑二显存没释放导致 OOM。批量推理时如果每张图都重新加载模型显存会越占越多最后爆掉。正确做法是模型只加载一次循环里复用。如果还是爆就在循环里定期torch.cuda.empty_cache()。坑三伪标签格式不统一。Grounded-SAM 输出的格式和 autodistill 期望的格式可能不一致直接对接会报错。中间需要写个转换脚本把坐标格式、类别索引对齐。这个转换脚本虽然简单但一定要写别指望两个工具能无缝对接。6.3 数据飞轮转起来之后的收益跑通第一轮之后后面的迭代会越来越轻松。我实测下来第一轮纯冷启动人工修正比例大概在 60% 左右第二轮用蒸馏模型预标注人工修正比例降到 30%第三轮之后基本稳定在 15% 到 20%。也就是说同样的数据量人工成本能降到原来的三分之一甚至更低。更重要的是这个流程是可复用的。换一个新项目只要改一下本体配置和提示词整套流程直接套用冷启动时间从几天缩短到几小时。这才是数据飞轮真正的价值——不是省一次标注的钱而是把标注这件事变成可积累、可复用的能力。7. 几个容易被忽略的细节和进阶方向7.1 标注格式转换的通用思路不同工具用的标注格式不一样COCO、YOLO、LabelMe 各有各的结构。与其每次手写转换脚本不如写一个通用的转换函数库把常见格式之间的互转都封装好。核心就是搞清楚每种格式的坐标表示方式COCO 用[x, y, width, height]绝对坐标YOLO 用[x_center, y_center, width, height]归一化坐标LabelMe 用多边形点集。搞清楚了转换就是纯数学。7.2 主动学习让飞轮转得更聪明基础的飞轮是全量预标注 全量人工修正但更聪明的做法是主动学习——只挑模型最不确定的样本让人工标。比如模型置信度在 0.4 到 0.6 之间的样本说明模型拿不准这些样本的标注价值最高。X-AnyLabeling 支持按置信度筛选可以优先处理这些难样本用更少的人工获得更大的模型提升。7.3 团队协作时的版本管理如果是多人协作标注版本管理很重要。建议每批标注数据都打上版本号记录用了哪个模型、哪套提示词、哪些人参与。这样出问题时能追溯模型效果变化时也能定位是哪批数据导致的。别嫌麻烦等数据量上来了没有版本管理会乱成一锅粥。我个人在实际操作中的体会是这套工具链最大的价值不在于某个单点工具多强而在于它们组合起来形成了一条可迭代的流水线。刚开始搭环境、调参数确实费劲但一旦跑通后面每个新项目的冷启动都会变得非常轻松。真正需要花心思的是本体定义和提示词设计这两个环节——它们决定了自动标注的质量上限也是目前还很难完全自动化的部分。把这两块打磨好剩下的就是让飞轮自己转起来。
上一篇/下一篇内容由系统自动关联 返回资讯列表 →