当前位置: 首页 > news >正文

未知物体自动标注流水线

训练目标检测模型需要标注数据。大量的标注数据。而手动绘制边界框,坦率地说,是一项令人痛苦的工作。

打开一张图片。扫描寻找物体。小心翼翼地拖动一个矩形围住它。下一张图片。再下一张。成百上千次。这既乏味又缓慢,令人筋疲力尽,而且你不可避免地会遗漏东西。没有人想做这个。

开放词汇模型——Grounding DINO、SAM3 及其同类——或许能拯救我们。输入"cat"它们就能找到猫。输入"traffic light"它们就能准确定位。那么它们也能自动标注你的物体吗?

如果模型已经知道这个概念,可以。对于开放词汇模型训练词表内的物体,仅文本提示就足以自动生成可用的标注。

但当模型从未见过你的物体时会发生什么?

在这个实验中,我碰巧选择了水下镜头中的虾。将"shrimp"输入 Grounding DINO,你会得到:

"shrimp" → Recall = 0.000 "fish" → Recall = 0.761 "crab" → Recall = 0.843

零。不是低置信度——零检测。单词"shrimp"根本不在模型的词表中。我尝试了 11 个视觉模型的文本和视觉提示模式。没有一个能仅从参考图像可靠地检测到虾。

1、本文涵盖的内容

我构建了一个流水线,仅使用少量参考裁剪图像就能自动标注未知物体。不需要物体名称。不需要微调。不需要迭代训练。

目标不是完全自动化。而是从根本上改变工作的形态

  • 之前:打开每张图片,搜寻物体,从零开始绘制边界框
  • 之后:查看预生成的候选裁剪,点击接受或拒绝
    不再需要搜索。不再需要绘制。只需做出判断。仅这一点就能大幅提高吞吐量。

提前声明:此处展示的结果和技术是针对水下虾的具体情况。不同的物体会有不同的最佳配置。流水线的设计是可定制的——你并行运行多种策略,迭代收敛到最适合你特定物体的方案。

2. 实验设置

2.1 数据集

AAU Brackish Underwater Dataset(CC BY 4.0)——包含六个类别的水下镜头:crab、fish、jellyfish、shrimp、small_fish、starfish。这六个类别都不在 COCO-80 中,使它们成为标准开放词汇检测器真正未知的对象。

目标:shrimp——1,467 张验证图像中的 76 个实例。体型小、半透明,容易在背景中丢失。

2.2 硬件和模型

  • GPU: NVIDIA RTX 5090(32GB VRAM)
  • SAM3: Segment Anything 3(通过 Ultralytics,SAM3SemanticPredictor
  • Grounding DINO v1: 文本引导检测(HuggingFacetransformers
  • Qwen3-VL-8B: 视觉语言模型(用于环境检测)

2.3 设计哲学:不要试图一击命中

标注生成不是实时过程。你创建标签一次,然后可以随意训练模型多少次。不需要优化速度。

相反,并行运行多种方法,比较输出,然后选择最适合你物体的配置。尝试 SAM3 的多个置信度级别。生成一系列提示模板。混合搭配验证方法。查看所有结果,然后决定。

没有单一的方法普遍适用。每个物体都有自己的最佳配置。这种"并行探索 → 交互选择"的思维模式是流水线设计的基础。

3. 基线:11 个模型,零样本

在构建任何东西之前,我对现有的方案进行了基准测试:

两个发现:

  1. 文本提示是唯一可行的路径。所有五种视觉提示方法都彻底失败了。参考图像无法为未知物体完成工作。
  2. 对于已知物体,自动标注已经有效。挑战在于未知物体。

4. 描述性提示:检测你无法命名的东西

这是使其他一切成为可能的洞察。

GDino 不知道"shrimp"。但它理解描述:

"shrimp" → R = 0.000 ❌ "underwater creature" → R = 0.553 ★ "small translucent creature" → R = 0.368 ★

模型无法在其词表中查找"shrimp",但它可以将"underwater creature"的视觉概念与它在图像中看到的内容进行匹配。GDino 的文本编码器在预训练期间学会了将描述性短语与视觉特征关联起来——它只是从未遇到过"shrimp"这个特定的词。

4.1 自动化提示生成

用户不应该猜测哪些描述有效。我使用 VLM(Qwen3-VL-8B)分析参考裁剪并自动检测环境:

参考裁剪 + 完整图像 → VLM → "underwater" → 模板: "underwater creature", "underwater animal", "underwater organism"

为什么用固定模板而不是自由形式的 VLM 描述?我将在第 6 节中详细说明,但简短版本是:形容词会破坏 GDino 的区分能力。

4.2 发现是一切的起点

描述性提示现在可以找到虾。但它们也会找到其他一切。GDino 在整个数据集上返回超过 9,000 个检测,其中大约 70 个是真正的虾。

关键在于:你无法标注你找不到的东西。无论多么精确的过滤器,都无法挽救从未进入候选池的真实物体。这使得 Discovery——候选阶段捕获的 GT 物体比例——成为首要优先级。

误报总是可以稍后处理。遗漏的物体就永远丢失了。

5. 关键转变:先分割,再分类

我尝试了所有能想到的方式来过滤 GDino 的全图检测结果——CLIP 余弦相似度、置信度差值、面积过滤器、VLM 验证、SVM。最好的结果也只能让一半的标签正确。

突破来自于完全重新定义问题。

5.1 旧方法:检测 → 过滤(失败)

完整图像 → GDino "underwater creature" → 9,145 个检测 (TP=69, FP=9,076) → 过滤 → 最好结果: 一半标签是错误的

GDino 的全图检测结果很嘈杂:重叠的框、一个框中有多个物体、纯背景。试图在那堆混乱中区分好坏极其困难。

5.2 新方法:分割 → 分类(有效)

完整图像 → SAM3 分割 → ~10K 干净的片段(1 个裁剪 = 1 个物体) → 每个裁剪 → GDino "underwater creature" → 分类分数 → 阈值 → 高质量标注 ★★

为什么这有效:SAM3 生成不重叠的掩码,具有干净的物体边界。每个裁剪只包含一个东西。此时 GDino 不再做嘈杂的检测——它在做二元分类:"这个裁剪是水下生物吗?"将 TP 与 FP 分离变得容易得多。

5.3 SAM3 配置很重要

两个产生显著差异的设置:

1. 领域特定的类别词至关重要。

SAM3 只使用 ["object"]: Recall = 53.9% ❌ SAM3 使用 ["animal", "creature", "object"]: Recall = 78.9% ✅

SAM3 是一个视觉语言模型。像"animal"这样广泛的类别词会以"object"无法做到的方式激活对生物实体的注意力。这是一个生物学特定的设置——其他领域需要不同的类别词。

2. 降低置信度可以捕获更多 TP。

SAM3 conf = 0.15: Recall = 60.5%, TP = 124 SAM3 conf = 0.10: Recall = 80.3%, TP = 215 (+73%)

更多的误报随之而来,但下游的 GDino 分类步骤可以处理这些。最佳阈值取决于物体——这就是为什么你要运行多个级别进行比较。

from ultralytics.models.sam.predict import SAM3SemanticPredictor predictor = SAM3SemanticPredictor(overrides={ "model": "sam3.pt", "conf": 0.10, "imgsz": 1008 }) predictor.prompts = {"text": ["animal", "creature", "object"]} results = predictor(image_path)

(注意:SAM3 的自动分割模式在 Ultralytics API 中不受支持。你需要使用SAM3SemanticPredictor配合文本提示。)

6. 完全自动化:VLM 应该做什么(和不应该做什么)

分割→分类流水线有效——但我需要手动选择提示。要真正可复用,一切都需要自动运行。

6.1 形容词陷阱

第一次尝试:让 VLM 生成丰富的描述性提示,如"smooth undersea item"或"pale round organism"。听起来合理。但针对 9,318 个 SAM3 裁剪测试后:

提示 GDino 区分度 (TP vs FP 平均分数差距) "underwater animal" 0.144 ★★★ 2 词模板 "underwater creature" 0.136 ★★★ 2 词模板 "pale underwater animal" 0.138 +1 形容词 "small underwater creature" 0.122 +1 形容词 "underwater smooth round organism" 0.034 ❌ +3 形容词 (差 4 倍!)

你添加的形容词越多,GDino 在区分 TP 和 FP 方面就越差。为什么?GDino 的文本-图像匹配是一种粗粒度的类别判断。"smooth"和"round"这样的词同样匹配目标裁剪和背景裁剪,缩小了差距。

VLM 的最佳用途:只检测环境。

VLM → ENV = "underwater" → 模板: "underwater creature", "underwater animal", "underwater organism"

这是从虾的实验中得出的发现——形容词可能对其他物体有用。这正是为什么你生成多个提示候选,让 GDino 的区分性筛选自动排名,然后根据数据选择最佳方案。

6.2 SAM3 提示污染问题

一个更微妙的问题:VLM 生成的提示如"smooth undersea item"与模板提示一起被传递给 SAM3。它们不仅在分类上失败了——它们还主动误导了 SAM3 的分割:

SAM3 使用基础 + VLM 提示: TP = 173 SAM3 使用基础 + 仅模板提示: TP = 215 (+24%)

修复方法:只将模板提示传递给 SAM3。将其他一切保留给 GDino 分类步骤。

6.3 完全自动化结果

自动化流水线在零人工干预的情况下匹配了手动版本的性能。整个流程——从参考裁剪到标注数据——无需人工参与即可运行。

7. 发现:捕获 96% 的真实标注

流水线自动化后,下一个问题是:有多少 GT 物体实际进入了候选池?这就是 Discovery 率,它为下游一切设定了上限。

找不到的东西就无法标注。Discovery 是硬限制。

7.1 SAM3 + GDino 互补

SAM3 在 conf=0.10 时捕获 61/76 个 GT 物体。但在全图上直接运行 GDino 会捕获一些 SAM3 遗漏的物体——两个模型以不同的方式失败:

仅 SAM3: 61/76 GT (80.3%) + GDino 互补: 73/76 GT (96.1%) ★ +16 个百分点

这将 96% 的 GT 物体放入候选池。这就是我们能标注的上限。

权衡:GDino 互补增加了 4,241 个额外候选,其中只有 18 个(0.4%)是真正例。更多的候选,但几乎都是噪音。如何处理这些取决于你的验证策略。

7.2 标注质量

如果边界框是垃圾,Discovery 就毫无意义。它们不是:

  • 与 GT 的平均 IoU: 0.799
  • IoU ≥ 0.7 的 GT 物体: 86%
    我目视检查了所有 73 张叠加图像。边界框紧密跟随虾的轮廓。像素级精确不是目标——重要的是人类审阅者是否会按原样接受它们。他们会。

7.3 GDino 互补的权衡

是否使用 GDino 互补取决于物体:

  • 如果 SAM3 单独已经给你足够的 Discovery(比如说,90%+),跳过互补。它只会增加 FP。
  • 如果 SAM3 不够(本例中 80% → 96%),互补是重大提升。
    同样,不要预先锁定选择——两种方式都运行并比较。

8. 验证:从噪音中分离信号

Discovery 将 96% 的 GT 放入候选池。接下来是排序。

8.1 自动化验证尝试

我想自动过滤到 TP。尝试了几种方法:

对于虾,完全自动化验证碰壁了。但这是虾特定的结果。对于视觉上更具特色的物体,或 CLIP 覆盖更好的领域,自动验证可能效果更好。

8.2 GDino 分数的更好用途

GDino 分数不够可靠用于自动过滤,但它们在另一方面很出色:优先排序人工审阅。

高分候选更可能是 TP。低分候选大多是 FP。按分数排序,从顶部开始审阅,在有足够标签时停止。

9. 不是替代人类——而是让他们更快

这个流水线并没有完全自动化标注。

但这不是正确的问题。问题不是"它能替代人类吗?“——而是"它能让人类快多少?”

9.1 之前 vs 之后

没有流水线(传统标注):

  • 在查看器中打开 1,467 张水下图像

  • 扫描每张图片寻找虾(体型小、半透明、容易遗漏)

  • 从零开始为每个找到的绘制边界框

  • 重复。遗漏一些。失去注意力。犯错。
    有流水线

  • 运行流水线

  • 审阅预生成的候选裁剪,边界框已经绘制好

  • 接受或拒绝每个候选

  • 导出已接受的标签作为标注数据
    认知负荷完全不同。不需要搜索物体——流水线已经找到了 96%。不需要绘制框——IoU = 0.80 的边界框已经准备好了。你只需做出判断。

这不是自动化的失败。而是人类和 AI 之间正确的分工。流水线处理重活——检测和候选生成。人类处理简单的部分——决定是或否。

10. 流水线概览:定制化轴

流水线有三个阶段,每个阶段都有一个你应该针对每个物体调整的旋钮。

阶段 1: 提示生成 ┌──────────────────────────────────────────────────┐ │ VLM → 环境检测 → 模板提示 │ │ │ │ 定制化轴: 类别名词 │ │ 生物学: creature, animal, organism │ │ 工业: part, component, piece (未测试) │ │ 医学: lesion, tissue, mass (未测试) │ └──────────────────────────────────────────────────┘ 阶段 2: 发现 ┌──────────────────────────────────────────────────┐ │ SAM3 主要分割 │ │ + GDino 互补检测(可选) │ │ │ │ 定制化轴: 互补开关 │ │ SAM3 足够 → 互补关闭 (更少 FP) │ │ SAM3 不足 → 互补开启 (Discovery ↑) │ └──────────────────────────────────────────────────┘ 阶段 3: 验证 ┌──────────────────────────────────────────────────┐ │ GDino 分类评分 → 审阅 / 自动接受 │ │ │ │ 定制化轴: 验证策略 │ │ 高 GDino 差距 → 倾向自动接受 │ │ 低 GDino 差距 → 倾向人工审阅 │ └──────────────────────────────────────────────────┘ 输出 ┌──────────────────────────────────────────────────┐ │ 标注数据(边界框 + 类别名称) │ └──────────────────────────────────────────────────┘

10.1 并行探索 → 交互选择

你无法提前知道最佳配置。相反:

  • 以多个置信度级别运行 SAM3(0.10、0.12、0.15)——比较 TP/FP 权衡
  • 生成多个提示模板——让 GDino 的区分性筛选自动排名
  • 尝试有和没有 GDino 互补两种方式——权衡 Discovery 与 FP 数量
  • 查看结果,然后选择策略——GDino 差距告诉你使用哪种验证方法
    所有这些都是离线运行的。单次流水线运行就为你提供了做出明智决策所需的一切。从那里,你根据数据对你特定物体显示的内容进行交互式调优。

不同的物体——比如装配线上的缺陷检测——会有不同的最佳设置。这是预期的。流水线为你提供了找到它的工具。

10.2 流水线需要什么

输入:1-3 张参考裁剪图像 + 1 张完整场景图像 + 类别名称

不需要

  • 模型已知的物体名称
  • 模型微调
  • 迭代训练循环
  • 实时推理
  • 大量标注数据集

11. 要点

1. 未知物体需要不同的方法。开放词汇检测对于模型训练词表外的物体会失败。描述性提示(“shrimp” → “underwater creature”)弥合了这个差距。

2. 先分割,再分类。在全图上运行 GDino 使过滤几乎不可能。先用 SAM3 分割,然后用 GDino 分类各个裁剪,区分能力会大幅提升。

3. 让 VLM 检测环境——仅此而已。让 VLM 生成大量形容词的描述会降低 GDino 的区分能力。最佳提示就是"{environment} {category noun}。"不过,这是虾特定的发现,可能不适用于每个物体。

4. Discovery 设定上限。你无法标注你找不到的东西。SAM3 + GDino 互补捕获了 96% 的 GT 物体,边界框质量为 IoU = 0.80——完全可用于标注。

5. 不要试图一击命中。并行运行多个置信度级别、提示变体和互补设置。交互式审阅结果,收敛到适合你物体的最佳配置。标注是离线过程——花掉那些计算资源。

6. 不要替代人类——让他们更快。从零开始绘制边界框 → 对预生成的候选进行接受/拒绝。仅这一转变就大幅降低了标注成本和认知负荷。

7. 每个物体的结果都不同。本文中的所有内容都是针对虾调优的。不同的物体需要不同的设置。定制化轴——类别名词、Discovery 策略、验证策略——正是为此而存在的。


原文链接:未知物体自动标注流水线 - 汇智网

http://www.jsqmd.com/news/674101/

相关文章:

  • 别再死记硬背UNet结构了!用PyTorch手把手拆解那个经典的U型编码-解码器
  • 暗黑破坏神2存档编辑器终极指南:5分钟打造你的完美游戏角色
  • 【微软MVP亲测】C# 14原生AOT×Dify客户端:如何用1个.csproj配置砍掉63% Azure Functions账单?
  • 如何将微信读书笔记转化为结构化知识资产:Obsidian Weread插件深度指南
  • 电动车续航计算:优化数据读取
  • Blazor组件生命周期陷阱大全,92%开发者踩过的6类内存泄漏+服务注入失效问题(含.NET 9 Preview 5验证报告)
  • 《应届生勇闯AI大厂都需要哪些技能?》(AI核心岗)
  • Kubernetes 如何部署微服务?
  • Dify多租户权限治理全攻略(从失控到可控的90天演进实录)
  • 终极Windows任务栏美化指南:RoundedTB让你的桌面焕然一新
  • Dify 2026边缘部署全链路拆解(含YAML模板+离线包校验SHA256值)
  • 爱毕业(aibiye)为数学建模论文提供高效复现与智能排版的一体化解决方案
  • 面向药品自动识别的YOLO26检测系统:Cipro/Ibuphil/Xyzall等4种药品及4种颜色联合检测(项目源码+数据集+模型权重+UI界面+python+深度学习+远程环境部署)
  • 靠谱的东莞高新技术企业认定培训公司
  • 基于YOLOv5的自动驾驶实时目标检测优化实战:从模型剪枝到TensorRT部署
  • JavaScript 中数组引用陷阱与“破纪录”问题的正确解法
  • 广州GEO优化多少钱?2026本地报价+真实行情,避开低价陷阱
  • 缓存基础概念与原理
  • 吊车地基承载力计算全攻略:从地勘报告到路基箱铺设,一文讲透
  • 基于泰勒展开的YOLOv5通道剪枝重要性评估:理论与实践
  • 面向测试工程师的机器学习调试实战:深入解析损失函数优化
  • 避坑指南:大华海康SDK回调流如何用JavaCV稳定推流到ZLMediaKit?
  • 全球首个龙虾模型:GLM--Turbo(手把手安装、配置、使用教程)来了!
  • Harness 中的推理步数预算:防止无限循环
  • 00华夏之光永存:华为黄大年茶思屋难题揭榜第10期(题目篇)—— 7道云原生核心难题全解析
  • python gitlab-ci
  • 【2026政企采购强制标准】:Blazor离线PWA能力、FIPS 140-2加密集成、GDPR合规审计链——3步通过等保三级验收
  • Godot 4中实现第三人称相机的技巧与实例
  • 模型加载耗时4.2秒?教你用.NET 11 MemoryMappedFile预热+Lazy<T>缓存,在300ms内完成冷启动(已落地券商核心系统)
  • 回归显见:在亚马逊,为何“最简单、最本质”的价值是抵御复杂化陷阱的终极武器