简介:面向工业质检、设备维护等场景的传送带皮带破损检测数据集,基于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",在图片上框出缺陷区域,弹窗里选择对应类别。每张图标注完按Ctrl+S保存,会生成一个与图片同名的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(parents=True, exist_ok=True) 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', encoding='utf-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(parents=True, exist_ok=True) Path(str(d).replace('images', 'labels')).mkdir(parents=True, exist_ok=True) 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 python=3.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 data=data.yaml model=yolov8s.pt epochs=200 imgsz=640 batch=16 patience=50模型规模选yolov8s而不是yolov8m或l,700张图用大模型必然过拟合,s模型在精度和泛化之间最平衡。patience=50意思是连续50个epoch验证集指标不提升就早停,小样本训练跑到一半就能触发,省时间。imgsz=640是IOU和mAP计算的基准尺寸,不要改成1280,虽然大图对小目标更友好,但700张图的样本量根本喂不饱1280分辨率的模型。
如果你的图像里缺陷很小,比如只有十几个像素宽、几十个像素长,64 0可能不够,可以先按640跑一版看结果,小目标效果差再启用YOLOv8的SAHI切片推理,而不是直接拉高imgsz。
4.3 训练监控与结果解读:从loss曲线到混淆矩阵
训练过程中需要盯三个关键输出。第一个是训练日志里的box_loss和cls_loss,正常情况下两者都持续下降,box_loss很快收敛到0.02以下说明框的拟合已经稳定。第二个是验证集mAP50和mAP50-95,mAP50反映粗粒度定位是否准确,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 data=data.yaml model=yolov8s.pt epochs=200 batch=16 \ hsv_h=0.015 hsv_s=0.7 hsv_v=0.4 translate=0.1 scale=0.5 fliplr=0.5hsv_h/hsv_s/hsv_v控制颜色扰动,皮带表面在不同光照下颜色差异大,增强开高一点有益。translate=0.1让目标在图片内平移,模拟摄像头安装位置微调。注意fliplr水平翻转,在皮带这类方向性不强的场景可以开,但如果你的皮带表面有方向性的编织纹理,水平翻转会把纹理方向搞反,反而增加学习难度。
5.2 类别不平衡:如果700张里600张是wear
实际标注数据里类别分布几乎没有均匀的。比如某条皮带主要故障模式是磨损,日久天长磨损样本占了八成,撕裂只有零星几张。这时候有两个选择:一是用class_weight,YOLOv8支持在训练时给少样本类别加权:
yolo train ... class_weights=0.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(format='onnx', imgsz=640, opset=12, dynamic=False)导出后的best.onnx文件带着模型的全部后处理逻辑,NMS等操作已经封装在输出节点里。用ONNX Runtime做推理时要注意,输入张量的尺寸是[1, 3, 640, 640],前处理需要把原始图按letterbox方式缩放填充,不能粗暴resize。很多新手在部署阶段翻车都翻在这里——训练时YOLOv8内部做了letterbox,推理时不吃同样的预处理,精度立刻掉了好几个点。
现场推理时的另一个我被坑过的细节是摄像头画面方向问题。皮带正反方向拍摄的图像特征差异很大,如果训练数据全是皮带正向运行时的画面,但现场摄像头装在了另一侧或者用了镜像模式,推理精度会明显下跌。解决的办法是在部署脚本里做一次水平翻转测试,对比左右方向的结果,选置信度平均更高的方向作为推理输入。
最后一条个人习惯:每一版模型训练完,除了记录mAP指标,我会单独存一组线上抓拍的"刁钻图片"——弱光照的、皮带表面有水渍的、有矿石遮挡的。模型能不能上线,不看它在测试集上的分数,看这组图有没有明显翻车。光靠700张标注图构建的数据集,模型对现场极端工况的容忍能力天生就有限,识别能力弱半分没关系,稳定才是硬道理。希望这些踩坑经验对你有帮助。
本文还有配套的精品资源,点击获取