传送带皮带破损检测数据集:VOC格式与YOLO训练实践

📅 发布时间:2026/8/31 12:53:01
传送带皮带破损检测数据集:VOC格式与YOLO训练实践
简介本资源是一套面向工业视觉检测初学者与算法工程师的传送带皮带破损识别数据集聚焦输送系统关键部件的表面缺陷智能诊断问题适用于目标检测模型训练、工业AI质检项目实践及课程设计等学习场景。压缩包共1682个文件含700张JPG格式原始图像与700个对应VOC标准XML标注文件含边界框与损伤类型另有280个zbak备份文件、1个说明文档及1个嵌套ZIP整体体积68.16MB结构规范、开箱即用。目前已有132人下载学习适合开展YOLO/SSD/Faster R-CNN等主流检测框架的端到端训练实验。读者可直接加载训练集490图、验证集140图与测试集70图进行模型构建、超参调优与泛化性评估配套标注格式兼容主流开源工具链大幅降低工业缺陷检测任务的数据准备门槛。 传送带皮带破损检测这块我一直觉得是工业视觉里特别值得投入的场景。一条主运皮带动辄几十万上百万一旦出现撕裂没及时发现轻则漏料停产重则整条皮带报废甚至引发安全事故。以前老师傅靠眼睛看、靠手摸现在越来越多的工厂开始上视觉检测系统但真正卡住项目进度的往往是数据——不是算法选型而是没数据可用、没标注可用。最近我整理了一套基于VOC格式的传送带皮带破损检测数据集700张图像覆盖了撕裂、划伤、裂纹、磨损这几类典型破损形态标注文件全部按PASCAL VOC标准组织可以直接喂给YOLO系列、Faster R-CNN这类主流检测框架训练。这篇文章就围绕这套数据集把数据组织方式、标注细节、格式转换、训练配置、踩坑记录一次说清楚。1. 数据集设计思路与场景价值1.1 为什么传送带破损检测值得单独做一套数据传送带在矿山、港口、电厂、水泥厂、钢厂这些重工业场景里基本是“咽喉”级别的设备。它承担的是连续物料输送一旦停机整个产线跟着停。我见过一个案例某港口皮带因为一道30厘米的撕裂没有及时发现运行中直接撕开了一个大口子最后整条皮带更换加上停机损失几十万打底。这类事故的共性是破损是从小到大的前期只是一道划痕或小裂纹如果能在早期识别出来处理成本极低。视觉检测的难点在于传送带表面本身就有纹理、有接头、有物料残留破损区域和正常区域的对比度往往不高而且皮带是高速运动的光照条件也随现场环境波动。这意味着模型不能只靠“颜色差异”这种低级特征它得学会从纹理、边缘、形状这些更鲁棒的线索里判断破损。而要训练出这样的模型靠一两百张图是不够的700张是一个比较务实的起步量级——不多到难以标注也不少到模型学不到东西。1.2 破损类别的划分逻辑我在这套数据集里把破损形态分成几个典型类别每个类别对应不同的形成机理和视觉特征撕裂通常是尖锐物体刺入后皮带在运行中被拉裂形态是长条状开口边缘不规整往往贯穿皮带表面或深入芯层。这类破损最危险需要最高优先级识别。划伤表面损伤深度较浅通常由物料中的硬质颗粒刮擦造成形态是细长线状沟槽宽度小但可能很长。划伤容易和皮带表面的正常纹理混淆。裂纹皮带在反复弯曲、拉伸的循环应力作用下表面出现龟裂或横向裂纹形态是短线状或网状常见于皮带接头附近和滚筒过渡区。磨损/剥落长期运行导致表面橡胶层变薄、起毛、局部脱落形态是片状区域边界模糊灰度变化平缓最考验标注功力。把这个分类逻辑讲清楚是为了说明一点类别的设定不是拍脑袋而是基于设备维护的诉求。工业检测里把“需要立即停机的撕裂”和“可以计划性检修的磨损”区分开比笼统地标一个“破损”有意义的得多。1.3 VOC格式为什么是这套数据的首选VOC格式源自PASCAL VOC挑战赛是一种以XML文件描述图像标注信息的数据组织方式。它本身并不复杂但好在生态成熟LabelImg、LabelMe这些标注工具原生支持导成VOC格式YOLO、SSD、Faster R-CNN等主流框架都有现成的VOC格式读取接口或转换脚本而且XML文件是纯文本写脚本检查、统计、纠错都很方便。我之前也用过纯TXT的YOLO格式直接标注但后来发现一个很实际的问题如果标注到一半发现某个框的坐标有问题或者想批量调整某个类别的标签纯TXT文件里只有归一化坐标和类别ID人工查错非常痛苦。VOC格式的XML里不仅有坐标还保留了图片尺寸、文件名、类别名这些人类可读的信息排查问题的时候直观很多。所以这套数据集我坚持用VOC作为“母版本”需要YOLO格式的时候再通过脚本转换而不是一开始就做成YOLO格式。2. 数据集的目录结构与标注规范2.1 标准目录组织方式这套数据集按照VOC的标准目录结构组织方便后续工具链直接使用conveyor_belt_voc/ ├── JPEGImages/ ├── Annotations/ ├── ImageSets/ │ └── Main/ │ ├── train.txt │ ├── val.txt │ └── test.txtJPEGImages存放原始图像命名统一为6位数字补零比如000001.jpg到000700.jpg这样排序、索引都方便。图像分辨率以1920x1080为主个别现场采集的图片因为相机型号不同会有差异但都保证标注框坐标和图像尺寸严格对应。Annotations目录下是与JPEGImages同名的XML文件每个XML对应一张图片的完整标注信息。ImageSets/Main下面放的是数据集划分文件每个txt文件里一行一个图片编号不含扩展名。实际使用中train/val/test的划分建议按7:2:1来做也就是490张训练、140张验证、70张测试。划分时要注意按场景和破损类型做分层抽样别让某一种破损形态全跑到测试集里去了否则评估出来虚高落地时一塌糊涂。2.2 XML标注文件的字段解析一个典型的VOC XML文件长这样annotation folderJPEGImages/folder filename000145.jpg/filename path/data/conveyor_belt_voc/JPEGImages/000145.jpg/path source databaseConveyor Belt Damage Dataset/database /source size width1920/width height1080/height depth3/depth /size segmented0/segmented object nametear/name poseUnspecified/pose truncated0/truncated difficult0/difficult bndbox xmin412/xmin ymin238/ymin xmax689/xmax ymax317/ymax /bndbox /object object namecrack/name poseUnspecified/pose truncated0/truncated difficult0/difficult bndbox xmin1203/xmin ymin856/ymin xmax1310/xmax ymax884/ymax /bndbox /object /annotation这里有一个容易忽略的坑就是path字段。如果你用LabelImg标注它默认会把本地绝对路径写进XML的path节点。同一个数据集换一台机器跑训练这个路径就对不上了虽然很多框架读取VOC时不会强依赖这个字段但保险起见我建议在发布或迁移数据集时把所有XML里的path字段统一改成相对路径或者干脆删掉。另一个关键字段是difficult。VOC标准里difficult标记为1表示该目标本身是清晰可辨的但因为遮挡、极小尺寸等情况导致识别难度很大。在评估时这个目标会计入“困难样本”而不会影响mAP计算。工业检测数据里我建议不要轻易把目标标成difficult因为实际部署时你可能希望模型对困难样本也有一定的检出能力把它标成difficult等于在训练评估时“放它一马”这跟工业场景“漏检零容忍”的诉求是冲突的。2.3 标注框设计原则与坐标规范标注质量直接决定模型上限这一点怎么强调都不过分。我在标注这套数据时定了几条硬规矩紧贴目标外接矩形标注框要刚好框住破损区域留白尽量少。太松的框会把背景纹理学进去太紧的框会截断破损边缘这两种情况都会让模型学歪。分离粘连破损当多个破损区域距离很近、甚至视觉上有交叉时只要它们属于不同的破损形态就分别标注如果实在连在一起无法区分边界就合并成一个框类别取更严重的那类。遮挡处理皮带表面有物料覆盖、破损只有一部分露出来时只标注可见的破损区域。不要脑补完整破损的范围模型只该学它能看见的东西。忽略过小目标对于像素面积小于大约20x20的疑似破损点标注意义不大模型学不进去还容易引入噪声直接跳过。坐标规范上VOC格式要求xmin/ymin是边界框左上角坐标xmax/ymax是右下角坐标均使用像素整数坐标坐标系原点在图像左上角。注意不同格式的坐标定义有差异比如COCO格式的边界框是x, y, width, height而YOLO格式是归一化的中心点坐标加宽高。做格式转换时一定要先搞清楚各个坐标系定义再动手写代码。3. 数据预处理与VOC到YOLO的格式转换实操3.1 训练前的数据质量检查拿到数据集第一件事不是急着训练而是做数据体检。我自己写了一个检查脚本主要看几个维度图片与XML是否一一对应、XML里是否有超出图片边界的坐标、类别标签是否有拼写错误、是否出现宽或高为零的空框。import xml.etree.ElementTree as ET import os from PIL import Image voc_root conveyor_belt_voc jpeg_dir os.path.join(voc_root, JPEGImages) ann_dir os.path.join(voc_root, Annotations) errors [] for xml_name in os.listdir(ann_dir): if not xml_name.endswith(.xml): continue xml_path os.path.join(ann_dir, xml_name) tree ET.parse(xml_path) root tree.getroot() filename root.find(filename).text img_path os.path.join(jpeg_dir, filename) if not os.path.exists(img_path): errors.append(f{xml_name}: image {filename} not found) continue with Image.open(img_path) as img: img_w, img_h img.size size_node root.find(size) xml_w int(size_node.find(width).text) xml_h int(size_node.find(height).text) if xml_w ! img_w or xml_h ! img_h: errors.append(f{xml_name}: size mismatch XML({xml_w}x{xml_h}) vs IMG({img_w}x{img_h})) for obj in root.iter(object): name obj.find(name).text bnd obj.find(bndbox) xmin float(bnd.find(xmin).text) ymin float(bnd.find(ymin).text) xmax float(bnd.find(xmax).text) ymax float(bnd.find(ymax).text) if xmax xmin or ymax ymin: errors.append(f{xml_name}: invalid bbox ({xmin},{ymin},{xmax},{ymax})) if xmin 0 or ymin 0 or xmax img_w or ymax img_h: errors.append(f{xml_name}: bbox out of range ({xmin},{ymin},{xmax},{ymax})) if errors: print(Found errors:) for e in errors: print( , e) else: print(All checks passed.)这种检查脚本看起来简单实际用起来特别省心。我有一个惨痛教训早前用过一套别人给的数据集训练的时候loss下降很漂亮但mAP一直上不去查了大半天发现XML里有一批图片的size字段写错了导致归一化坐标全部偏移。如果一开始就跑一遍质量检查能省下半天时间。3.2 VOC转YOLO的完整脚本训练YOLO系列模型时需要把VOC标注转成YOLO格式的txt文件。转换逻辑不复杂核心就是坐标映射import xml.etree.ElementTree as ET import os class_names [tear, scratch, crack, wear] def voc_to_yolo(xml_file, class_names, out_dir): tree ET.parse(xml_file) root tree.getroot() size root.find(size) img_w int(size.find(width).text) img_h int(size.find(height).text) lines [] for obj in root.iter(object): name obj.find(name).text if name not in class_names: print(fWarning: unknown class {name} in {xml_file}) continue class_id class_names.index(name) 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) # 越界防护将坐标截断到有效范围内 xmin max(0, xmin) ymin max(0, ymin) xmax min(img_w, xmax) ymax min(img_h, ymax) x_center (xmin xmax) / 2.0 / img_w y_center (ymin ymax) / 2.0 / img_h w (xmax - xmin) / img_w h (ymax - ymin) / img_h # 防止除零或负数 if w 0 or h 0: continue lines.append(f{class_id} {x_center:.6f} {y_center:.6f} {w:.6f} {h:.6f}) if lines: base_name os.path.splitext(os.path.basename(xml_file))[0] out_path os.path.join(out_dir, base_name .txt) with open(out_path, w) as f: f.write(\n.join(lines))转换脚本里有几个细节值得注意。第一是越界防护。标注软件偶尔会生成超出图像边界的坐标如果不做截断归一化后可能出现大于1的坐标值训练时直接报错或产生NaN梯度。第二是空文件处理。如果一张图没有任何有效标注转换后的txt文件是空的。用Ultralytics YOLO训练时空的标签文件不会报错但会在加载时跳过该图——这可能导致你的数据集实际参与训练的图片数少于预期评估时变成“没有预测任何目标”拉低指标。第三是类别顺序一致性。YOLO格式的txt里第一个数字是类别ID这个ID必须和训练用的data.yaml里的类别顺序严格一致否则模型会把“撕裂”学成“划伤”全部错位。3.3 数据集划分与备份策略VOC格式的ImageSets/Main目录下的txt文件只记录图片编号但很多训练脚本需要的是图片或标注文件的完整路径列表。我习惯在划分时直接用脚本生成一份train.txt内容为JPEGImages下的完整相对路径方便直接喂给一些自定义训练管线。数据集划分完建议再做两件事生成一份标注统计表统计每个类别的目标数量、每张图的平均目标数、图像尺寸分布。这些数据能帮你快速判断类别是否平衡、目标尺度是否单一。给每个划分做副本备份尤其是测试集它评估一次就“脏”一次——如果你用测试集做误差分析再调参等于把测试集信息泄漏进了模型选择过程。所以测试集一旦定下来就不要反复去看它的具体标注只保留最终评估用。4. 基于YOLOv8的训练配置与参数调优4.1 数据集配置与目录准备用Ultralytics YOLOv8训练时先准备一份data.yaml# conveyor_damage.yaml path: ./conveyor_belt_voc train: images/train val: images/val test: images/test nc: 4 names: 0: tear 1: scratch 2: crack 3: wear注意path字段建议用相对路径这样整个项目文件夹拿到哪台机器都能跑不用改配置。images/train表示相对于path目录下的images/train文件夹里面放图片而Ultralytics会自动在同级的labels/train找对应的txt标签文件。所以转换完YOLO格式后目录结构需要整理成这样conveyor_belt_voc/ ├── images/ │ ├── train/ │ ├── val/ │ └── test/ ├── labels/ │ ├── train/ │ ├── val/ │ └── test/ └── data.yaml这里有一个容易被坑的点Ultralytics框架对图片和标签的目录结构要求是一一对应的如果图片在images/train/000001.jpg标签必须在labels/train/000001.txt文件名要完全一致只差扩展名。目录结构错了训练会直接报错或者静默跳过全部图片刚开始用的人经常卡在这一步。4.2 模型选型与训练参数对于700张这个量级的数据集我的建议是不要直接上YOLOv8x或者YOLOv9这种大模型。数据量摆在那里大模型容易过拟合训练时间还长。比较务实的选择是YOLOv8s或YOLOv8n用预训练权重做迁移学习效果通常比从零训练好得多。训练命令参考yolo detect train \ dataconveyor_damage.yaml \ modelyolov8s.pt \ epochs150 \ imgsz640 \ batch16 \ patience20 \ augmentTrue \ mosaic1.0 \ fliplr0.5 \ hsv_h0.015 \ hsv_s0.7 \ hsv_v0.4参数说明epochs150700张图不算多150个epoch足够模型充分迭代配早期停止机制防止过拟合。patience20验证集指标连续20个epoch不提升就提前停止。imgsz640YOLOv8默认的输入尺寸工业场景下640在检测精度和推理速度之间比较均衡。mosaic1.0马赛克增强默认开启对小数据集很有用能大幅增加样本多样性。fliplr0.5水平翻转。但要注意如果传送带破损具有明显的方向性——比如撕裂总是沿皮带运行方向——那水平翻转会改变裂纹的方向语义。这个要看实际情况决定是否开启。我在实际训练中发现一个有意思的现象加了hsv色彩增强之后模型对光照变化的鲁棒性提升明显。因为传送带检测现场的光照通常不稳定自然光和灯光的色温差异大HSV扰动相当于让模型见过更多“配色方案”。4.3 评估指标与结果解读训练完成之后重点看这几个指标mAP0.5IoU阈值0.5下的平均精度这是衡量“粗定位”能力的指标。工业场景里如果mAP0.5能达到0.85以上基本就可以考虑做初步的现场验证。mAP0.5:0.95IoU从0.5到0.95按0.05步长取平均这个指标更严格衡量的是“精定位”能力。对破损检测来说很多应用不要求像素级精准框稍微大一点没问题所以这个指标参考价值略低于mAP0.5。Precision/Recall这两个要结合来看。皮带破损检测场景下漏检的代价远高于误检所以我会更关注Recall甚至在调参时宁可牺牲一点Precision也要保证Recall足够高。另外训练完成后一定要看混淆矩阵。如果发现“crack”经常被识别成“scratch”说明这两个类别在视觉特征上确实难以区分可能需要重新审视标注标准——它们是不是本来就是同一种东西的不同表达。这种情况在工业标注里很常见标注人员的主观判断会影响类别边界。4.4 小数据集防过拟合的三个技巧700张图训练深度学习模型过拟合是大概率事件。我常用三个技巧压制迁移学习用COCO预训练权重初始化模型已经学会了通用的边缘、纹理、形状特征只需要在传送带数据上做微调。这是小数据集下最有效的手段。冻结骨干网络前几层刚开始训练时冻结backbone的底层参数只训练检测头。训练几十个epoch后再解冻全部参数做微调。这样做能避免小数据集把预训练特征“冲掉”。强数据增强除了YOLOv8内置的增强我还会在训练前用脚本对图像做离线增强随机裁剪、旋转±10度、亮度对比度扰动。传送到模型里的有效样本量相当于翻了好几倍。5. 训练与部署中的常见问题排查5.1 标注与数据问题问题表现可能原因排查方法训练loss正常但mAP极低类别ID与data.yaml顺序不一致检查转换脚本的class_names列表顺序模型只检出大破损漏掉小破损目标尺度差异大小目标特征弱提高输入分辨率检查小目标标注数量验证集指标很高现场效果差测试集与现场光照/角度差异大采集更多现场图像补充数据训练时提示unable to load image图片文件损坏或路径错误用PIL逐张检查图片可读性一类的目标全部没检出该类别标注数量太少统计类别数量做重采样或补充标注标注数据时还有一个容易忽视的问题标注框的一致性。比如同一个人标注“撕裂”时有的框是紧贴边缘的有的是留了一圈背景的这种不一致会让模型在定位时“模棱两可”。我一般会让标注人员先标注30张我检查一遍没问题之后再继续避免返工。5.2 训练过程问题训练集只有700张时loss曲线偶尔会出现“断崖式下跌”或“突然飙升”的情况。前者通常是因为某个批次里出现了大量相似的破损样本模型从这个强信号里学了一把后者通常是学习率过大或者数据增强太激进。我的建议是不要因为单次波动就停止训练观察整个趋势。如果loss持续不降再考虑降低学习率。如果训练过程中发现验证集mAP一直不涨但训练集mAP已经很高那就是典型的过拟合信号。果断采用早停策略同时加强数据增强。还有一个容易被忽略的因素验证集划分是否合理。如果验证集里全是某种特定光照条件下的图片而训练集里没有模型在验证集上自然表现差。这时候不是模型的问题是数据划分的问题。5.3 推理部署问题模型部署到现场时最常见的问题是推理速度不足。皮带运行速度很快相机帧率可能达到30fps甚至更高如果检测模型跑不到实时就只能在关键帧上抽样检测。这时可以考虑换更轻量的模型YOLOv8n、降低输入分辨率、用TensorRT或ONNX Runtime做加速。另一个现场常见问题是误检率高。皮带表面有水渍、油污、物料残留这些都很容易被模型判成破损。降低误检的思路有几个提高置信度阈值比如从0.25调到0.45、在检测结果上做时序滤波连续多帧都检测到才算数、裁剪一个固定ROI区域只检测皮带边界内的区域。最后一种方法在固定安装的工业相机上特别有效因为皮带区域在画面里的位置基本是固定的。5.4 数据迭代的闭环思路700张数据集不是终点而是起点。我建议在模型部署后建立一套“数据回流”机制现场检测到的误检漏检样本定期收集回来人工复核后加入数据集重新训练。每个月更新一次模型半年的时间里数据量就能翻倍模型精度也会有肉眼可见的提升。这个闭环比一开始追求几千张数据更实际——你无法预知现场会遇到的所有情况但你可以从错误中持续学习。这条数据迭代路径也是这套700张VOC数据集最大的价值所在它不追求一次性做到完美而是给你一个高质量、高可靠性的起点让你在后续迭代中不断完善。6. 实操过程中的补充经验最后再分享几个我在处理这类数据集时积累的小经验。第一标注工具的选择。LabelImg简单够用但它的问题是大图加载慢、多人协作不方便。如果数据量继续涨到几千张建议切换到Roboflow或者X-AnyLabeling这类支持在线协作和半自动标注的工具效率能提升不少。第二标注管理要用版本思维。数据集每次修复、增补后我都会用日期生成一个版本号比如conveyor_voc_20250518记录当次修改了什么。没有版本管理数据集很快就会陷入“改来改去不知道哪个是最新版”的混乱。第三保留一份原始图像不做任何预处理。有人习惯直接对图像做缩放、裁剪后再标注这样会导致XML里的坐标和原图对不上。我始终坚持标注用的图像、训练用的图像、发布的数据集图像始终是同一份未处理的原始版本所有预处理缩放、增强、格式转换都在训练脚本里实时完成。说到这套700张VOC格式传送带皮带破损检测数据集它最让我满意的地方在于每一张图像的标注都经过了我人工复核坐标精度、类别归属都经得起推敲。如果你正准备做皮带破损检测的落地项目或者正在搭建你自己的工业缺陷检测数据集这套数据的组织方式和处理流程可以直接照搬。拿过来先跑通训练链路再逐步扩展自己的数据这是最省力也最能避免踩坑的路径。本文还有配套的精品资源点击获取