第四章 数据集准备与预处理:工业落地的第一步
说实话,很多搞算法的朋友觉得模型结构才是核心。但我做了这么多年工业项目,可以负责任地告诉你——数据准备才是真正决定项目生死的关键。模型剪枝量化再牛,数据不对,一切都是白搭。
这一章,我们就来聊聊工业场景下,YOLOv11的数据集到底该怎么准备。
4.1 工业数据集格式:COCO vs YOLO
工业项目里,最常见的标注格式就两种:COCO和YOLO。我见过不少团队在这上面栽跟头,所以先把这个讲清楚。
| 对比维度 | COCO格式 | YOLO格式 |
|---|---|---|
| 标注文件 | 单个JSON文件 | 每张图片一个TXT |
| 坐标表示 | 左上角(x,y)+宽高 | 中心点(x,y)+宽高(归一化) |
| 类别定义 | JSON内categories数组 | 数字索引(0,1,2...) |
| 适用场景 | 通用检测、实例分割 | YOLO系列原生格式 |
| 工业落地难度 | 中等(需解析JSON) | 低(直接读取) |
我个人习惯:工业项目直接用YOLO格式。为什么?因为产线上的数据量动不动几十万张,COCO的单个JSON文件一旦损坏,整个标注就废了。YOLO格式每张图独立,出问题只影响一张,容错性好太多。
核心要点:YOLOv11原生支持YOLO格式。如果你手头是COCO数据,记得做格式转换。我一般用下面这个脚本搞定:
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'])}
# 逐张图片转换
for ann in coco_data['annotations']:
img_id = ann['image_id']
img_file = img_map[img_id].replace('.jpg', '.txt')
# COCO: [x, y, w, h] → YOLO: [cx, cy, w, h] 归一化
x, y, w, h = ann['bbox']
img_w = coco_data['images'][img_id]['width']
img_h = coco_data['images'][img_id]['height']
cx = (x + w/2) / img_w
cy = (y + h/2) / img_h
nw = w / img_w
nh = h / img_h
cat_id = cat_map[ann['category_id']]
with open(os.path.join(output_dir, img_file), 'a') as f:
f.write(f"{cat_id} {cx:.6f} {cy:.6f} {nw:.6f} {nh:.6f}\n")
我曾经踩过的坑:COCO的bbox是[x, y, width, height],而YOLO需要的是归一化的中心点坐标。直接复制粘贴坐标,模型训练出来检测框全偏。嗯,那次排查了我整整两天。
4.2 数据标注工具:选对工具事半功倍
工业场景下,标注工具的选择直接影响效率。我推荐三个:
- LabelImg:轻量级,适合小团队快速上手。Python写的,安装简单。
- LabelStudio:支持多人协作,适合中大型项目。可以标注分类、检测、分割。
- CVAT:英特尔出品,功能最全。支持自动标注、半自动标注,工业级首选。
我个人在产线上用得最多的是CVAT。为什么?因为它支持半自动标注——先用一个预训练模型跑一遍,人工只修正错误框。效率能提升3-5倍。
小技巧:标注时,类别名称统一用英文小写+下划线。比如"defect_scratch"、"defect_dent"。中文路径在Linux服务器上经常出编码问题,别问我怎么知道的。
4.3 数据增强策略:Mosaic与MixUp
工业数据往往不够多样。比如产线上拍的零件,角度、光照都差不多。这时候就需要数据增强来"造"数据。
Mosaic增强
YOLOv4开始引入的Mosaic,说白了就是把4张图拼成1张。这样做的好处:
- 小目标检测能力提升(拼图后目标相对变小)
- 背景多样性增加
- BN层统计更稳定
YOLOv11里Mosaic默认是开启的。但注意,训练最后10-20个epoch建议关掉。为什么?因为拼图后的分布和真实场景有差异,一直用会让模型学偏。
# YOLOv11超参数配置示例
# hyp.yaml
mosaic: 1.0 # 前80% epoch开启
mosaic_close_epoch: 10 # 最后10个epoch关闭
MixUp增强
MixUp更狠——两张图按比例混合,标签也按比例混合。比如0.7的猫+0.3的狗,标签就是[0.7, 0.3]。
我在项目中遇到过一个问题:MixUp虽然能提升泛化能力,但会让模型收敛变慢。所以我的建议是:数据量少于1万张时开MixUp,超过1万张可以关掉。
工业落地经验:数据增强不是越多越好。我见过一个团队开了10种增强,结果模型在产线上误检率飙升。记住:增强的目的是模拟真实变化,不是制造不存在的情况。
4.4 数据加载器定制:让GPU吃饱
工业场景下,数据加载往往是性能瓶颈。GPU算力再强,数据喂不进去也是白搭。
YOLOv11的数据加载器已经做得不错了,但有几个点需要定制:
- 多线程加载:workers数量设为CPU核心数的2-4倍。我一般设8或16。
- 预取队列:开启prefetch,让CPU提前准备下一批数据。
- 缓存策略:小数据集(<1万张)可以全量缓存到内存,IO速度提升10倍。
# 自定义数据加载器示例
from torch.utils.data import DataLoader
from ultralytics.data import YOLODataset
class IndustrialDataset(YOLODataset):
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
# 缓存图片到内存
self.cache_images = True
def load_image(self, i):
# 自定义加载逻辑
img = super().load_image(i)
# 工业相机拍的图可能带EXIF旋转信息
# 这里做自动旋转校正
return self._fix_exif_rotation(img)
# 使用示例
loader = DataLoader(
IndustrialDataset(...),
batch_size=32,
num_workers=8, # 多线程加载
prefetch_factor=4, # 预取队列
pin_memory=True # 锁页内存加速
)
注意:num_workers不是越大越好。我试过设32,结果CPU被打满,GPU反而等数据。一般8-16就够用了。具体多少,跑一次看CPU利用率就知道了。
4.5 本章知识体系总览
下面这张图,把数据准备的全流程串起来了。你可以把它当作一个checklist,做项目时对照着来。
数据准备这块,说白了就是"磨刀不误砍柴工"。我见过太多项目,模型结构调得飞起,结果数据有问题,最后全白干。嗯,这一章的内容足够你应付90%的工业场景了。记住:好的数据,是模型剪枝量化的地基。