共计 5199 个字符,预计需要花费 13 分钟才能阅读完成。
目录
- 先定义“好标签”:标注规范与口径
- 工具三选一:Label Studio / CVAT / Roboflow
- 目录结构与命名约定
- 标注 → 导出为 YOLO(检测 / 分割 / 关键点)
data.yaml编写模板(多数据集 / 多任务)- 数据集 体检脚本(合法性 / 分布 / 可视化)
- 划分 train/val/test(分层与去泄漏)
- 数据增强策略(上线友好 vs 竞赛风格)
- 最小训练 / 验证一把过
- 常见坑与排错清单
- 课后练习(含参考答案要点)
1) 先定义“好标签”:标注规范与口径
检测(Bounding Box)
- 紧致贴合:矩形尽量贴合可见区域,不要留大边。
- 遮挡 / 截断:只框可见部分;>50% 可见仍标注;完全遮挡不标。
- 重叠实例:分开各自标注,不合并。
- 旋转物体:仍用轴对齐框(YOLO 检测头假定 axis-aligned)。
- 模糊 / 远小目标:若最短边 < 4 像素,建议不标(训练难、噪声大)。
分割(Instance Segmentation)
- 用 多边形 勾勒外轮廓;孔洞按工具规范(内环)处理;
- 重叠实例分别标,避免“粘连”。
关键点(Pose/Keypoints)
- 定义关键点顺序与可见性规则(如:不可见记 0/1),务必写成 README。
类目清单(示例)
0 person
1 bicycle
2 car
3 dog
一旦开工,类目名称与顺序不可随意改动。改动 = 全量重映射(见 §10)。
2) 工具三选一:Label Studio / CVAT / Roboflow
三者都能导出 YOLO 格式,取悦即可:
- Label Studio:易上手,开源;装插件可导 YOLO。适合小团队。
- CVAT:专业、多人协作强,支持检测 / 分割 / 关键点;导出 YOLO 系列格式。
- Roboflow:托管式,导出 / 转换方便;免费配额适合入门练习。
通用流程
- 创建项目 → 录入 类目清单 并给每类配色;
- 导入图片(注意版权与尺寸多样性);
- 配置协作:任务划分、质检人(QA)与抽检比例(≥ 10%);
- 标注快捷键训练(框 = 拖拽;分割 = 笔刷 / 多边形;复制 =Ctrl+D 等);
- 质检:对齐“边界策略”“遮挡策略”;
- 导出:选择 YOLO(检测 / 分割 / 关键点)格式包。
3) 目录结构与命名约定
YOLOv8 推荐:
my-dataset/
images/
train/ xxx.jpg
val/ xxx.jpg
test/ xxx.jpg # 可选
labels/
train/ xxx.txt
val/ xxx.txt
test/ xxx.txt # 可选
- 标签文件与图片 同名,内容为 YOLO 行(详见下节)。
- 建议文件名只用
[a-z0-9_-],避免空格与中文路径。
4) 标注 → 导出为 YOLO
4.1 YOLO 检测标签(*.txt)
每行一个框:
<class_id> <x_center> <y_center> <width> <height>
- 坐标都是 相对比例(0~1),相对图像宽高;
- 例:
2 0.512 0.433 0.210 0.180表示类 2 的框。
4.2 YOLO 分割标签
- 与检测类似,但在该行后追加 归一化多边形点序列:
x1 y1 x2 y2 ...; - 一个实例可含多个轮廓,工具会生成多行(按导出器规范)。
4.3 YOLO 关键点(pose)
- 行内含
num_keypoints组(x, y, v),v是可见性标志; - 你需要在
data.yaml中提供kpt_shape: [num_kpts, dim]与flip_idx(见官方示例)。
4.4 从工具导出到目录
- CVAT:
Export → YOLO 1.x/YOLOv5-7/YOLOv8,选 train/val 分包或一次性导出后自己拆分。 - Label Studio:安装 YOLO 导出插件(或先导 COCO 再转换脚本)。
- Roboflow:
Export → YOLOv8直接得到标准结构包。
5) data.yaml 模板
最小示例(检测 / 分割通用):
# data.yaml
path: /abs/path/to/my-dataset # 或相对路径
train: images/train
val: images/val
# test: images/test
nc: 4
names: [person, bicycle, car, dog]
关键点任务需补:
kpt_shape: [17, 3] # 关键点数量与维度
flip_idx: [0,2,1,4,3,...] # 左右翻转映射(示例,按你的定义填写)
多数据源(合并多个子集):
train:
- /data/ds1/images/train
- /data/ds2/images/train
val:
- /data/ds1/images/val
- /data/ds2/images/val
6) 数据集 体检脚本(强烈建议)
用 Python 快速扫一遍标签合法性与分布。
# check_yolo_dataset.py
import os, glob, math
from collections import Counter, defaultdict
def read_sizes(txt_path):
bad, classes = [], Counter()
for p in glob.glob(os.path.join(txt_path, '**', '*.txt'), recursive=True):
with open(p, 'r', encoding='utf-8') as f:
for ln, line in enumerate(f, 1):
arr = line.strip().split()
if len(arr) < 5: bad.append((p, ln, 'len<5')); continue
try:
cid = int(arr[0]); vals = list(map(float, arr[1:5]))
except: bad.append((p, ln, 'parse')); continue
x,y,w,h = vals
if not (0<=x<=1 and 0<=y<=1 and 0<w<=1 and 0<h<=1):
bad.append((p, ln, 'range'))
if w*h < 1e-5: bad.append((p, ln, 'tiny'))
classes[cid]+=1
return bad, classes
for split in ['train','val','test']:
lbl = f'my-dataset/labels/{split}'
if os.path.isdir(lbl):
bad, cls = read_sizes(lbl)
print(f'[{split}] classes:', dict(cls))
if bad:
print(f'[{split}] BAD {len(bad)} lines (path, line, why):')
for b in bad[:20]: print(' ', b)
print('...')
看三件事:① 非法坐标 / 极小框;② 类别分布是否 长尾过度 ;③ 是否存在 大量空标签(没对象也不是错,但要有意识)。
7) 划分 train/val/test(分层与去泄漏)
- 分层 :按 类目出现 做近似分层(防止某类只落在 train);
- 去泄漏:
- 同一视频 /Burst 连拍 → 只放一个 split;
- 同一 ID 的同场景重复图 → 去重或固定到 train;
- 生成式增强出的图片 不要 混入验证集。
快速划分脚本(按文件名哈希 80/10/10)
import os, shutil, hashlib, glob
SRC='images_all' # 原始图像目录
DST='my-dataset'
for sp in ['train','val','test']:
os.makedirs(f'{DST}/images/{sp}', exist_ok=True)
os.makedirs(f'{DST}/labels/{sp}', exist_ok=True)
def bucket(p):
h=int(hashlib.md5(p.encode()).hexdigest(),16)%100
return 'train' if h<80 else ('val' if h<90 else 'test')
for img in glob.glob(f'{SRC}/**/*.jpg', recursive=True):
sp=bucket(os.path.basename(img))
base=os.path.splitext(os.path.basename(img))[0]
lbl=img.replace('/images_all/','/labels_all/').replace('.jpg','.txt')
shutil.copy2(img, f'{DST}/images/{sp}/{base}.jpg')
if os.path.exists(lbl):
shutil.copy2(lbl, f'{DST}/labels/{sp}/{base}.txt')
更严格的“按视频 /ID 分桶”可在文件名或清单里编码,再按桶分配。
8) 数据增强策略
上线友好型(稳健泛化)
- 颜色扰动(HSV/ 亮度对比度)、水平翻转、轻微缩放与裁剪;
- 关闭极端 mosaic/mixup(可能引入不自然分布)。
竞赛 / 极限型(追分)
- 开启 mosaic/mixup、大尺度多尺度训练;
- 结合强随机裁剪与旋转(注意不要剪掉太多目标)。
命令示例(参数以你本地 ultralytics 版本为准)
yolo train model=yolov8n.pt data=data.yaml epochs=100 imgsz=640 \
hsv_h=0.015 hsv_s=0.7 hsv_v=0.4 fliplr=0.5 degrees=0.0 translate=0.1 scale=0.5 shear=0.0 \
mosaic=0.0 mixup=0.0 # 上线友好:先关掉
注意不同版本默认增强略有差异,建议显式写出关键增强参数,确保可复现。
9) 最小训练 / 验证一把过
# 1) 训练
yolo train model=yolov8n.pt data=data.yaml epochs=50 imgsz=640 batch=auto
# 2) 验证(可单独跑,也会在训练结束自动评估)yolo val model=runs/detect/train*/weights/best.pt data=data.yaml
# 3) 推理查看效果
yolo predict model=runs/detect/train*/weights/best.pt source=images/val --save
关注指标:mAP50、mAP50-95、Precision/Recall 与推理速度。类目极不均衡时观察 每类 mAP。
10) 常见坑与排错清单
- 类目错位 :
names顺序变了 → 训练 / 预测类别全乱。办法:统一names,如需改动,用脚本 重映射 class_id 后再训。 - 坐标越界 / 空行:导出后跑 §6 的体检脚本;有问题回工具修或用脚本过滤。
- 图片有,标签无:表示“负样本”(OK);但要控制比例,避免网络学到“背景即一切”。
- 过小框:面积极小的框会扰乱训练;考虑阈值过滤(如
w*h<1e-4)。 - 分割多边形自交:某些导出会产生自交 polygon,训练时报错;回到工具里修形或简化点数。
- 路径 / 编码:Windows 反斜杠与中文路径可能导致脚本失效;路径用相对 / 英文。
11) 课后练习(建议 60–90 分钟)
练习 A(两类玩具集)
- 任选 120 张图片,定义两类(如 apple, banana),各 ≥ 50 个框;
- 标注并导出 YOLO;
- 用体检脚本列出类分布与小框比例;
epochs=50训练,报告mAP50与每类AP。
练习 B(数据增强对比)
- 同一数据,跑两组:
mosaic=0.0与mosaic=0.5 mixup=0.2,比较 mAP 与错检 / 漏检案例。
练习 C(重映射与合并)
- 将
[car, van, bus]合并为vehicle,写脚本把旧标签重映射后重训; - 加入一批“全背景图”,观察
Precision/Recall变化。
参考答案要点:A) 类别均衡度、标注一致性对 mAP 的影响;B) 强增强可能提升 Recall 但也会增加假阳性;C) 合并类能提升样本规模,前提是语义一致。
附录:类别重映射脚本(示例)
# remap_classes.py
import os, glob
mapping = {0:0, 1:0, 2:0} # car/van/bus -> vehicle(0)
for p in glob.glob('my-dataset/labels/**/*/*.txt', recursive=True):
lines=[]
with open(p,'r') as f:
for line in f:
arr=line.strip().split()
if not arr: continue
cid=int(arr[0])
if cid in mapping:
arr[0]=str(mapping[cid])
lines.append(' '.join(arr))
with open(p,'w') as f: f.write('\n'.join(lines)+'\n')
小结
数据是模型的镜子。先把 口径 和规范 写清楚,再让工具替你稳稳地执行。体检脚本是你最好的“班主任”——天天查、每次训前查。
正文完

