皮带破损检测数据集制作与YOLOv8训练实战指南
简介面向工业质检、设备维护等场景的传送带皮带破损检测数据集基于700张原始图片完成YOLOv8格式标注可用于训练识别传送带表面的破损、裂口等缺陷是目标检测模型训练与验证的实用基础数据。压缩包共1401个文件包含700张jpg原始图像、700个txt标注文件和1个yaml配置文件整体大小约68.75MB目录结构清晰便于图片与标签配对使用。其中txt文件保存了YOLOv8所需的类别编号与归一化坐标信息yaml文件定义了数据集路径及类别名称解压后即可接入常见训练流程。目前已有613人浏览学习适合需要快速获取真实工业视觉样本、进行皮带破损检测模型训练或算法验证的读者。数据组织清晰图片与标注一一对应便于转换为其他检测框架的格式也可作为进一步扩充数据集的基础。1. 皮带破损检测数据集700张原图真的够用吗做过工业视觉的人都知道产线上最头疼的不是算法选型而是数据从哪来。传送带皮带破损检测这类项目现场拍回来的原始图片往往只有几百张缺陷样本更是稀少找公开数据集基本没戏。这套针对700张原始图片做YOLOv8格式标注的数据集解决的就是这个冷启动问题把小样本变成能直接扔进训练脚本的规范数据集。它适合两类人——一类是做输送带视觉巡检的工程师想用YOLOv8在本地快速验证破损检测可行性另一类是刚接触目标检测的数据新手想拿一份完整标注数据走通labelme标注到训练的全流程。先说结论700张图不算多但配合数据增强和合理的标注策略训练出的模型在固定工位场景下完全能跑到实用水平关键在于标注一致性和验证集划分。2. 标注规范先行破损类别定义与labelme实操2.1 破损类别怎么定撕裂、磨损、划伤的三分类边界拿到700张原始图片第一步不是打开标注工具就画框而是先定类别。皮带破损在视觉上差异很大长条形的撕裂、大面积的表面磨损、细线状的划伤如果全部标成一类模型学到的特征会互相干扰。常见做法是分成三类tear代表撕裂特征是有明显开裂边缘、通常沿皮带运行方向延伸wear代表磨损表现为表面材料剥落、颜色发白或发暗、边缘不规则scratch代表划伤细长条、深度浅、宽度窄。三分类的好处是互相之间特征重叠少YOLOv8在小样本下更容易收敛。如果你的产线皮带只有一种典型破损形态也可以合并成一类但建议先按三类标训练完看混淆矩阵再决定是否合并。标注框的绘制也有讲究。撕裂和划伤用倾斜的细长矩形贴合缺陷走向比正矩形更准确但labelme默认是正矩形实际标注时我习惯把框稍微放大一点把缺陷周边的过渡区域也包进去这样模型学习到的不是一条细线而是一个有上下文的区域特征。磨损区域则按实际面积画框不要刻意框满整个磨损带框住最明显的核心区域就好。这700张图里如果单张图片出现多个同类型缺陷全部标出来不要只标最明显的那个——YOLOv8训练时需要正样本的多样性漏标等于主动制造false negative。2.2 labelme标注流程与JSON导出从画框到生成标注文件的完整操作标注工具我推荐labelme它是目前转YOLOv8格式最顺手的工具之一装起来快标注界面直观。安装和启动命令pip install labelme labelme --labels labels.txt --nodatalabels.txt里按行写入类别名tear、wear、scratch。启动后左侧工具栏选Create Polygons或Create Rectangle在图片上框出缺陷区域弹窗里选择对应类别。每张图标注完按CtrlS保存会生成一个与图片同名的JSON文件。--nodata参数很有用它让JSON文件里不嵌入图片的base64数据体积小很多批量处理时读写更快。标完一个批次后检查一下labels.txt是否写入了正确类别名以及JSON里shapes数组的长度是否和人工标注数量一致。一个常见的小坑是标注过程中手滑多画了一个框然后删除但labelme删除对象后有时不会自动清空shapes数组里的残留数据建议每次保存前用文本编辑器打开JSON看一眼结构或者写个小脚本统计每个文件的目标数量。2.3 标注质量自检700张图的人工复核要点标注质量直接决定模型上限算法工程师接手数据集时一定要做一轮复核。我一般按三个维度检查一是类别是否张冠李戴磨损标成撕裂这类问题在疲劳标注时频繁出现二是框是否贴合目标过大过小都会给训练带来噪声三是漏标率随机抽20%的图重新看一遍如果漏标的缺陷超过5个说明标注员的标准和需求方不一致需要重新对齐标准。有一个值得注意的现象皮带表面本身有纹理和接缝新手容易把正常接缝当成划伤标进去。解决的办法是在标注规范里写一条硬规则——只有破坏表面连续性的深色线条才算scratch接缝和纹理不算。这类边界情况最好在开始标注前找几张典型图片做一个标什么、不标什么的示例文档比口头沟通高效得多。3. 把labelme标注转成YOLOv8格式转换脚本与四个边界坑3.1 转换脚本与数据切分逻辑labelme保存的是JSON格式YOLOv8训练需要的是TXT格式的标签文件每行一个目标格式为class_id x_center y_center width height全部归一化到0~1。转换脚本是数据集构建的核心环节下面是一个可直接复用的Python脚本import json import os import random from pathlib import Path def labelme_to_yolov8(json_dir, output_dir, class_names): # 创建YOLO格式的labels目录 labels_dir Path(output_dir) / labels labels_dir.mkdir(parentsTrue, exist_okTrue) for json_file in Path(json_dir).glob(*.json): # 跳过没有对应图片的JSON img_name json_file.stem .jpg img_path Path(json_dir) / img_name if not img_path.exists(): print(f跳过: {img_name} 缺少图片文件) continue with open(json_file, r, encodingutf-8) as f: data json.load(f) img_w data[imageWidth] img_h data[imageHeight] txt_lines [] for shape in data[shapes]: label shape[label] if label not in class_names: print(f警告: {json_file.name} 含未知类别 {label}) continue class_id class_names.index(label) points shape[points] # labelme points是[[x1,y1],[x2,y2]]转换为x,y,w,h xs [p[0] for p in points] ys [p[1] for p in points] x_min, x_max min(xs), max(xs) y_min, y_max min(ys), max(ys) w x_max - x_min h y_max - y_min # 判断是否含有缺陷,图片有缺陷才生成标注文件 if w 0 and h 0: x_center (x_min w / 2) / img_w y_center (y_min h / 2) / img_h w_norm w / img_w h_norm h / img_h txt_lines.append(f{class_id} {x_center:.6f} {y_center:.6f} {w_norm:.6f} {h_norm:.6f}) # 只保留有目标的图片标注 if txt_lines: txt_path labels_dir / (json_file.stem .txt) with open(txt_path, w) as f: f.write(\n.join(txt_lines)) print(f转换完成, 有效标注文件已输出到 {labels_dir}) class_names [tear, wear, scratch] labelme_to_yolov8(labelme_json/, yolov8_dataset/, class_names)这个脚本的逻辑要点class_names列表的索引顺序决定了TXT文件里的class_id这个顺序必须和后续训练时YAML配置文件里的类别顺序完全一致否则模型训练时类别对应关系就是错乱的。归一化坐标全部保留6位小数精度足够。脚本里跳过没有目标框的图片因为YOLOv8训练默认不支持纯背景图的负样本训练空TXT文件反而可能触发数据加载错误。3.2 数据目录划分训练集、验证集、测试集的比例与放置规则YOLOv8要求数据集目录按images和labels两个顶层文件夹组织各自内部再分train和val子目录。700张图我建议按7:2:1划分训练集490张、验证集140张、测试集70张。测试集单独留出来的原因和分类任务不同——目标检测的测试集要模拟真实产线的没见过的新图验证集会参与模型调参放一起会被模型间接记住。import random from pathlib import Path import shutil src_images Path(images_raw) # 原始图片目录 src_labels Path(yolov8_dataset/labels) # 上一步转换出的标签目录 all_files list(src_images.glob(*.jpg)) random.seed(42) # 固定随机种子保证每次切分结果一致 random.shuffle(all_files) num_train int(len(all_files) * 0.7) num_val int(len(all_files) * 0.2) dirs { train: Path(dataset/images/train), val: Path(dataset/images/val), test: Path(dataset/images/test), } for d in dirs.values(): d.mkdir(parentsTrue, exist_okTrue) Path(str(d).replace(images, labels)).mkdir(parentsTrue, exist_okTrue) for i, img_path in enumerate(all_files): if i num_train: split train elif i num_train num_val: split val else: split test lbl_path src_labels / (img_path.stem .txt) if not lbl_path.exists(): continue shutil.copy(img_path, dirs[split] / img_path.name) shutil.copy(lbl_path, str(dirs[split]).replace(images, labels) / lbl_path.name)注意random.seed(42)这行很多入门教程不写固定种子每次切分结果都不同后面模型训练中途重启再复现结果就困难了。还有一个容易踩的坑如果你补标了一些新图再重新切分已经训练过的模型不要直接加载旧权重继续训因为数据分布变了旧权重里的anchor统计信息大概率和新分布不匹配。3.3 边界坑之一图像尺寸不一致导致归一化坐标漂移矿山和港口的皮带监控摄像头不一定全是2000万像素的工业相机有些是用旧的海康或大华网络摄像机抓拍的分辨率五花八门。如果原始图片里有不同分辨率混在一起转换脚本里imageWidth和imageHeight取的是JSON里的原始值归一化后坐标本身是自洽的但YOLOv8训练时会把输入统一resize到640x640不同原始分辨率被压到同一尺寸后缺陷的宽高比信息会发生不同程度的变化。实际表现是模型在训练集上loss很低验证集上mAP忽高忽低。解决思路是统一分辨率所有图片和标签一起resize到同一个尺寸再进训练管线。注意resize时标签坐标必须同步变换不能只改图片。另外如果原始图片不是标准的水平方向不要用角度旋转增强——皮带缺陷是方向敏感的旋转90度后撕裂和划伤的方向特征就变了。3.4 边界坑之二空标签文件与纯背景图皮带运行中大部分时间没有破损收集的原始图片自然有很多是正常的。这些图没有目标标注转换脚本不会生成对应的TXT文件训练集目录里图片和标签数量对不上轻则训练日志出现警告重则数据加载直接中断。YOLOv8在训练时会过滤掉没有标签的图片所以目录里存在纯背景图影响不大但如果你希望模型学会区分正常和破损而不是只在有缺陷的图上找框更合适的做法是单独做一个分类头或加一个正常类而不是硬塞空标签图。4. 用YOLOv8训练皮带破损检测环境搭建与三个必调参数4.1 本地训练环境搭建与数据配置YOLOv8训练不需要昂贵的A100一张GTX 1660 Ti或者RTX 3060就能跑得动640分辨率的小样本训练。环境搭建最稳的方式是conda建独立环境conda create -n yolov8 python3.10 -y conda activate yolov8 pip install ultralytics注意Python版本不要用3.12当前ultralytics对3.10和3.11的兼容性最稳3.12上个别依赖编译会翻车。安装完成后验证一下环境python -c from ultralytics import YOLO; model YOLO(yolov8n.pt); print(环境OK)如果第一次运行会自动下载yolov8n.pt预训练权重。数据集配置写在YAML文件里这是YOLOv8训练的核心入口。我习惯把配置放在项目的data.yaml中path: /home/user/conveyor_belt_dataset # 数据集根目录 train: images/train # 训练图片相对路径 val: images/val # 验证图片相对路径 test: images/test # 测试图片相对路径 nc: 3 # 类别数量 names: [tear, wear, scratch] # 类别名称path字段是坑最多的一个点——如果你的数据集目录换了位置path必须是绝对路径或相对当前工作目录的路径写错的话训练启动时会报Dataset not found或者静默跳过。另外nc和names必须与转换脚本里的class_names顺序一致这里一旦出错所有标注的class_id全部错位。4.2 训练命令与参数说明训练命令本身很简单但参数值的设定直接决定小样本训练的成败yolo train datadata.yaml modelyolov8s.pt epochs200 imgsz640 batch16 patience50模型规模选yolov8s而不是yolov8m或l700张图用大模型必然过拟合s模型在精度和泛化之间最平衡。patience50意思是连续50个epoch验证集指标不提升就早停小样本训练跑到一半就能触发省时间。imgsz640是IOU和mAP计算的基准尺寸不要改成1280虽然大图对小目标更友好但700张图的样本量根本喂不饱1280分辨率的模型。如果你的图像里缺陷很小比如只有十几个像素宽、几十个像素长64 0可能不够可以先按640跑一版看结果小目标效果差再启用YOLOv8的SAHI切片推理而不是直接拉高imgsz。4.3 训练监控与结果解读从loss曲线到混淆矩阵训练过程中需要盯三个关键输出。第一个是训练日志里的box_loss和cls_loss正常情况下两者都持续下降box_loss很快收敛到0.02以下说明框的拟合已经稳定。第二个是验证集mAP50和mAP50-95mAP50反映粗粒度定位是否准确mAP50-95对框和类别同时敏感破损检测场景mAP50达到0.85以上基本可用。第三个看混淆矩阵训练结束后在runs/detect/train/目录下能找到confusion_matrix.png如果tear和scratch之间出现明显混检说明这两类的视觉特征确实接近后面可以通过难例挖掘补充一些边界样本。有一条血泪经验训练完成第一时间看验证集上误检的样例图特别是把正常皮带纹理检测为scratch的false positive。工业场景中false positive比false negative更致命——皮带没有破损却报警停机运维人员几次下来就不信任这个系统了。5. 小样本训练的五个避坑点过拟合、类别不平衡与标注噪声5.1 过拟合的表现与数据增强参数调节700张图跑YOLOv8最典型的问题就是过拟合。现象很直观训练集mAP一路涨到0.99验证集mAP在0.6附近反复震荡上不去。解决手段按优先级排序依次是调高数据增强强度、减小模型容量、降低学习率。YOLOv8的增强参数集中在hyp.scratch.yaml里训练命令中可以直接覆盖yolo train datadata.yaml modelyolov8s.pt epochs200 batch16 \ hsv_h0.015 hsv_s0.7 hsv_v0.4 translate0.1 scale0.5 fliplr0.5hsv_h/hsv_s/hsv_v控制颜色扰动皮带表面在不同光照下颜色差异大增强开高一点有益。translate0.1让目标在图片内平移模拟摄像头安装位置微调。注意fliplr水平翻转在皮带这类方向性不强的场景可以开但如果你的皮带表面有方向性的编织纹理水平翻转会把纹理方向搞反反而增加学习难度。5.2 类别不平衡如果700张里600张是wear实际标注数据里类别分布几乎没有均匀的。比如某条皮带主要故障模式是磨损日久天长磨损样本占了八成撕裂只有零星几张。这时候有两个选择一是用class_weightYOLOv8支持在训练时给少样本类别加权yolo train ... class_weights0.2,0.5,0.3这三个值对应tear、wear、scratch的权重给撕裂和划伤更高权重让loss计算时对它们更敏感。另一个更有效的手段是离线复制少样本图片做增强。把撕裂样本做水平翻转、平移、加噪声后复制到训练目录一次性把撕裂类别扩充到300张左右。注意增强后的图片不要进验证集——验证集必须保持原始数据分布一旦增强mAP水分很大。5.3 标注噪声的直接后果与处理标注噪声在这里理解为框位置偏移和类别错标。框位置偏移的影响比多数人想的大一是框边缘偏离目标后会让IoU计算不准确训练出来的模型框筋不紧现场输出框偏大或偏小二是随机偏移方向上不连续模型学习到的框边界特征本身是抖动的。处理方式不必回到标注软件重新逐帧修中阶做法是训练后用模型自己解析一遍训练集找出置信度低于0.6的标注框人工检查这些框是否是标注问题手动修掉后重新训练。这类模型辅助标注复核的做法在只有700张图的小数据集上特别香一次能找出十几二十个问题框。5.4 验证集和测试集的划分陷阱切分数据时如果按文件列表直接shuffle可能会把同一时间段连续拍摄的相似图片分到训练集和验证集各一份导致验证集效果虚高。正确的做法是按拍摄时间或者视频片段划分让同一段皮带运行时间内的连拍帧只落在一个集合里。具体实现方式是给文件名加时间前缀按前缀分组shuffle后切分。这个细节经常被忽略但现场模型上线后效果远不如本地验证集一半以上的原因就在这里。5.5 置信度阈值与NMS参数的现场适配训练完成后导出推理时很多人直接沿用YOLOv8默认的置信度0.25、NMS 0.45。但皮带破损检测现场的误报成本高建议把置信度提高到0.4~0.5漏检一点没关系误报一次就要被现场运维骂一次。NMS的iou参数在破损场景保持0.45即可因为缺陷互相交叠的情况不多。如果处理的是同一张图多个相邻磨损带的情况可以稍微降一点到0.35避免相邻框被合并成一个。6. 部署阶段的BT问题从.pt权重到ONNX推理的实际经验训练完成的.pt权重只能用于实验验证现场部署要么转ONNX用OpenVINO或ONNX Runtime推理要么用TensorRT量化到FP16跑在Jetson或RK3588工控机上。最简单可靠的一条路是转成ONNX再交给不同的部署平台from ultralytics import YOLO model YOLO(runs/detect/train/weights/best.pt) model.export(formatonnx, imgsz640, opset12, dynamicFalse)导出后的best.onnx文件带着模型的全部后处理逻辑NMS等操作已经封装在输出节点里。用ONNX Runtime做推理时要注意输入张量的尺寸是[1, 3, 640, 640]前处理需要把原始图按letterbox方式缩放填充不能粗暴resize。很多新手在部署阶段翻车都翻在这里——训练时YOLOv8内部做了letterbox推理时不吃同样的预处理精度立刻掉了好几个点。现场推理时的另一个我被坑过的细节是摄像头画面方向问题。皮带正反方向拍摄的图像特征差异很大如果训练数据全是皮带正向运行时的画面但现场摄像头装在了另一侧或者用了镜像模式推理精度会明显下跌。解决的办法是在部署脚本里做一次水平翻转测试对比左右方向的结果选置信度平均更高的方向作为推理输入。最后一条个人习惯每一版模型训练完除了记录mAP指标我会单独存一组线上抓拍的刁钻图片——弱光照的、皮带表面有水渍的、有矿石遮挡的。模型能不能上线不看它在测试集上的分数看这组图有没有明显翻车。光靠700张标注图构建的数据集模型对现场极端工况的容忍能力天生就有限识别能力弱半分没关系稳定才是硬道理。希望这些踩坑经验对你有帮助。本文还有配套的精品资源点击获取