☰
铝片表面缺陷检测:400张VOC+YOLO数据集训练YOLOv8实战
2026/10/5 7:48:50 网站建设 项目流程

简介:本资源为铝片表面工业缺陷检测数据集,面向从事工业质检、表面缺陷识别方向的算法工程师与深度学习学习者,可用于目标检测模型的训练、验证与算法对比实验。数据集采用Pascal VOC与YOLO双格式标注,包含400张jpg图片,并配套400个VOC格式xml文件与400个YOLO格式txt文件,标注工具为labelImg,共覆盖ca_shang、zang_wu、zhe_zhou、zhen_kong四类缺陷,总标注框数达1062个,其中zang_wu与ca_shang样本相对丰富。压缩包为7z格式,内含1202个文件,整体约15.25MB,体积轻便,便于快速下载与本地部署。目前已有526人学习下载,适合作为工业缺陷检测入门练手或小样本实验的现成数据来源,读者可直接接入YOLO系列或VOC兼容框架,省去自行标注与格式转换的时间成本。

1. 铝片表面缺陷检测:400 张 VOC+YOLO 数据集到底能不能训出可用模型

产线上铝片表面缺陷检测,最让人头疼的不是模型选型,而是数据。铝片反光强、缺陷对比度低,划痕、凹坑、脏污、氧化这几类缺陷在普通工业相机下经常糊成一片。很多团队一上来就想搞几千张标注数据,结果采集两周、标注一个月,模型还没跑起来项目就先黄了。我拿到「铝片表面工业缺陷检测数据集 VOC+YOLO 格式 400 张 4 类别」这个标题时,第一反应是:这个量级到底够不够用?答案是——看你怎么用。400 张、4 类别,平均每类 100 张,如果直接硬训 YOLOv8n 从零开始,大概率过拟合;但如果走迁移学习 + 合理增强 + 严格划分,做一条产线单工位的初筛模型是能落地的。这篇笔记就围绕这个数据集,把 VOC 与 YOLO 两种格式的转换、训练参数、增强策略和踩坑点讲透,适合刚接手铝片缺陷检测、手里只有几百张标注图的工程师。

2. 先搞懂 VOC 和 YOLO 两种格式:为什么这个数据集要同时给两份

2.1 VOC 的 XML 结构与 YOLO 的 TXT 结构差异

VOC 格式的核心是每张图对应一个 XML 文件,里面用<object>节点记录类别名和边界框的左上角、右下角坐标。YOLO 格式则是每张图对应一个 TXT 文件,每行是类别索引 中心x 中心y 宽 高,且这四个值都归一化到 0~1。这个数据集同时给 VOC 和 YOLO 两份,本质是照顾两类工具链:VOC 方便用 labelImg 继续改标、用 mmdetection 或 PaddleDetection 直接读;YOLO 格式则直接喂给 ultralytics 系的 YOLOv5/v8/v11。

我一般会先确认一件事:两份标注是不是严格一一对应。常见翻车点是 VOC 里改了框,YOLO 的 TXT 没同步,训练时 mAP 死活上不去,最后发现是标注错位。校验方法很简单,写个脚本把 VOC 的框转成 YOLO 格式,和给定的 TXT 逐行比对。

import os import xml.etree.ElementTree as ET def voc_to_yolo(xml_path, class_list): tree = ET.parse(xml_path) root = tree.getroot() size = root.find('size') w = int(size.find('width').text) h = int(size.find('height').text) lines = [] for obj in root.iter('object'): cls_name = obj.find('name').text if cls_name not in class_list: continue cls_id = class_list.index(cls_name) bnd = obj.find('bndbox') x1 = float(bnd.find('xmin').text) y1 = float(bnd.find('ymin').text) x2 = float(bnd.find('xmax').text) y2 = float(bnd.find('ymax').text) # 归一化并转中心点格式 cx = (x1 + x2) / 2.0 / w cy = (y1 + y2) / 2.0 / h bw = (x2 - x1) / w bh = (y2 - y1) / h lines.append(f"{cls_id} {cx:.6f} {cy:.6f} {bw:.6f} {bh:.6f}") return lines CLASSES = ['scratch', 'dent', 'stain', 'oxidation'] # 按数据集实际类别顺序改 xml_dir = 'Annotations' for f in os.listdir(xml_dir): if f.endswith('.xml'): out = voc_to_yolo(os.path.join(xml_dir, f), CLASSES) with open(os.path.join('labels', f.replace('.xml', '.txt')), 'w') as fp: fp.write('\n'.join(out))

这段脚本的关键在class_list的顺序,必须和 YOLO 训练时data.yaml里的names完全一致,否则类别会整体错位。归一化时用图像真实宽高,不要用网络输入尺寸,这是新手最容易搞混的地方。转换完建议随机抽 5 张用可视化脚本画框核对,别嫌麻烦,这一步省下的时间后面会加倍还回来。

2.2 400 张 4 类别,划分比例怎么定才不浪费

400 张按 8:1:1 划分是 320 训练、40 验证、40 测试。听起来验证集只有 40 张,每类 10 张,mAP 波动会很大。我的做法是:如果只是内部快速验证,用 7:2:1;如果要出正式报告,至少保证验证集每类不少于 15 张,也就是把训练集压到 280 左右。铝片缺陷本身类间差异大、类内差异小,验证集太小会让早停策略误判。

划分时务必按「批次/工位」分层,而不是纯随机。同一片铝板裁出的多张图如果被分到训练和验证两边,验证指标会虚高,上线就露馅。常见做法是先把图片按采集批次分组,再按组划分。

提示:划分完把文件列表存成 train.txt / val.txt,后续训练直接读列表,避免每次重新随机导致指标不可复现。

3. 用 YOLOv8 在 400 张铝片缺陷上跑通训练:参数与增强

3.1 环境与数据目录组织

ultralytics 系现在装起来很省事,一条命令搞定。我一般用 Python 3.10 + torch 2.x,显卡 8G 显存足够跑 yolov8n/s。数据目录按官方推荐结构放:

pip install ultralytics # 目录结构 # datasets/aluminum/ # images/train/ images/val/ # labels/train/ labels/val/ # data.yaml

data.yaml内容如下,path用绝对路径最稳,避免相对路径在不同工作目录下找不到:

path: /data/datasets/aluminum train: images/train val: images/val names: 0: scratch 1: dent 2: stain 3: oxidation

3.2 迁移学习:为什么必须从预训练权重起步

400 张图从零训,卷积核根本学不出铝片那种低对比度纹理。我一般直接加载yolov8n.pt或yolov8s.pt,冻结前几层先热身,再全量微调。命令如下:

yolo detect train \ data=/data/datasets/aluminum/data.yaml \ model=yolov8s.pt \ epochs=150 \ imgsz=640 \ batch=16 \ lr0=0.001 \ lrf=0.01 \ warmup_epochs=3 \ freeze=10 \ patience=30 \ cache=True \ name=aluminum_v8s

参数逐个说:imgsz=640是 YOLO 默认,铝片缺陷有的划痕很细,如果显存够可以上 960,小目标召回会明显好;batch=16在 8G 卡上跑 yolov8s 基本不炸;lr0=0.001比默认 0.01 小一个量级,因为数据少,大学习率容易震荡;freeze=10冻结 backbone 前 10 层,先让 head 适应新类别;patience=30配合早停,400 张数据通常 80~120 轮就收敛。cache=True把图缓存到内存,小数据集能明显提速。

3.3 针对铝片反光的增强参数怎么调

默认增强里hsv_v、hsv_s对铝片反光有帮助,但mosaic在缺陷检测里要慎用。mosaic 会把 4 张图拼一起,铝片背景本来就单一,拼完容易出现不真实的边界,模型学到伪特征。我的经验是:前 100 轮开 mosaic 提升泛化,后 50 轮关掉让模型适应真实单图分布。

# 在 train 命令后追加 mosaic=1.0 close_mosaic=50 \ hsv_h=0.015 hsv_s=0.7 hsv_v=0.4 \ degrees=10 translate=0.1 scale=0.5 \ fliplr=0.5 flipud=0.0

flipud=0.0是因为铝片在产线上有固定上下方向,垂直翻转会造出物理上不存在的缺陷形态。degrees=10小角度旋转模拟摆放偏差,别开太大,否则划痕方向特征被破坏。scale=0.5允许缩放,对远近不同的拍摄距离有好处。

注意:增强不是越多越好。400 张数据如果增强过猛,模型会把增强噪声当特征,验证集 mAP 虚高,上线误检一堆。

4. 训练完指标好看但产线误检:铝片缺陷检测的避坑清单

4.1 现象:验证 mAP 0.85,上线误检率却超过 20%

原因通常是验证集和产线分布不一致。400 张数据如果全来自同一批铝板、同一光照,验证集只是「同分布抽样」,模型没学过光照变化和不同批次的反光差异。解决:把产线新采的图(哪怕没标注)先跑推理,人工看误检集中在哪类,再针对性补 20~30 张困难样本重训。别指望一次训练就上线。

4.2 现象:小划痕全部漏检,大凹坑正常

原因在imgsz和 anchor 尺度。640 输入下,长度小于 10 像素的划痕在特征图上只剩 1~2 个像素,很容易被下采样吃掉。解决:把imgsz提到 960 或 1280,或者改用 yolov8 的 P2 小目标检测头。代价是显存和推理耗时上升,产线节拍要重新评估。

4.3 现象:训练 loss 正常下降,但验证 loss 从第 30 轮开始反弹

典型过拟合。400 张数据训 150 轮,backbone 参数量远大于数据量。解决:加大weight_decay到 0.001,提高dropout(如果模型支持),或者直接换更小的 yolov8n。另一个常被忽略的点是freeze层数,冻结太少等于全量微调,小数据必过拟合。

4.4 现象:同一张图两次推理结果框位置抖动

原因可能是conf阈值设太低,模型在低置信度区间反复横跳。解决:把推理conf从默认 0.25 提到 0.4~0.5,配合 NMS 的iou=0.5。铝片缺陷通常一个区域只有一个缺陷,NMS 可以更激进。另外检查推理时是否误开了 TTA,TTA 会放大抖动。

4.5 现象:VOC 和 YOLO 两份标注类别名不一致

比如 VOC 里写scratch,YOLO 的data.yaml里写Scratch,大小写不匹配导致某类永远学不到。解决:统一用小写,转换脚本里加cls_name.lower()。这个坑我踩过,排查了两天才发现是大小写。

5. 把 400 张用到极致:困难样本挖掘与半自动标注的进阶技巧

数据量小的时候,与其盲目加图,不如把每一张的价值榨干。我常用的套路是「训练—推理—挑错—回标」闭环。先用当前模型对训练集本身做推理,把置信度在 0.3~0.6 之间的图挑出来,这些是模型「犹豫」的样本,人工复核后修正标注,再重训。400 张里通常能挑出 30~50 张标注有偏差或本身模糊的图,修正后 mAP 能涨 3~5 个点。

第二个技巧是半自动标注扩数据。产线上无标注的铝片图很多,用训好的模型先跑一遍预测,导出 YOLO 格式 TXT,再人工只做「删错框、补漏框」,比从零画框快 3~5 倍。注意预测框的conf要设高一点(0.5 以上),宁可漏标也别引入大量错标,错标对模型的伤害比漏标大得多。

第三个技巧是类别不平衡处理。4 类别里如果oxidation只有 40 张,其他类 120 张,训练时可以在data.yaml同级加一个cls_weights,或者在 loss 里对稀有类加权。ultralytics 默认不直接暴露这个参数,简单做法是把稀有类图片在训练列表里重复 2~3 次(过采样),配合强增强,效果立竿见影。

验证阶段别只看 mAP50,铝片缺陷检测更该关注mAP50-95和每类的precision/recall。产线最怕漏检,recall 优先于 precision。如果 recall 上不去,先查标注有没有漏框,再查imgsz和conf阈值。我现在的习惯是:每次训完先导出confusion_matrix.png和val_batch0_pred.jpg,肉眼过一遍预测框,比盯数字有用得多。400 张数据不大,但用对了,足够撑起一条单工位的铝片表面缺陷初筛。希望帮到你。

本文还有配套的精品资源,点击获取

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询