3. 数据集标注(上)

做目标检测,数据标注是绕不开的一步。很多人觉得标注就是画框,没什么技术含量。其实不然。我见过不少项目,模型训练出来效果差,回头一查,标注数据一塌糊涂。今天我们就来聊聊标注这件事。

核心观点:标注质量直接决定模型上限。算法再牛,也救不了垃圾标注。

3.1 标注工具选型:为什么我推荐LabelImg

市面上标注工具有很多,LabelImg、LabelMe、CVAT、RectLabel……我个人习惯用LabelImg。原因很简单:轻量、免费、跨平台、上手快。你不需要折腾服务器,下载就能用。

工具 平台 输出格式 适合场景
LabelImg Windows / macOS / Linux Pascal VOC / YOLO 小团队、个人项目
LabelMe Web / 本地 JSON 语义分割、多边形标注
CVAT Web(需部署) 多种格式 团队协作、大规模标注
RectLabel macOS Pascal VOC / YOLO mac用户、付费需求

如果你只是做YOLO目标检测,LabelImg完全够用。我在项目中用过CVAT,功能确实强大,但部署和维护成本高。对于课程里的实战项目,LabelImg是最佳选择。

3.2 LabelImg安装与使用

3.2.1 安装步骤

LabelImg的安装方式取决于你的操作系统。我建议用pip安装,最省事。

# 安装依赖
pip install pyqt5 lxml

# 安装LabelImg
pip install labelImg

# 启动
labelImg

如果你在macOS上遇到权限问题,试试用homebrew:

brew install labelImg

Windows用户可以直接下载exe安装包,或者用Anaconda环境安装。我记得有一次在Windows上装了半天,最后发现是Python版本不兼容。嗯,这里要注意:LabelImg对Python 3.6-3.9支持最好,3.10以上可能会有小问题。

3.2.2 界面与基本操作

启动后你会看到一个简洁的界面。左边是工具栏,中间是图片显示区,右边是标签列表。操作流程很简单:

  1. 打开图片目录:点击「Open Dir」选择存放图片的文件夹
  2. 设置保存目录:点击「Change Save Dir」选择标注文件存放位置
  3. 开始标注:点击「Create RectBox」或按快捷键 W,在目标上拖拽画框
  4. 输入标签:画完框后弹出对话框,输入类别名称
  5. 保存:按 Ctrl+S 或点击「Save」
  6. 下一张:按 D 切换到下一张图片

小技巧:LabelImg支持快捷键操作。我习惯左手键盘(W画框、D下一张、A上一张、Ctrl+S保存),右手鼠标。这样标注效率能提升30%以上。

3.3 Pascal VOC格式详解

LabelImg默认输出Pascal VOC格式,也就是XML文件。这个格式在目标检测领域非常经典,很多框架都支持。

3.3.1 文件结构

一个标准的Pascal VOC数据集目录结构是这样的:

VOCdevkit/
  VOC2007/
    JPEGImages/        # 存放原始图片
    Annotations/       # 存放XML标注文件
    ImageSets/
      Main/            # 存放训练/验证/测试集划分文件
        train.txt
        val.txt
        trainval.txt
        test.txt

3.3.2 XML文件解析

我们来看一个实际的XML标注文件:

<annotation>
  <folder>VOC2007</folder>
  <filename>000001.jpg</filename>
  <source>
    <database>MyDataset</database>
  </source>
  <size>
    <width>500</width>
    <height>375</height>
    <depth>3</depth>
  </size>
  <segmented>0</segmented>
  <object>
    <name>person</name>
    <pose>Unspecified</pose>
    <truncated>0</truncated>
    <difficult>0</difficult>
    <bndbox>
      <xmin>100</xmin>
      <ymin>50</ymin>
      <xmax>300</xmax>
      <ymax>350</ymax>
    </bndbox>
  </object>
</annotation>

关键字段说明:

字段 含义 注意事项
filename 图片文件名 必须与JPEGImages中的文件一致
size 图片尺寸(宽、高、通道数) 标注时自动读取,不要手动修改
name 目标类别名称 大小写敏感,建议全小写
truncated 目标是否被截断(0/1) 图片边缘的目标设为1
difficult 目标是否难以识别(0/1) 模糊、遮挡严重的目标设为1
bndbox 边界框坐标(xmin, ymin, xmax, ymax) 左上角和右下角坐标,像素值

3.3.3 坐标格式说明

Pascal VOC用的是左上角+右下角坐标格式。而YOLO用的是中心点+宽高的归一化格式。两者转换公式如下:

# Pascal VOC (xmin, ymin, xmax, ymax) → YOLO (cx, cy, w, h)
cx = (xmin + xmax) / 2 / image_width
cy = (ymin + ymax) / 2 / image_height
w = (xmax - xmin) / image_width
h = (ymax - ymin) / image_height

这个转换在后续训练中会用到。我建议你写一个脚本批量处理,不要手动算。

3.4 标注规范与避坑指南

这部分是我最想说的。标注规范没定好,后面全是坑。

3.4.1 标注基本原则

  • 框要贴边:边界框紧贴目标轮廓,不要留太多背景,也不要切掉目标主体
  • 遮挡处理:目标被遮挡时,只标注可见部分,不要脑补完整形状
  • 小目标标注:小于图片面积1%的目标,建议统一标注,不要漏标
  • 类别一致性:同一类目标在不同图片中,标注标准要统一

3.4.2 常见错误

我曾经在一个项目中,标注员把「car」和「truck」混着标。结果模型训练出来,大卡车被识别成小轿车。你想想看,这问题出在哪?标注标准没定清楚。

错误类型 表现 后果
框太大 边界框包含大量背景 模型学到背景特征,误检率高
框太小 切掉目标边缘 模型学不到完整特征,召回率低
漏标 图片中有目标但没标注 模型认为这是负样本,产生漏检
标签错误 类别名称写错或混淆 模型分类错误
坐标越界 xmin/xmax超出图片范围 训练时报错,数据加载失败

3.4.3 避坑指南

我曾经踩过的坑:

  • 标注完才发现图片命名有中文和空格,导致训练时路径解析失败。建议统一用数字或英文命名,不要用中文和特殊字符。
  • XML文件中的filename和实际图片名不一致。LabelImg有时会自动修改文件名,记得检查。
  • 多人标注时,同一类目标用了不同名称(比如「person」和「people」)。建议提前定义好类别列表,标注时只能从列表中选择。

3.5 标注流程与质量控制

一个规范的标注流程,应该包含以下步骤:

  1. 制定标注规范文档:明确类别定义、边界框标准、特殊情况处理
  2. 小批量试标:先标50张,检查质量,修正规范
  3. 正式标注:按规范批量标注
  4. 质量抽检:随机抽取10%-20%的标注结果,检查准确率
  5. 修正与迭代:根据抽检结果,修正错误标注

我的建议:标注完成后,用脚本做一次自动化检查。检查内容:XML文件是否完整、坐标是否越界、类别名称是否在预定义列表内、图片和XML是否一一对应。这些检查能帮你省掉很多调试时间。

3.6 本章知识体系

下面这张图总结了本章的核心内容,从工具选择到格式理解,再到标注规范,形成一个完整的数据标注知识体系。

数据集标注知识体系 标注工具选型 LabelImg安装使用 Pascal VOC格式 工具对比 LabelImg / LabelMe CVAT / RectLabel 轻量 vs 协作 vs 付费 操作流程 打开图片 → 画框 输入标签 → 保存 快捷键提升效率 XML结构解析 filename / size object / name bndbox坐标格式 标注规范与避坑指南 框要贴边 | 遮挡处理 | 类别一致性 | 命名规范 | 坐标检查 质量控制:试标 → 正式标 → 抽检 → 修正