3、YOLOv8模型训练准备:数据集标注工具LabelImg介绍、COCO数据集格式、自定义数据集制作
好,到了第三章节。前两章我们把树莓派的环境和YOLOv8的框架搭好了,但有个关键问题——模型拿什么学?
说白了,YOLOv8再厉害,它也是个“睁眼瞎”。你得先给它看一堆标注好的图片,告诉它“这是猫”、“那是狗”、“这个红绿灯是红灯”。这个过程,就是数据集制作。
我个人习惯把这一步叫做“喂数据”。数据喂得好不好,直接决定模型能不能用。我在项目里见过太多人,模型结构调得飞起,结果数据集一塌糊涂,最后训练出来的模型根本没法部署。嗯,咱们今天就把这个地基打牢。
3.1 数据集标注工具:LabelImg
标注工具很多,但LabelImg是最经典、最轻量的一个。它用Python写的,界面简单,支持YOLO和VOC两种输出格式。对于咱们树莓派部署的场景,完全够用。
3.1.1 安装LabelImg
安装很简单,我一般用pip直接装:
pip install labelImg
装完之后,在终端输入 labelImg 就能启动。如果你用的是Python虚拟环境,记得先激活环境再运行。
3.1.2 标注流程
打开LabelImg后,界面很直观。我简单说一下操作步骤:
- 打开图片目录:点击“Open Dir”,选择你存放原始图片的文件夹。
- 选择保存格式:点击“Change Save Dir”,设置标注文件的输出目录。然后在菜单栏 View 里勾选“Auto Save mode”,省得每标一张点一次保存。
- 创建矩形框:按键盘
W键,鼠标会变成十字。在目标物体上拖拽出矩形框。 - 输入标签名:弹窗里输入类别名称,比如
person、car、helmet。注意,标签名不要带空格和特殊字符。 - 切换下一张:按
D键切换到下一张图片,按A键回退。
标注完一张,LabelImg会自动在同目录下生成一个同名的 .txt 文件(如果你选的是YOLO格式)。这个文件里存的就是目标框的坐标信息。
3.2 COCO数据集格式
聊完工具,咱们得说说数据格式。YOLOv8原生支持两种格式:YOLO格式和COCO格式。我个人更推荐大家理解COCO格式,因为它是目前目标检测领域的事实标准。
COCO格式说白了就是一个大的JSON文件。里面包含了图片信息、标注信息、类别信息。结构大概是这样的:
{
"images": [
{"id": 1, "file_name": "000001.jpg", "width": 640, "height": 480}
],
"annotations": [
{"id": 1, "image_id": 1, "category_id": 1, "bbox": [100, 150, 200, 300], "area": 60000}
],
"categories": [
{"id": 1, "name": "person"}
]
}
这里有个关键点:bbox 的格式是 [x, y, width, height],其中 x, y 是矩形框左上角的坐标。这和YOLO格式的 [center_x, center_y, width, height] 不一样。很多新手在这里搞混,导致训练出来的模型检测框全偏了。
- COCO格式:左上角坐标 + 宽高,单位是像素。
- YOLO格式:中心点坐标 + 宽高,单位是相对于图片宽高的归一化值(0~1)。
YOLOv8在训练时,会自动把COCO格式的JSON转换成内部的张量。所以如果你用LabelImg标注时选了YOLO格式,其实也可以直接用,但需要把图片和txt文件按YOLO的目录结构放好。
3.3 自定义数据集制作
好了,理论讲完,咱们来动手。假设你要做一个“安全帽检测”的数据集,用来部署到树莓派上监控工地安全。
3.3.1 数据采集
数据采集这块,我建议你遵循“三多原则”:多角度、多光照、多背景。别只拍正面的安全帽,侧面的、背面的、逆光的、阴天的,都得有。
我在项目里遇到过这种情况:训练集里全是红色安全帽,结果部署到现场,工人戴的是黄色安全帽,模型直接漏检。所以采集数据时,尽量覆盖所有可能的变体。
3.3.2 目录结构
YOLOv8对数据集目录结构有约定。我个人习惯这样组织:
datasets/
helmet/
images/
train/
img_001.jpg
img_002.jpg
...
val/
img_100.jpg
img_101.jpg
...
labels/
train/
img_001.txt
img_002.txt
...
val/
img_100.txt
img_101.txt
...
注意:图片和标注文件的名字必须一一对应,后缀不同而已。比如 img_001.jpg 对应 img_001.txt。
3.3.3 数据集配置文件
YOLOv8训练时需要一个 .yaml 文件来告诉模型数据在哪。内容如下:
# helmet.yaml
path: ./datasets/helmet # 数据集根目录
train: images/train # 训练集图片路径
val: images/val # 验证集图片路径
nc: 2 # 类别数量
names: ['helmet', 'head'] # 类别名称列表
这里 nc 是类别数,names 是类别名列表。顺序要和标注时的标签名一致。比如标注时 helmet 是第一个出现的标签,那它在列表里就排第一。
3.3.4 数据划分
数据采集完、标注完,最后一步是划分训练集和验证集。我一般按8:2的比例随机划分。可以用一个简单的Python脚本搞定:
import os
import random
import shutil
# 假设所有图片都在 raw_images 文件夹
images = os.listdir('raw_images')
random.shuffle(images)
split_idx = int(len(images) * 0.8)
train_images = images[:split_idx]
val_images = images[split_idx:]
# 然后分别复制到 images/train 和 images/val
# 同时复制对应的 .txt 文件到 labels/train 和 labels/val
3.4 本章知识结构图
下面这张图总结了数据集制作的完整流程,从原始图片到可训练的YOLOv8数据集:
3.5 避坑指南
最后,我把自己这些年踩过的坑总结一下,你遇到了可以少走弯路:
| 常见问题 | 现象 | 解决方案 |
|---|---|---|
| 类别ID混乱 | 训练时loss不收敛,mAP为0 | 检查 data.yaml 中 names 的顺序是否与标注时的标签顺序一致 |
| 标注框超出图片边界 | 训练报错或检测框异常 | 标注时注意框不要超出图片边缘,LabelImg会自动限制 |
| 图片与标注文件不匹配 | 训练时提示找不到标注文件 | 确保文件名完全一致(包括大小写),且放在对应的 labels 目录下 |
| 类别样本不均衡 | 模型只检测出多数类,漏检少数类 | 采集数据时有意增加少数类的样本量,或者使用数据增强 |
data.yaml 里的 nc 写成了3,但我实际只有2个类别。YOLOv8不会报错,它会默默地把第三个类别当成空类,导致模型学歪了。所以,训练前一定要用 yolo checks 命令验证一下数据集配置。