
简介YOLO工业油污缺陷检测数据集面向制造业质检、工业视觉与目标检测开发者整合10000张真实工业环境下的油污缺陷图片场景丰富且由LabelImg完成高质量标注可直接用于YOLO系列模型训练。压缩包约797.79MB共2000个文件核心包括1985个xml标签、6个txt、6个html教程与3个py脚本同时提供voc(xml)、coco(json)、yolo(txt)三种格式标签并分文件夹存放满足不同框架的输入要求。除数据外配套Linux与Windows下的YOLO环境搭建教程、训练案例教程以及训练/验证/测试集划分脚本和ImageSets生成脚本便于按需求自由拆分数据并复用到自建数据集。整体资料完整已有286人学习下载适合需要快速落地工业油污缺陷检测与模型复现的算法工程师、科研用户及课程学习者。1. 一万张工业油污图为什么比你自己攒三个月数据集更值得用做工业视觉检测的工程师十有八九都栽在数据上。产线拍回来的图不是背景太乱就是光照不均油污缺陷本身又是那种边界模糊、反光多变的东西靠自己在车间蹲点采集三个月能凑两千张有效样本就算运气好。这也是为什么 YOLO工业油污缺陷检测数据集 这种带一万张图片的现成资源一出现大家第一反应是先看看它能不能直接用。这个数据集解决的痛点很明确油污检测不像猫狗分类网上随便一抓就是几万张。工业场景的缺陷样本往往涉及具体的产线背景、特定的油污形态公开数据集稀缺标注成本又高。一万张图片配合VOC、COCO、YOLO三种格式的标签意味着你拿到手不用重新转换格式不管你是习惯用labelimg做标注、用Detectron2做训练、还是直接走YOLO系列的训练管线都能直接对接到自己的流程里。它真正适合的是两类人一是刚入门工业视觉、想在真实数据集上跑通YOLO训练全流程的开发者二是已经有一套检测系统、但缺新的负样本做模型迭代的一线工程师。前者缺数据后者缺的是省时间的标注和格式转换这个包两头都占了。不过数据集好用不代表拿来就训练。一万张图听着不少但工业缺陷检测里类别分布是否均匀、标注框是否贴合真实油污边界、划分脚本能不能保证训练集和验证集不串样本这些才是决定模型能不能上产线的关键。下面从格式转换、划分脚本、训练参数到避坑一条条拆开讲。2. 三种标签格式的底层逻辑VOC、COCO、YOLO到底差在哪2.1 标签格式本质上只有一种东西框的坐标表示很多新手拿到数据集看到三个文件夹——VOC的XML、COCO的JSON、YOLO的TXT以为这是三套完全不同的东西其实它们描述的是同一批标注框只是坐标的存储姿势不一样。VOC用XML文件逐个记录每个object的类别名和bounding box的四个值xmin、ymin、xmax、ymax全是绝对像素坐标COCO把所有图片的标注汇总到一个JSON文件里框的坐标是[x, y, width, height]同样是绝对像素YOLO最直接每张图一个TXT每行是“类别ID x_center y_center width height”四个值全部归一化到0到1之间。YOLO的归一化坐标是它和另外两种格式最大的分水岭。归一化意味着不管你的原图是640乘640还是1920乘1080训练时模型读到的框的相对位置和大小都是一致的这直接契合YOLO在特征图上做回归的机制。而VOC和COCO的绝对像素坐标在送入YOLO训练前必须除以图片宽高完成归一化这个步骤看似简单但图片宽高信息一旦和XML/JSON对不上坐标就全偏了。我见过一个翻车现场有人从COCO转YOLO时没注意原图被预处理脚本resize过JSON里的宽高和实际图片不一致训练出来的模型框全偏到右下角排查了整整一天。这个数据集同时提供三种格式对使用者的价值不只是省去转换这一步更是给了你一个校验基准。你可以从VOC里随机抽几十张图手算一下XML里的坐标能不能和YOLO TXT里的归一化值互相换算验证整个标注管线的一致性。这个习惯建议保留以后自己标注新数据时也用得上。2.2 VOC格式的XML结构读标注、改标注的基本功VOC格式以Pascal VOC的标准目录结构为模板每张图片对应一个同名XML文件。一个标准的标注XML长这样annotation folderoil_stain/folder filenameoil_001.jpg/filename size width1280/width height720/height depth3/depth /size object nameoil_stain/name bndbox xmin342/xmin ymin188/ymin xmax756/xmax ymax534/ymax /bndbox /object /annotation看到这段结构你要关注三个关键点。第一是size节点下的width和height这是后期转YOLO格式时做归一化的分母一旦错误所有坐标全废。第二是name标签它决定类别映射关系如果原始数据集里类别名不止一种比如既有oil_stain又有scratch训练前要统一做类别ID映射。第三是bndbox里的四个值注意VOC用的是框的左上角和右下角坐标不是中心点加宽高。常见的做法是写一个Python脚本用xml.etree.ElementTree遍历整个标注目录做校验检查每个XML里filename字段对应的图片文件是否存在、图片实际尺寸是否和size节点一致。这个校验过程不需要额外装库十几行就能跑完但能避免后面训练时一大半样本因为路径问题被跳过。2.3 COCO的JSON结构和YOLO的TXT效率和直白的两个极端COCO格式把一整批数据的标注汇总在一个JSON文件里顶层结构分images、annotations、categories三段。images段是一个列表每项包含图片的id、file_name、width、heightannotations段是核心每个标注项含image_id、category_id、bbox四个数的列表、area、iscrowd等字段categories段定义类别ID到类别名的映射。这种设计的好处是按需读取训练框架像Detectron2和MMDetection都用它做标准输入但缺点是文件大了以后加载慢、人工查看困难一万张图的标注JSON轻松上几十兆。YOLO格式则是另一个极端每张图一个TXT文件名与图片同名。TXT里每行一个标注框空格分隔五个数类别ID、归一化中心点x、归一化中心点y、归一化宽、归一化高。五个数都是浮点边界框的绝对像素值和图片宽高在这个文件里完全看不到。用的时候心里得时刻装着图片尺寸否则光看TXT你根本不知道这个框在图上什么位置。三种格式的适用场景VOC适合人工校对和可视化XML树状结构用脚本改起来方便COCO适合多类别、需要统计类别分布的实验管理YOLO格式对齐模型训练吃进去直接开训。所以这个数据集三种都给其实是在降低你的接入成本——你不需要为换格式重写脚本省下的时间正好拿去调模型。2.4 格式互转的关键脚本逻辑一个Python函数讲清楚不管数据集给不给你转换脚本自己掌握互转逻辑是必须的。VOC转YOLO的核心就是把绝对坐标除以图片宽高代码逻辑如下import xml.etree.ElementTree as ET def voc2yolo(xml_path, img_width, img_height, class_map): tree ET.parse(xml_path) root tree.getroot() lines [] for obj in root.findall(object): name obj.find(name).text if name not in class_map: continue bndbox obj.find(bndbox) xmin float(bndbox.find(xmin).text) ymin float(bndbox.find(ymin).text) xmax float(bndbox.find(xmax).text) ymax float(bndbox.find(ymax).text) x_center (xmin xmax) / 2.0 / img_width y_center (ymin ymax) / 2.0 / img_height w (xmax - xmin) / img_width h (ymax - ymin) / img_height lines.append(f{class_map[name]} {x_center:.6f} {y_center:.6f} {w:.6f} {h:.6f}) return lines这段代码的核心是第10到13行所有坐标转换都在这里完成。除以img_width和img_height必须用浮点数Python 3里/默认就是浮点除法但如果你写成//就会得到整数归一化结果直接错。class_map是一个字典比如{oil_stain: 0, scratch: 1}它决定了类别名到数字ID的映射映射错误会在训练时表现为类别错位那种错误最难排查因为loss照样下降、mAP看着也还行但推理结果类别对不上。COCO转YOLO的逻辑稍微绕一点因为JSON里bbox的存储形式是[x, y, width, height]不是左上右下。转换时x_center等于bbox[0] bbox[2] / 2再除以图片宽度y_center同理用bbox[1] bbox[3] / 2除以高度宽高直接就是bbox[2] / img_width和bbox[3] / img_height。我一般会写一个双向转换的脚本放在工程里既能VOC转YOLO也能YOLO转VOC因为后面做预测结果可视化的时候经常需要把YOLO输出的框转回绝对像素坐标画在图上。这个反向转换就是乘回去容易忽略的是取整画图用matplotlib时不取整没关系但如果要用OpenCV的rectangle画框坐标必须是整数否则会报错。3. 划分脚本怎么做训练集、验证集、测试集的正确分法3.1 划分的本质是保证三个集合不重叠、分布一致很多初学者以为划分数据集就是把文件随机挑一部分出来分成三份放文件夹里。这么做没毛病但工业缺陷检测里有两个细节必须处理否则你的模型评估结果没有参考价值。第一个是图片级别的去重同一张图在采集时可能拍了多帧连续帧之间背景几乎一样、缺陷位置可能只差几个像素如果按文件名随机划分相邻帧可能被分到训练集和验证集里模型在验证集上表现虚高因为它在训练时已经见过几乎一模一样的图。第二个是类别分布的均衡性如果油污缺陷只在某个光照条件下出现随机划分可能导致所有难样本都进了训练集、验证集全剩下简单的或者反过来。判断一个划分脚本好不好用第一看能不能设随机种子保证每次运行结果一致第二看支不支持按类别比例分层采样而不是纯随机第三看输出有没有报告文件记录每个集合里图片数量和类别分布。这个数据集自带的划分脚本我不清楚具体实现但按行业通用做法它的功能应该覆盖了以上三点。拿到手先别急着跑花两分钟看它的输出格式再决定是直接用还是改成自己的版本。3.2 按目录划分还是按文件划分影响的是后续增量迭代常见的划分方式有两种。第一种是物理划分脚本创建train、val、test三个文件夹把图片和对应标签按比例复制或移动进去训练时data.yaml直接指向这三个目录。这种方式优点是目录结构直观人眼检查样本容易缺点是如果要迭代数据集、加新样本需要重新执行划分脚本否则新样本无法进入训练集。第二种是文件名清单划分脚本只生成三个TXT文件里面分别记录训练集、验证集、测试集的文件名列表实际文件原地不动训练时通过读取train.txt和val.txt来加载数据。这种方式在YOLOv5和YOLOv8里都支持好处是增量迭代快新样本加到数据目录后只需把新文件名追加到对应清单里不需要搬文件。我一般推荐第二种因为工业项目里数据集是活的产线随时可能补充新缺陷样本用清单方式划分省去文件复制的时间和磁盘占用。import random import os from collections import defaultdict random.seed(42) img_dir images label_dir labels train_ratio, val_ratio, test_ratio 0.7, 0.2, 0.1 all_imgs [f for f in os.listdir(img_dir) if f.endswith(.jpg)] random.shuffle(all_imgs) n_total len(all_imgs) n_train int(n_total * train_ratio) n_val int(n_total * val_ratio) train_files all_imgs[:n_train] val_files all_imgs[n_train:n_train n_val] test_files all_imgs[n_train n_val:] with open(train.txt, w) as f: for name in train_files: f.write(os.path.join(img_dir, name) \n)这段脚本是最基础的按比例划分第3行random.seed(42)是关键注释已经标了。seed的值随便设一个整数运行时固定即可这样多次划分结果完全一致实验可复现。第17行的os.path.join(img_dir, name)写入的是图片的完整路径有些训练框架要求写绝对路径有些相对路径也能跑这取决于你的data.yaml怎么配。这里要留意stu_train和stu_val两个集合的图片数量如果你的类别是长尾分布只做简单随机尾部类别可能直接消失。这时候可以改成分层采样先按类别把所有样本分组再在每个组内按比例划分最后合并各组结果。3.3 划分前必须做的三个检查跑划分脚本之前有几个检查不能跳过。第一个是标签和图片的配对检查遍历所有TXT或XML确认每个标注文件都有对应的图片文件多标的、漏标的都列出来。第二个是空标注检查YOLO格式的TXT如果文件大小为0代表这张图没有标注框训练时遇到这样的样本模型会学到一个纯背景输出这类样本在划分时要单独处理——要么放进一个ignore列表要么只在训练集出现而验证集不放否则会拉低验证指标。第三个是类别ID连续性检查YOLO的类别ID必须从0开始连续编号如果原始数据里类别ID有跳号比如只有0和2没有1训练会直接报错。我拿到新数据集第一件事不是训练而是写一个统计脚本输出每个类别的样本数量、每张图的平均标注框数、标注框面积分布。这些统计数字决定了我后面的模型优化方向如果油污缺陷的框普遍很小说明需要调整anchor尺寸或者提高输入分辨率如果某个类别样本特别少就得考虑数据增强或类别权重。这套统计逻辑用CLIP的文本编码器做视觉特征分析也行但直接读标注文件更简单可靠没必要绕弯。4. 从零跑通YOLO训练环境、预训练权重和关键参数怎么设4.1 环境配置YOLOv5还是YOLOv8以及CUDA版本的坑用这个数据集训练油污检测选哪个YOLO版本是个绕不开的问题。YOLOv5的最大优势是生态成熟网上教程多Ultralytics的库一直在维护遇到报错搜一下基本能解决YOLOv8则引入了C2f模块和更灵活的head设计小目标检测和训练速度上有提升但部分自定义改动的资料相对少。我的建议是如果你之前跑过YOLOv5就继续用v5如果新上手直接用v8因为它们的核心训练流程相似无非是配置文件格式略有差异。环境配置上最常见的翻车点是CUDA和PyTorch版本不匹配。YOLOv5在PyTorch 1.8到2.x之间基本都兼容但如果你用的显卡是V100这种老一代架构注意CUDA版本别上11.8以上实测V100在CUDA 12.x下训练速度反而下降。环境配置命令一般是这样conda create -n yolo_oil python3.10 conda activate yolo_oil pip install torch torchvision --index-url https://download.pytorch.org/whl/cu118 pip install ultralytics这里cu118对应CUDA 11.8如果你的显卡驱动支持更高版本可以换成cu121但注意驱动版本要跟上。第4行pip install ultralytics会同时装好YOLOv8和基础依赖YOLOv5的管道是分开装requirements.txt本质差不多。装完后跑一句python -c import torch; print(torch.cuda.is_available())输出True才算环境OK这一步别跳过GPU不可用还硬着头皮训练的人不在少数。4.2 预训练权重怎么选COCO预训练还是从头训练训练油污检测模型强烈建议下载YOLO预训练模型下载的COCO权重做迁移学习不要从头训练。油污缺陷虽然和COCO的80类物体没有交集但预训练权重在ImageNet或COCO上学到的低级特征——边缘、纹理、色彩梯度——对油污这种无定形缺陷仍然有效。用COCO预训练权重初始化后模型只需要在最后几层做适配收敛速度快很多数据量小的时候泛化也更好。# YOLOv5 python train.py --data oil.yaml --weights yolov5s.pt --epochs 100 --batch-size 16 --imgsz 640 # YOLOv8 yolo detect train dataoil.yaml modelyolov8s.pt epochs100 imgsz640 batch16两条命令的modelyolov5s.pt和yolov8s.pt都是自动下载COCO预训练权重的入口网络不通时得手动下载后放到对应目录。yolov5s.pt里的s是模型规模s代表small后面还有m、l、x依次变大。油污检测这种单类别任务s或m就够了l和x参数多、训练慢、在GPU显存不够时还容易OOM没必要。4.3 data.yaml的编写路径、类别数和类别名的正确姿势训练前必须准备一个data.yaml内容决定了模型读什么数据、预测什么类别。一个针对油污检测的YAML长这样train: ./train.txt val: ./val.txt nc: 1 names: [oil_stain]第1行和第2行的train和val指向划分脚本生成的TXT文件也可以用目录路径两种写法YOLO都支持。第3行nc是类别数油污检测通常只有一类就填1。第4行names是类别名列表顺序必须和标注里类别ID对应如果你数据集里除了油污还有锈蚀、划痕等nc改成对应数量names列表依次补上。这里最容易犯的错是只改names不改nc或者names顺序和标注里的类别ID顺序不一致后果是模型输出的类别标签张冠李戴。4.4 训练参数的设置逻辑epochs、batch-size、imgsz和anchor训练参数有四个必须理解到位epochs、batch-size、imgsz、anchor。epochs是训练轮数油污检测任务我一般跑100轮如果验证集loss还在稳步下降就加到150轮不要无脑跑300轮时间成本高且容易过拟合。batch-size受显存限制V100 16G跑yolov8s的640分辨率batch设为16比较稳再高容易OOMOOM时先降batch而不是降分辨率。imgsz是输入分辨率油污缺陷如果普遍偏小建议用768甚至960分辨率上去对小目标的召回率有肉眼可见的提升训练时间也相应翻倍这个取舍要看你的产线需求。anchor的设置在YOLOv5和v8里已经自动化了训练时会自动从数据里聚类出预设anchor一般不需要手动改。但如果你发现模型的recall一直上不去、训练日志里的best_mAP_05卡在某个值不动可以看看是不是anchor尺寸和油污框的真实尺寸差距过大极端情况下需要手动关掉autoanchor、按数据集的框尺寸分布重新聚类。这个情况在油污检测里确实存在因为油污经常是一条细长的带而不是方方正正的块标准anchor对这种细长形状覆盖不好。训练过程中最值得监控的不是mAP而是三部分loss——box_loss、cls_loss、dfl_loss——的变化曲线。油污检测只有一类cls_loss变化通常平缓主要看box_loss和dfl_loss是否同步下降。如果你看到loss在某一轮突然跳高然后回不去十有八九是学习率策略出了问题或者训练集里混入了标注错误的样本。这时候用--resume从崩溃前的权重继续训练是唯一靠谱的后悔药。5. 油污检测训练避坑指南五个让模型翻车的常见问题5.1 标注框太小导致小目标漏检模型学到的是背景现象训练完成后mAP看着不错但到产线实测距离稍远的油污点完全检测不到而训练集里的图片大都是近距离拍摄的。原因油污检测的标注框经常只有整张图的2%到5%大小属于典型的小目标。YOLO的检测头在特征图的深层输出上对小目标不敏感如果标注框面积占比过小模型学到的特征容易被背景淹没。解决最直接的手段是把imgsz从640提高到960让油污在输入图像上占据更多像素配合马赛克增强但注意YOLOv5的mosaic增强在小目标场景下可能导致目标被裁掉一半需要同时开启copy_paste增强混合粘贴油污区域到不同背景。另一个思路是用YOLO的P2输出层——也就是在更深一层的特征图上做检测YOLOv8里通过修改model配置文件增加一个小目标检测头实测能把小目标recall提升5到8个百分点。5.2 训练中BN崩溃loss变成NaN模型权重全废现象训练跑到第23轮loss突然变成nan之后所有指标归零整个训练白跑。原因BN崩溃的根源在于batch size太小或学习率过大。工业数据集如果显存限制把batch压到4以下BN统计的均值和方差抖动剧烈容易在某个batch上计算到极端值随后数值溢出。油污图片本身反光区域亮度极端如果恰好在某个batch里几乎全是这类高反光图BN的方差估计会爆炸。解决如果batch size只能维持4或8把normalization层从BN换成GN也就是GroupNorm它不依赖batch内统计量小batch下更稳定。或者用累积梯度的方式等效增大batch sizeYOLOv8里通过--accumulate参数可以凑够等效batch。还有就是学习率调低一个量级比如从0.01降到0.001BN对学习率比对模块结构更敏感。5.3 混淆矩阵总和不为1评估指标的误读现象训练结束后输出的混淆矩阵每一行加起来不是100%看起来像bug有人甚至怀疑评估脚本坏了。原因混淆矩阵的每一行代表真实类别每一列代表预测类别当置信度阈值调低时同一个真实框可能同时被多个预测框命中导致单行总和超过100%反过来阈值调高部分真实框没有任何预测命中行总和低于100%。解决这不是bug是阈值效应。看混淆矩阵时要先确认你关注的阈值YOLO默认输出的是在置信度0.25下的结果查看时把confusion matrix的归一化方式搞清楚是除以真实框总数还是除以预测框总数两种结果含义完全不同。在工业检测场景我更习惯看的是F1-Confidence曲线它直接给出不同置信度阈值下的F1分数用它来选择部署时的置信度阈值比看混淆矩阵更直观。5.4 油污高反光导致的误检把光照边缘当成了缺陷现象模型把金属表面的高光反射边缘识别成油污误检率奇高产线上每天触发几百次报警。原因油污在光照下呈不规则亮斑和金属表面正常的高光反射形态相似模型学到的是颜色和亮度的统计特征而不是油污的纹理特征。解决数据增强层面训练时把亮度扰动和对比度扰动的幅度调大让模型见过各种光照条件下的正负样本而不是只见过特定光照。更根本的解法是增加负样本把产线上大量无油污但有高光反射的图片打上背景标签放进训练集让模型学会区分高光反射和油污。这个数据集一万张图如果背景类别已经标注了还好如果没标自己补标一批负样本是值得的。5.5 训练集和验证集样本重叠导致指标虚高现象模型表现惊人验证集mAP达到0.99但拿到新拍的图片上一测效果远不如训练时的指标怀疑自己哪步做错了。原因前文说过划分时如果把同一批连续拍摄的图片拆到了训练集和验证集两个集合里存在高度相似的图验证集失去了独立评估的意义。油污数据采集往往是连续拍摄相邻帧之间差异极小。解决划分前先做去重。用感知哈希算法pHash或dHash都行计算每张图片的哈希值把相似度超过阈值的图片合并处理只保留其中一张作为样本。这一步放在划分脚本之前比任何训练参数调整都重要。我一般把去重阈值设在0.95这样连续帧基本都被合并场景差异大的图互不影响划分出来的验证集才是真正没见过的场景。6. 验证模型能不能上产线混淆矩阵之外你得看这三样东西训练完不等于模型能交付尤其是工业检测误检率直接关系到产线停不停机。我自己的验证习惯分三步第一看PR曲线下的面积也就是AP值要求油污类别的AP0.5到0.95不低于0.7低于这个数说明模型在严格IoU阈值下定位精度不足第二看F1-Confidence曲线找到F1最高点对应的置信度阈值这个阈值就是部署时的初始值第三是把模型跑在训练时没见过的产线视频上看视频里的表现而不是单张静态图。视频测试这个方法值得多说一句。单张图片测试只能看模型能不能检出油污视频测试能看模型的稳定性——同一块油污在连续帧里是不是会被断断续续地检出框的位置会不会来回跳动。如果检出结果不稳定可以给模型加上时序平滑用前后几帧的检测结果做投票或者用简单的EMA滤波平滑框的位置。油污在传送带上是动态的检测抖动会直接干扰下游的剔除机构这个问题不解决模型精度再高也没法上产线。最后一件事是导出模型做推理速度验证。用yolo export modelbest.pt formatengine device0导出TensorRT引擎在目标硬件上实测单张推理延迟。工业视觉的实时性要求通常在30到50毫秒内完成一帧检测如果超过这个范围就要考虑换更轻量的模型比如yolov8n加TensorRT或者降输入分辨率。这一整套验证流程走下来模型能不能交付你心里就有数了。一个我自己养成的习惯每次训练结束把最优权重、数据划分的随机种子、训练参数连同验证集的PR曲线图一起归档存成一份实验记录。三个月后回头改模型时这份记录比记忆可靠得多。模型的迭代不是一条直线数据和参数来回调整没有记录等于每次从头摸索。希望这篇能帮你在油污检测这条路上少走几段弯路。本文还有配套的精品资源点击获取