4、数据集准备与标注:LabelImg、CVAT工具使用,COCO与自定义数据集格式转换
做YOLO项目,数据是根本。模型再牛,没有好数据也白搭。我见过太多同学花大把时间调参,结果发现是标注出了问题——类别标错了、框没贴边、格式不对。嗯,这章咱们就把数据准备这块彻底捋清楚。
4.1 标注工具怎么选?
说白了,标注工具就两类:本地轻量的和团队协作的。我个人习惯,小项目用LabelImg,大项目或者团队协作直接上CVAT。
| 特性 | LabelImg | CVAT |
|---|---|---|
| 安装方式 | pip install / 直接下载 | Docker部署 / 在线版 |
| 标注方式 | 单机本地标注 | Web端多人协作 |
| 输出格式 | Pascal VOC / YOLO | COCO / YOLO / 自定义 |
| 适用场景 | 几百张图片的小项目 | 几千张以上的团队项目 |
| 学习成本 | 5分钟上手 | 需要简单配置 |
4.2 LabelImg:快速上手
LabelImg是我最早用的工具,轻量、直接。安装就一行命令:
pip install labelImg
labelImg
打开后界面很简洁。左边工具栏,中间图片区,右边文件列表。操作流程就三步:
- 打开图片目录:点击"Open Dir"选择你的图片文件夹
- 创建矩形框:按键盘
w键,鼠标拖拽画框 - 输入标签名:弹窗里输入类别名称,比如"person"、"car"
d 键切换到下一张,按 a 键回退。左手键盘右手鼠标,效率能翻倍。我曾经一天标了800张图,全靠这套快捷键。
保存格式我建议直接选YOLO格式。在LabelImg里点"Change Save Dir",然后选"YOLO"。这样每张图片会生成一个同名的 .txt 文件,里面格式是:
class_id x_center y_center width height
注意,这里的坐标都是归一化的(0~1之间)。比如一张1920x1080的图,框的中心点在(960, 540),宽640,高360,那记录就是:
0 0.5 0.5 0.333 0.333
4.3 CVAT:团队协作利器
项目大了以后,LabelImg就有点吃力了。这时候我推荐CVAT。它是Intel开源的Web标注工具,支持多人同时标注、自动标注、AI辅助标注。
部署方式我用Docker,简单稳定:
git clone https://github.com/opencv/cvat
cd cvat
docker compose up -d
启动后浏览器访问 localhost:8080,注册账号就能用了。CVAT的核心优势在于:
- 任务分配:可以把不同图片分给不同标注员
- 质量检查:标注完成后可以review,不合格的退回重标
- 自动标注:用预训练模型先跑一遍,人工修正就行
4.4 COCO格式 vs YOLO格式
标注完数据,接下来就是格式转换。YOLO官方训练用的是自己的格式,但很多公开数据集(比如COCO)用的是JSON格式。你得学会在两者之间切换。
| 对比项 | COCO JSON格式 | YOLO TXT格式 |
|---|---|---|
| 存储方式 | 一个JSON文件包含所有标注 | 每张图片一个TXT文件 |
| 坐标格式 | [x, y, width, height] 像素坐标 | [x_center, y_center, width, height] 归一化 |
| 类别定义 | JSON内categories数组 | 单独的classes.txt文件 |
| 数据结构 | 嵌套字典,包含images、annotations、categories | 每行一个标注:class_id x y w h |
我写了个转换脚本,每次项目都用它:
import json
import os
def coco_to_yolo(coco_json_path, output_dir):
with open(coco_json_path, 'r') as f:
coco_data = json.load(f)
# 建立图片ID到文件名的映射
img_map = {img['id']: img['file_name'] for img in coco_data['images']}
# 建立类别ID到索引的映射
cat_map = {cat['id']: idx for idx, cat in enumerate(coco_data['categories'])}
# 逐张图片生成YOLO标注
for ann in coco_data['annotations']:
img_id = ann['image_id']
img_name = img_map[img_id]
txt_name = img_name.rsplit('.', 1)[0] + '.txt'
# 转换坐标:COCO的[x,y,w,h] -> YOLO的[x_center,y_center,w,h](归一化)
x, y, w, h = ann['bbox']
img_w = coco_data['images'][img_id]['width']
img_h = coco_data['images'][img_id]['height']
x_center = (x + w / 2) / img_w
y_center = (y + h / 2) / img_h
w_norm = w / img_w
h_norm = h / img_h
cat_id = cat_map[ann['category_id']]
with open(os.path.join(output_dir, txt_name), 'a') as f:
f.write(f"{cat_id} {x_center:.6f} {y_center:.6f} {w_norm:.6f} {h_norm:.6f}\n")
4.5 自定义数据集格式
实际项目中,你很可能需要混合使用公开数据集和自己的数据。比如用COCO的80类做预训练,再在自己的5类数据上微调。这时候就需要统一格式。
YOLO训练要求的数据集目录结构是这样的:
dataset/
├── images/
│ ├── train/
│ │ ├── img001.jpg
│ │ └── img002.jpg
│ └── val/
│ ├── img003.jpg
│ └── img004.jpg
├── labels/
│ ├── train/
│ │ ├── img001.txt
│ │ └── img002.txt
│ └── val/
│ ├── img003.txt
│ └── img004.txt
└── dataset.yaml
dataset.yaml 文件内容:
train: ./images/train
val: ./images/val
nc: 5
names: ['person', 'car', 'bicycle', 'dog', 'cat']
4.6 数据标注避坑指南
标注质量直接影响模型效果。我踩过的坑,列出来给大家参考:
- 框要贴边:标注框必须紧贴目标边缘,不能留白太多,也不能切掉目标。我曾经标猫的时候框大了两圈,结果模型学了一堆背景特征。
- 遮挡目标也要标:被遮挡的部分用框框住完整目标,不要只标可见部分。YOLO学的是完整目标特征。
- 类别平衡:如果某个类别样本太少,模型会偏向多数类。我一般要求每个类别至少500张图,不够就做数据增强或者补充采集。
- 多人标注要统一标准:用CVAT时,一定要写标注规范文档。比如"人"这个类别,是只标全身还是半身也算?不统一的话,模型学出来会混乱。
4.7 本章知识体系
下面这张图总结了数据集准备的核心流程,从原始图片到最终可训练的YOLO数据集:
数据准备是YOLO项目中最基础也最容易被忽视的一环。标注工具选对了、格式转换搞清楚了、避坑指南记住了,后面训练模型才能顺风顺水。我个人觉得,花在数据上的时间永远值得——模型效果好不好,数据说了算。