简介:本资源为流水线皮带传送带异物检测数据集,面向从事工业视觉检测、智能制造与安全生产方向的算法工程师、研究生及深度学习入门者,可用于训练与验证传送带异常目标检测模型,解决皮带运输场景下异物识别与预警的样本需求。压缩包共332个文件,包含110张jpg原始图像、110个VOC格式xml标注文件与112个txt文件(含YOLO格式标注及说明),整体约17.76MB,jpg用于模型输入,xml与txt分别适配Pascal VOC和YOLO两种主流训练框架,便于直接转换使用。数据集仅设anomaly一个类别,共标注191个矩形框,采用labelImg工具人工画框,标注准确合理。目前已有391人学习下载,适合快速搭建传送带异物检测基线、验证数据增强策略或作为课程与项目实验素材,帮助读者省去从零采集与标注的成本,专注模型调优与效果对比。
1. 传送带异物检测数据集:110 张图、191 个框,这份 VOC+YOLO 双格式资源到底能干什么
传送带跑偏、撕裂、混入锚杆或铁片,这类事故在矿山、电厂、港口散料运输线上并不少见。真要在产线上做异物检测,第一步往往不是调模型,而是卡在数据上——公开的传送带异物检测数据集本来就少,能直接喂给 YOLO 训练的更是稀缺。这份资源给的就是一个已经标好的小样本集:110 张 jpg 图片,对应 110 个 Pascal VOC 格式 xml 和 110 个 YOLO 格式 txt,单类别anomaly,总共 191 个矩形框,标注工具是 labelImg。它适合两类人:一是想快速跑通「传送带异物检测」这条链路、验证方案可行性的算法工程师;二是拿它当模板,理解 VOC 与 YOLO 双格式如何对齐、后续自己扩标的人。110 张不算多,但胜在格式齐全、类别干净,拿来练手和搭 pipeline 足够。
2. VOC 与 YOLO 双格式拆解:xml 和 txt 到底怎么对应
2.1 两种格式的坐标体系差异
Pascal VOC 的 xml 用的是绝对像素坐标,xmin/ymin/xmax/ymax直接对应图片上的像素位置,人读起来直观,但不同分辨率图片混在一起训练时,模型没法直接吃。YOLO 的 txt 用的是归一化后的中心点加宽高,格式是class_id cx cy w h,五个值全部落在 0 到 1 之间,cx cy是框中心相对整图宽高的比例,w h是框宽高相对整图宽高的比例。这份数据集两种都给了,意味着你可以直接用 txt 喂 YOLO,也可以用 xml 转成 COCO、VOC 训练框架需要的格式,省掉自己写转换脚本的功夫。
需要留意的是,YOLO 的class_id从 0 开始编号。这份数据集只有一个类别anomaly,所以所有 txt 里的 class_id 都应该是 0。如果你拿到手发现有的 txt 第一列是 1,那说明标注时类别索引没对齐,训练时会出现「明明只有一个类却报两个类」的玄学问题,这个后面避坑章节会细说。
2.2 目录结构核对与文件配对检查
拿到压缩包解压后,常见做法是先核对三组文件是否一一对应:jpg 数量、xml 数量、txt 数量都应该是 110。文件名主干应当一致,比如chuansongdai_1.jpg对应chuansongdai_1.xml和chuansongdai_1.txt。下面这段脚本就是干这个的,跑一遍能立刻发现缺图、缺标注、命名不一致的情况。
import os img_dir = "images" # jpg 所在目录 xml_dir = "annotations" # VOC xml 目录 txt_dir = "labels" # YOLO txt 目录 imgs = {os.path.splitext(f)[0] for f in os.listdir(img_dir) if f.endswith(".jpg")} xmls = {os.path.splitext(f)[0] for f in os.listdir(xml_dir) if f.endswith(".xml")} txts = {os.path.splitext(f)[0] for f in os.listdir(txt_dir) if f.endswith(".txt")} print("图片数:", len(imgs), "xml数:", len(xmls), "txt数:", len(txts)) print("有图无xml:", imgs - xmls) print("有图无txt:", imgs - txts) print("有xml无图:", xmls - imgs)逻辑说明:用集合做差集是最快的配对检查方式,比逐个文件循环判断省事。参数上,三个目录名按你实际解压后的结构改,有的包会把 jpg 和 xml 放同一目录,那就把img_dir和xml_dir指向同一个路径。跑完如果三个差集都为空,说明文件配对没问题,可以进入下一步;如果有输出,先补齐再训练,否则 YOLO 在加载阶段会直接跳过找不到标签的图,你以为训了 110 张,实际可能只训了 100 张。
2.3 用 xml 反推 txt 的校验脚本
虽然这份数据集已经给了 txt,但校验一遍能确认标注没被改坏。下面脚本从 xml 重新算一遍归一化坐标,和现有 txt 对比,容差设 1e-4。
import os import xml.etree.ElementTree as ET def voc_to_yolo(xml_path): tree = ET.parse(xml_path) root = tree.getroot() size = root.find("size") w = float(size.find("width").text) h = float(size.find("height").text) boxes = [] for obj in root.iter("object"): cls = 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) cx = (xmin + xmax) / 2.0 / w cy = (ymin + ymax) / 2.0 / h bw = (xmax - xmin) / w bh = (ymax - ymin) / h boxes.append((cls, cx, cy, bw, bh)) return boxes # 对比某个样本 xml_boxes = voc_to_yolo("annotations/chuansongdai_1.xml") with open("labels/chuansongdai_1.txt") as f: txt_lines = [l.strip().split() for l in f if l.strip()] print("xml框数:", len(xml_boxes), "txt框数:", len(txt_lines)) for xb, tb in zip(xml_boxes, txt_lines): print(xb[0], [round(float(v), 4) for v in tb[1:]])逻辑说明:voc_to_yolo把 xml 的绝对坐标按图片宽高归一化,得到和 YOLO 一致的五个值。参数上,容差不用写死在脚本里,肉眼对比小数点后四位即可,正常情况应当完全一致。如果发现某个框对不上,多半是标注时框被拖动过但只更新了一种格式,这种脏数据在训练里会拉低召回,建议以 xml 为准重新生成 txt。
3. 把 110 张图喂进 YOLO:划分、配置与训练命令
3.1 训练集验证集划分与 data.yaml 写法
110 张图做检测,常见做法是按 8:2 划分,训练集 88 张、验证集 22 张。样本量小,不建议再切测试集,否则验证集只剩十几张,指标波动会大到没法看。划分时按文件名排序后固定随机种子,保证每次复现一致。
import os, random, shutil random.seed(42) src_img, src_lbl = "images", "labels" for d in ["dataset/images/train", "dataset/images/val", "dataset/labels/train", "dataset/labels/val"]: os.makedirs(d, exist_ok=True) names = sorted([f for f in os.listdir(src_img) if f.endswith(".jpg")]) random.shuffle(names) split = int(len(names) * 0.8) for i, name in enumerate(names): stem = os.path.splitext(name)[0] phase = "train" if i < split else "val" shutil.copy(os.path.join(src_img, name), f"dataset/images/{phase}/{name}") shutil.copy(os.path.join(src_lbl, stem + ".txt"), f"dataset/labels/{phase}/{stem}.txt") print("train:", split, "val:", len(names) - split)逻辑说明:random.seed(42)固定划分,方便复现。参数上 0.8 是经验值,样本更少时可以调到 0.9,但验证集低于 15 张时指标参考价值有限。复制而非移动,保留原始文件,后面扩标时不用重新解压。
划分完写data.yaml,这是 YOLO 系列训练的入口配置:
path: ./dataset train: images/train val: images/val nc: 1 names: ["anomaly"]nc是类别数,这份数据集就是 1;names顺序必须和 txt 里的 class_id 对应,0 对应anomaly。写反了模型会把异物当背景学,训练 loss 看着降,实际一个框都检不出来。
3.2 从预训练权重起步的训练命令
小样本检测最忌讳从零训。常见做法是加载 YOLO 官方在 COCO 上预训练的权重做迁移,让 backbone 先具备通用特征提取能力,再在 110 张图上微调。下面以 YOLOv8 为例,命令里的参数按你的显存和图片尺寸调整。
yolo detect train \ data=dataset/data.yaml \ model=yolov8n.pt \ epochs=100 \ imgsz=640 \ batch=8 \ lr0=0.01 \ patience=20 \ project=runs/belt \ name=anomaly_v1逻辑说明:model=yolov8n.pt选 nano 版本,110 张图用大模型容易过拟合,nano 足够跑通链路。epochs=100配合patience=20,验证指标 20 轮不涨就早停,避免无效训练。imgsz=640是默认输入尺寸,如果原图分辨率远大于 640,异物又小,可以提到 960 或 1280,但显存占用会明显上升。batch=8是保守值,显存够可以加到 16。lr0=0.01是微调的常见起点,样本少时可以降到 0.001 更稳。
训练过程中重点看三个指标:box_loss是否稳定下降、mAP50是否在涨、验证集的precision/recall是否严重失衡。110 张图训到 mAP50 0.7 以上算正常,如果一直卡在 0.3 以下,先回去查标注,别急着调参。
3.3 推理验证与结果落盘
训练完拿验证集或新图跑推理,确认模型真的能框出异物:
yolo detect predict \ model=runs/belt/anomaly_v1/weights/best.pt \ source=dataset/images/val \ conf=0.25 \ save=True \ project=runs/belt \ name=pred_v1逻辑说明:conf=0.25是置信度阈值,低于它的框不输出。小样本模型置信度普遍偏低,可以先设 0.1 看召回,再逐步提到 0.3 看精度,找到业务能接受的平衡点。save=True把带框图片存到runs/belt/pred_v1,肉眼过一遍比看指标更直接——有些框位置明显偏了,指标却因为 IoU 阈值宽松没暴露出来。
4. 小样本异物检测的避坑清单:从标注到训练的血泪经验
4.1 现象:训练报「no labels found」,loss 直接为 0
原因:YOLO 按图片路径推导标签路径,如果你的目录结构不是images/和labels/平行,或者 txt 文件名和 jpg 主干不一致,它找不到标签就跳过。这份数据集原始文件是 jpg、xml、txt 混放,直接指向原目录训练必然踩这个坑。
解决:按 3.1 的脚本重建images/train、labels/train结构,确保每张 jpg 在同级 labels 下有同名 txt。跑一遍 2.2 的配对检查脚本,差集为空再开训。
4.2 现象:只有一个类别,训练却报 nc=2 或类别索引越界
原因:txt 第一列的 class_id 不全是 0。labelImg 在切换类别时如果没重置,可能把部分框标成了索引 1,而data.yaml里nc=1,加载时就会冲突。
解决:扫一遍所有 txt 的第一列,统计唯一值:
awk '{print $1}' labels/train/*.txt | sort | uniq -c正常输出只有0一个值。如果出现1,用 sed 批量替换回 0,或者回 labelImg 重新导出。这个坑很隐蔽,因为文件数量对得上,只有类别索引错了。
4.3 现象:mAP 忽高忽低,两次训练差十几个点
原因:110 张图样本量太小,验证集只有 22 张,随机划分不同、初始化不同,指标波动天然就大。这不是模型坏了,是小样本的固有特性。
解决:固定随机种子,多跑几次取平均;或者用 K 折交叉验证,把 110 张分成 5 折轮流做验证,指标更稳。别拿单次训练的 mAP 当结论,尤其别因为一次跑出 0.85 就以为方案成了。
4.4 现象:模型在训练集上框得很准,换一张新图就漏检
原因:过拟合。110 张图、191 个框,模型很容易记住训练集的背景纹理,而不是学到「异物」的通用特征。传送带背景又高度相似,过拟合更严重。
解决:开数据增强,YOLO 默认带 mosaic、翻转、HSV 扰动,确认没被关掉;imgsz适当调大保留小目标细节;如果还是漏,说明 110 张不够覆盖实际场景的异物形态,该扩标了,别硬调参。
4.5 现象:xml 和 txt 框数对不上
原因:标注过程中改过框,但只更新了一种格式,或者转换脚本跑了一半中断。这份数据集声称 xml 和 txt 都是 110 个、总框 191,实际拿到手要自己核一遍。
解决:用 2.3 的脚本逐样本对比框数,不一致的以 xml 为准重新生成 txt。总框数可以用一行命令快速统计:
cat labels/train/*.txt labels/val/*.txt | wc -l正常应该接近 191(划分后训练加验证合计)。差太多说明有标注丢失。
5. 从 110 张到可用模型:扩标策略与标注一致性技巧
这份数据集最大的价值不是那 191 个框本身,而是它给了一套干净的格式模板。真正上产线,110 张远远不够,通常要扩到几千张。扩标时我一般会沿用它的目录约定和类别命名,把新标的数据按同样结构并入,避免格式来回转换。
扩标的第一原则是类别定义要窄。anomaly这个词太宽,锚杆、铁片、木块、大块矸石都算异物,但它们的视觉特征差异很大。如果实际场景里异物形态超过三种,建议拆成metal、wood、rock这类子类,而不是全塞进anomaly。类别越宽,模型越难学,最后每个类都检不准。拆类之后data.yaml的nc和names同步改,txt 里的 class_id 也要重新映射。
第二原则是标注框贴边。传送带异物检测里,异物常常压在皮带边缘或部分遮挡,标注时框要贴住可见部分的外沿,不要把整条皮带框进去。我见过有人为了「保险」把框画大一圈,结果模型学到的特征是「皮带边缘」而不是「异物」,换条线就废。labelImg 里可以用Ctrl+滚轮放大细调,别嫌麻烦。
第三原则是负样本要留。纯异物的图好标,但真实产线上大部分帧是没有异物的。如果训练集全是带异物的图,模型会倾向于「每张图都得框点什么」,误报率飙升。扩标时按 1:1 或 2:1 混入无标注的纯背景图,YOLO 对没有 txt 的图会当作负样本处理,能明显压误报。
验证扩标质量有个笨办法但很管用:把新标的 200 张图随机抽 20 张,让另一个人重新标一遍,对比两版的框 IoU。如果平均 IoU 低于 0.7,说明标注标准没统一,回去对齐定义再继续。这个习惯我从第一次做产线检测项目就养成了,当时因为两个人对「异物边界」理解不一致,标出来的框差了一圈,模型训了两周指标上不去,排查到最后才发现是标注问题,白烧了算力。从那以后我每次扩标都强制走一遍交叉校验,宁可慢一点,也不让脏标注进训练集。
最后提一句,这份数据集明确声明不对模型精度作保证,这是负责任的说法。110 张、单类别、191 个框,它的定位就是让你跑通流程、验证格式、搭起 pipeline,不是直接拿去上线。把它当起点,按上面的扩标和校验方法往下走,才是这份资源正确的打开方式。希望帮到你。
本文还有配套的精品资源,点击获取