资讯动态

工业传送带损伤检测数据集实战:从标注转换到YOLO训练与边缘部署

发布时间:2026/10/14 12:47:35 来源:尧图企业网站定制
简介这份工业传送带损伤检测数据集面向工业视觉质检与智能工厂安全监控方向的开发者、算法工程师及高校研究人员用于训练传送带运行状态的实时感知与故障预警模型。数据集包含1000张高清工业传送带图像覆盖孔洞、撕裂、异物等8种损伤类别标注文件齐全并采用YOLO标准格式可直接对接YOLOv8等主流目标检测框架省去格式转换与清洗成本。资源包共3个文件以inscode项目配置、html说明页与gitignore为主压缩包约8KB体量轻便便于快速拉取与部署。文件结构清晰附有训练集与验证集划分建议及配置文件示例读者可据此直接搭建训练流程并在此基础上扩展实时监控、设备健康评估与预防性维护等应用。目前已有63人学习下载适合希望快速验证工业缺陷检测方案、缩短项目启动周期的中高级开发者参考使用。1. 工业传送带损伤检测数据集从标注到训练的一条龙落地传送带撕裂、划伤、异物嵌入这类损伤在矿山、港口、电厂这些连续作业场景里属于典型的“小概率高代价”故障。人工巡检要么漏检要么发现时已经撕开半米。我最近拆了一份工业传送带损伤检测数据集配套项目代码核心价值在于它把“图像采集—标注规范—检测模型训练—推理输出”这条链路做成了可复现的工程包而不是丢一堆图让你自己猜怎么用。它适合两类人一是做工业视觉检测的算法工程师想快速验证 YOLO 系列在传送带场景的迁移效果二是现场自动化团队需要一套能跑在边缘盒子上的损伤识别基线。数据集覆盖了纵向撕裂、边缘磨损、表面划痕、异物遮挡四类常见缺陷标注格式兼容主流检测框架代码包里包含数据转换、训练配置和推理脚本。下面按“先看懂数据、再跑通训练、最后避开坑”的顺序拆一遍。2. 数据集结构与标注格式先搞清楚你拿到的是什么2.1 目录组织与文件命名逻辑拿到压缩包后别急着解压到桌面先看目录层级。常见做法是根目录下分images和labels两个平行文件夹images里再按train、val、test切分labels保持同名对应。文件名通常带场景编号和损伤类型缩写比如belt_0231_tear.jpg对应belt_0231_tear.txt。这种命名不是随便起的它决定了你后面做数据增强时能不能按类别分层采样。我一般会先跑一段脚本统计各类别样本数和图像尺寸分布避免训练到一半才发现某类只有十几张图。下面这段代码直接读目录输出每类数量和宽高范围import os from collections import Counter from PIL import Image root ./dataset img_dir os.path.join(root, images, train) lbl_dir os.path.join(root, labels, train) cls_counter Counter() size_list [] for fname in os.listdir(img_dir): if not fname.lower().endswith((.jpg, .png)): continue img_path os.path.join(img_dir, fname) with Image.open(img_path) as im: size_list.append(im.size) lbl_path os.path.join(lbl_dir, os.path.splitext(fname)[0] .txt) if not os.path.exists(lbl_path): print(f缺失标注: {fname}) continue with open(lbl_path) as f: for line in f: cls_id int(line.split()[0]) cls_counter[cls_id] 1 print(类别分布:, dict(cls_counter)) print(图像尺寸范围:, min(size_list), -, max(size_list))逻辑说明先遍历训练集图像同时检查同名标注文件是否存在缺失就打印出来。cls_counter统计每个类别 ID 出现的次数注意这里统计的是标注框数量不是图像数量因为一张图可能有多个损伤。size_list用来判断图像分辨率是否统一如果宽高差异超过 30%后面做 mosaic 增强时就要小心边界框越界。参数方面root指向解压后的数据集根目录img_dir和lbl_dir必须严格对应。如果你的目录结构是train/images和train/labels改一下路径拼接即可。常见坑是 Windows 下路径分隔符混用建议统一用os.path.join。2.2 标注格式转换从 VOC 到 YOLO 的坐标映射这份数据集的标注大概率是两种格式之一PASCAL VOC 的 XML 或 YOLO 的 TXT。如果是 XML你需要转成 YOLO 的归一化中心点格式。转换的核心公式是x_center (xmin xmax) / 2 / widthy_center (ymin ymax) / 2 / heightw (xmax - xmin) / widthh (ymax - ymin) / height下面是一个批量转换脚本同时做类别名到 ID 的映射import os import xml.etree.ElementTree as ET classes [tear, wear, scratch, foreign] cls_map {name: i for i, name in enumerate(classes)} def convert(xml_path, out_path, img_w, img_h): tree ET.parse(xml_path) root tree.getroot() lines [] for obj in root.findall(object): name obj.find(name).text if name not in cls_map: continue bbox obj.find(bndbox) xmin float(bbox.find(xmin).text) ymin float(bbox.find(ymin).text) xmax float(bbox.find(xmax).text) ymax float(bbox.find(ymax).text) xc (xmin xmax) / 2.0 / img_w yc (ymin ymax) / 2.0 / img_h w (xmax - xmin) / img_w h (ymax - ymin) / img_h lines.append(f{cls_map[name]} {xc:.6f} {yc:.6f} {w:.6f} {h:.6f}) with open(out_path, w) as f: f.write(\n.join(lines)) # 调用示例 convert(./annotations/belt_0231.xml, ./labels/belt_0231.txt, 1920, 1080)逻辑说明ET.parse解析 XML遍历每个object节点提取类别名和边界框坐标。cls_map把类别名转成从 0 开始的整数 ID顺序必须和训练时的data.yaml一致。归一化时除以图像宽高得到 0 到 1 之间的小数保留 6 位足够精度。参数注意img_w和img_h必须和实际图像尺寸一致不能想当然写 1920x1080。如果图像尺寸不统一建议先统一 resize 再标注或者转换时逐张读取真实尺寸。常见翻车点是 XML 里坐标是浮点数但图像是整数尺寸除完以后边界框超出 [0,1] 范围训练时会被框架直接丢弃。2.3 类别不平衡与样本增强策略工业损伤数据天然不平衡划痕可能几百个撕裂可能只有几十个。直接训练会导致模型对少数类不敏感。我一般会做两件事一是按类别分层采样保证每个 batch 里少数类至少出现一次二是针对少数类做定向增强比如随机旋转、亮度扰动、局部遮挡。如果你用 YOLO 官方训练脚本可以在data.yaml里设置copy_paste和mixup概率但注意传送带背景相对固定mixup 太强反而会让模型学到不相关的纹理。我的经验是mixup0.1、copy_paste0.3比较稳。另外撕裂类损伤通常呈细长条状随机裁剪容易把目标裁掉一半建议用mosaic0.5而不是 1.0。3. 训练环境搭建与模型选型从零跑通第一个基线3.1 依赖安装与版本锁定这份代码包大概率基于 PyTorch 和 Ultralytics 的 YOLO 实现。别直接pip install ultralytics就完事版本不匹配会导致训练中途报 CUDA 错误。我一般会先建虚拟环境然后按requirements.txt锁版本。如果没有 requirements用下面这套组合比较稳conda create -n belt_det python3.9 -y conda activate belt_det pip install torch1.13.1cu117 torchvision0.14.1cu117 -f https://download.pytorch.org/whl/torch_stable.html pip install ultralytics8.0.145 opencv-python4.8.0.74逻辑说明Python 3.9 对大多数检测框架兼容性最好。PyTorch 1.13.1 配 CUDA 11.7 是经过验证的组合不会出现torch.cuda.is_available()返回 False 的玄学问题。Ultralytics 8.0.145 是较稳定的版本新版本 API 变动频繁容易和旧代码冲突。参数注意如果你的显卡是 30 系CUDA 11.7 没问题40 系建议上 CUDA 11.8 和 PyTorch 2.0。安装完跑一句python -c import torch; print(torch.cuda.is_available())输出 True 再往下走。3.2 模型选型YOLOv8n 还是 YOLOv8s传送带损伤检测的部署环境通常是边缘设备算力有限。YOLOv8n 参数量约 3.2M推理速度在 Jetson Nano 上能到 15 FPS 左右YOLOv8s 参数量 11.2M精度高 3 到 5 个点但速度掉一半。我的建议是如果撕裂类缺陷占主导用 YOLOv8s因为细长目标需要更多特征通道如果主要是划痕和异物YOLOv8n 够用。下面是一个训练配置示例直接写进train.pyfrom ultralytics import YOLO model YOLO(yolov8s.pt) results model.train( data./data.yaml, epochs120, imgsz640, batch16, lr00.01, lrf0.01, momentum0.937, weight_decay0.0005, warmup_epochs3.0, mosaic0.5, mixup0.1, copy_paste0.3, device0, workers4, project./runs, namebelt_v1 )逻辑说明data指向数据集配置文件里面写清楚train、val路径和类别名。epochs120是经验值传送带数据量通常不大120 轮足够收敛。imgsz640是速度和精度的平衡点如果图像里损伤目标很小可以提到 1280但显存占用翻倍。lr0初始学习率 0.01lrf最终学习率因子 0.01配合余弦退火。warmup_epochs3让模型前 3 轮慢慢升学习率避免一开始就震荡。参数注意batch16需要至少 8GB 显存不够就降到 8。workers4是数据加载线程数Windows 下建议设 0 避免多进程报错。mosaic0.5表示 50% 概率做马赛克增强传送带背景单一太高会让模型分不清真实边缘。3.3 训练过程监控与早停判断训练启动后别干等盯三个指标box_loss、cls_loss、mAP50。正常情况下box_loss在前 10 轮快速下降cls_loss下降稍慢。如果 20 轮后box_loss还在 0.5 以上震荡大概率是学习率太大或者标注有问题。我一般会在train.py里加patience30意思是 30 轮 mAP 不提升就早停。同时开 TensorBoard 看曲线tensorboard --logdir ./runs/belt_v1如果发现val/box_loss持续上升而train/box_loss下降说明过拟合了赶紧停掉减少 epochs 或者加数据增强。常见坑是mAP50到 0.6 就上不去了这时候先别调模型回去检查标注有没有把整张图框成一个大框有没有类别标错。4. 推理部署与性能验证模型到底能不能用4.1 单张图像推理与结果解析训练完拿到best.pt先别急着上产线用测试集跑一遍看漏检和误检。下面这段代码做单张推理并保存可视化结果from ultralytics import YOLO import cv2 model YOLO(./runs/belt_v1/weights/best.pt) results model.predict( source./test_images/belt_0456.jpg, conf0.35, iou0.45, imgsz640, saveTrue, project./infer_out ) for r in results: boxes r.boxes for box in boxes: cls_id int(box.cls[0]) conf float(box.conf[0]) xyxy box.xyxy[0].tolist() print(f类别: {cls_id}, 置信度: {conf:.3f}, 坐标: {xyxy})逻辑说明conf0.35是置信度阈值低于这个值的框直接丢弃。工业场景宁可误检不可漏检所以可以适当降低到 0.25。iou0.45是 NMS 的 IoU 阈值重叠度超过 45% 的框会被合并。saveTrue会把画了框的图存到infer_out目录。参数注意imgsz必须和训练时一致否则精度会掉。如果推理图分辨率远大于 640建议先缩放再推理或者把imgsz调大。常见问题是conf设太高导致小目标漏检撕裂初期只有几十个像素宽conf0.5基本检不到。4.2 批量测试与指标计算单张看不过瘾跑整个测试集算 mAP。Ultralytics 自带val模式yolo val model./runs/belt_v1/weights/best.pt data./data.yaml splittest imgsz640 batch8输出会给出每类的 Precision、Recall、mAP50、mAP50-95。重点关注 Recall工业检测漏检代价远大于误检。如果撕裂类 Recall 低于 0.7说明模型对细长目标不敏感回去检查训练时imgsz是不是太小或者标注框是不是太松。我一般会额外跑一个混淆矩阵看类别之间有没有互相误判。比如划痕和边缘磨损在低分辨率下很像如果混淆严重考虑把这两类合并或者加更多区分性样本。4.3 边缘设备部署的量化与加速如果最终要跑在 Jetson 或瑞芯微这类边缘盒子上PyTorch 模型直接跑太慢。常见做法是导出 ONNX 再转 TensorRTyolo export model./runs/belt_v1/weights/best.pt formatonnx opset12 simplifyTrue逻辑说明opset12兼容大多数推理引擎simplifyTrue会做算子融合减少冗余计算。导出后在边缘设备上用 TensorRT 加载FP16 量化能提速 2 到 3 倍精度掉不到 1 个点。参数注意量化时校准集要覆盖所有损伤类型否则某些类会掉点严重。常见坑是 ONNX 导出后输入尺寸写死 640实际推理图不是 640 就报错建议在预处理里统一 resize。5. 避坑与常见问题排查那些让我熬夜的瞬间5.1 标注框越界导致训练崩溃现象训练启动几轮后报AssertionError: all bboxes must be in [0,1]。原因VOC 转 YOLO 时坐标归一化除错了图像尺寸或者标注时框超出了图像边界。解决转换脚本里加一行裁剪xc max(0, min(1, xc))四个值都做一遍。同时检查原始 XML 里有没有xmax大于图像宽度的脏数据。5.2 类别 ID 不连续导致标签错乱现象训练时cls_loss一直很高mAP 接近 0。原因data.yaml里类别名顺序和标注文件里的 ID 对不上。比如标注里 0 是 tear但 yaml 里 0 写成了 wear。解决把data.yaml和转换脚本里的classes列表逐字对齐顺序完全一致。改完重新生成所有标签文件别手动改。5.3 图像尺寸不统一导致增强报错现象训练到第 5 轮突然报RuntimeError: invalid shape。原因数据集中混了不同分辨率的图mosaic 增强时拼接越界。解决训练前统一 resize 到 640x640或者用letterbox保持长宽比填充。Ultralytics 默认会做 letterbox但如果图像宽高比差异太大填充区域过多会影响精度。5.4 显存溢出与 batch 设置现象CUDA out of memory训练直接挂掉。原因batch设太大或者imgsz提到 1280 但没降 batch。解决先降batch到 4 跑通再逐步往上加。同时开ampTrue混合精度训练显存占用能降 30% 左右。如果还不行用--device 0指定单卡别用多卡数据并行。5.5 推理结果框重叠严重现象一张图上同一个损伤画了好几个框。原因NMS 的iou阈值设太高或者模型对同一目标输出了多个候选。解决把iou从 0.45 降到 0.3让重叠框合并得更狠。如果还不行检查标注里有没有重复框训练时一个目标标了两次。6. 进阶技巧用 TTA 和切片推理把召回率再拉高工业场景里撕裂类缺陷往往只占图像很小一块直接 resize 到 640 后目标可能只剩十几个像素。我试过几种办法最有效的是测试时增强TTA加切片推理。TTA 就是对同一张图做水平翻转、多尺度缩放分别推理后合并结果。Ultralytics 里直接加augmentTrue就能开results model.predict( source./test_images, conf0.25, iou0.3, imgsz640, augmentTrue, saveTrue )逻辑说明augmentTrue会在推理时对图像做翻转和缩放每个变体跑一次前向最后用 NMS 合并。代价是推理时间翻 3 倍左右但召回率通常能提 2 到 4 个点。如果边缘设备算力够建议开如果跑在单片机上还是老老实实单次推理。切片推理更适合超大分辨率图像。思路是把 4000x3000 的图切成 640x640 的小块每块单独推理最后把框映射回原图坐标。下面是一个简化实现import cv2 import numpy as np from ultralytics import YOLO model YOLO(./runs/belt_v1/weights/best.pt) img cv2.imread(./test_images/belt_large.jpg) h, w img.shape[:2] tile 640 stride 480 # 重叠 160 像素避免目标被切断 all_boxes [] for y in range(0, h, stride): for x in range(0, w, stride): crop img[y:ytile, x:xtile] if crop.shape[0] tile or crop.shape[1] tile: crop cv2.copyMakeBorder(crop, 0, tile-crop.shape[0], 0, tile-crop.shape[1], cv2.BORDER_CONSTANT, value(114,114,114)) res model.predict(crop, conf0.25, verboseFalse)[0] for box in res.boxes: xyxy box.xyxy[0].tolist() xyxy[0] x xyxy[1] y xyxy[2] x xyxy[3] y all_boxes.append((xyxy, float(box.conf[0]), int(box.cls[0]))) # 全局 NMS 合并 def nms(boxes, iou_thr0.3): boxes sorted(boxes, keylambda b: b[1], reverseTrue) keep [] while boxes: best boxes.pop(0) keep.append(best) boxes [b for b in boxes if iou(best[0], b[0]) iou_thr] return keep def iou(a, b): x1 max(a[0], b[0]); y1 max(a[1], b[1]) x2 min(a[2], b[2]); y2 min(a[3], b[3]) inter max(0, x2-x1) * max(0, y2-y1) area_a (a[2]-a[0]) * (a[3]-a[1]) area_b (b[2]-b[0]) * (b[3]-b[1]) return inter / (area_a area_b - inter 1e-6) final nms(all_boxes) print(f合并后框数: {len(final)})逻辑说明stride480表示每次滑动 480 像素相邻块重叠 160 像素防止目标正好落在切割线上。每个小块推理后把坐标加回原图偏移量。最后用全局 NMS 去掉跨块重复框。iou函数是标准交并比计算nms按置信度排序后贪心保留。参数注意tile和stride要根据目标尺寸调。如果损伤目标普遍大于 200 像素tile640够用如果目标很小tile降到 320但推理次数翻倍。常见坑是边界填充用了黑色模型可能把黑边当成异物建议用灰色 (114,114,114) 填充。从那以后我每次拿到新的工业检测数据集都强制先跑一遍类别分布统计和标注可视化确认没有脏数据再开训练。这份传送带损伤检测数据集和代码包最大的价值是省掉了从零搭 pipeline 的时间但前提是你得先看懂它的标注逻辑和目录结构。希望帮到你。本文还有配套的精品资源点击获取

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价 →
↑