简介面向煤矿输送带异物识别场景的深度学习目标检测数据集适合使用YOLO、Faster R-CNN、SSD等框架进行模型训练与效果验证。数据集的标注信息已划分为训练集、验证集和测试集采用YOLO格式的txt文件同时配套指定类别信息的yaml配置文件便于一键加载与训练。压缩包共2000个文件以1999个txt标注文件为主体另含1个yaml配置整体大小约117.87MB。当前已有1119人学习使用适合煤矿智能安监方向的研究人员、算法工程师及相关专业学生作为基准数据。拿到资源后可直接读取标签、统计类别分布并能快速适配自己的模型结构省去数据整理的重复劳动有助于聚焦异物检测算法的调参与优化。1. 煤矿输送带异物识别数据集先攒够一周再谈训练做煤矿输送带异物识别的同行大都有过这种经历模型结构抄好了、YOLOv8 也装好了结果手里只有几百张网上凑的皮带照片跑出来的模型在演示视频里看着还行一到井下就疯了一样报警。问题不在算法在数据集——煤矿输送带异物识别数据集不是普通的公开数据集能替代的它的价值在于采集环境特殊、类别边界模糊、漏报代价极高。这篇文章就围绕这个数据集本身讲清采集、标注、格式转换、训练适配和避坑让新手能照着攒出一份能用于实战的数据集也让正在被误报折磨的人找到一套排查路径。2. 从井下到硬盘煤矿输送带异物数据集的采集方案、类别定义与标注规范2.1 相机与光照可见光补光是这套数据集正确打开方式煤矿井下输送带环境有几个躲不开的现实粉尘大、光照差、皮带速度快。见过有人直接用普通监控摄像头加红外灯去采数据红外在煤矸石和煤块之间几乎没有对比度因为两者的红外反射特性差异极小采回来的图连人眼都分不清模型更学不会。我一般会要求现场用工业面阵相机配合白色 LED 补光灯分辨率至少 500 万像素推荐 1200 万像素帧率 30 帧起步曝光时间控制在 1/500 秒左右避免皮带运行时产生明显运动模糊。相机安装位置在皮带正上方视野覆盖 2 到 3 米宽的皮带面拍摄距离 1.5 到 2 米。光照角度比亮度更关键总结成一句话让异物在皮带表面形成可分辨的阴影或反射差异。白光 LED 阵列和相机光轴成约 30 度角能显著增强锚杆、钢丝绳头这种金属异物的边缘轮廓而对煤矸石这类同样深色的目标侧光带来的局部纹理细节也是模型能学到的关键特征。采集时记录曝光参数保证整套数据集的亮度分布相对一致——这一点直接影响训练时的灰度分布稳定性很多人忽略。采集时长问题值得单独说测量单位是“小时”。以一条皮带速度每秒 2.5 米、异物出现每 20 分钟一次来估算要攒到 5000 到 8000 个标注框至少需要连续采集 40 到 60 小时的输送带运行画面中间还得包含换班、检修、不同载荷时段。我见过的失败案例大多是只采了一下午就急着标注最后统计类别时发现金属异物只有 30 个框根本没法训。采集完成不意味着可以直接标注。先做一次粗筛把含有异物的帧抽取出来建议先跑一版现成的检测模型做预标注把置信度高于 0.6 的区域当作候选框没有现成模型时用帧差法把与背景灰度差异明显的邻域框出来也可以。这一步能把人工标注量压缩到三分之一左右下面 2.2 节会说类别怎么定。2.2 异物类别怎么定六类起步别一上来就做“全异物”很多第一次做煤矿输送带异物识别数据集的人标注时只建一个“异物”标签。这是给自己埋雷。异物里锚杆和木板长的完全不同、粘结在输送带表面的大块煤和混杂其中的矸石更是难分你把所有东西堆在一个类别里模型学到的是一团浆糊的特征簇。我建议煤矿输送带异物识别数据集起步按表 1 的六类组织后续再根据现场情况扩类或合并类别名典型对象标注难度是否必选ore混入煤流的大块矸石高与煤块边界模糊必选bolt锚杆、锚索头中细长目标必选rope钢丝绳头、网丝中易断成多截必选wood木棍、板条、荆芭片低建议metal刮板、螺栓、铁器中反光区域大建议hazard雷管、炸药包装、水袋中特征小但不可漏按需求类别定义要先写一份标注说明文档尤其是 ore 和煤块这种靠近的类。现场常见做法是以物体表面是否存在清晰的层理纹理、反光差异和棱角作为判定标尺标注时只把确信属于矸石的目标框出来像素上拿不准的丢弃而不是硬标。锚杆这类细长目标要单独说明穿出皮带的一段标成整个异物框不要只标一端。六类配置下单独一个类的样本量要求不低于 500 个框总量 5000 以上才谈得上训练稳定性。采集到的图像不应只保留连续帧。皮带异物有很强的时序相关性同一根锚杆会在 30 帧里反复出现如果全部进训练集模型会对这个特定目标的姿态和纹理过度拟合特征泛化能力变差。抽帧策略上我习惯按每 5 秒抽 1 帧同时每 3 分钟额外抽 1 帧作为低频补充兼顾连续性和场景多样性。2.3 标注规范与质检流程双人复核 模糊帧单列标注工具选 labelImg 还是 X-AnyLabeling 倒在其次重要的是流程。煤矿输送带异物识别数据集的标注有三个必须遵守的底线第一标注框必须紧贴目标外接矩形不能为了“留余地”把框扩一圈。第二遮挡面积超过 70% 的目标不标标注时在软件里直接跳过。第三运动模糊导致人眼也看不清的帧单独放到 unlabeled 目录不删、不标、不参与训练。前两条直接影响框的中心点分布YOLO 系列对框的紧贴程度非常敏感第三条是防止脏标签污染损失函数。质检环节值得投入成本。第一遍标注完成后换一个没有参与初标的工读生做全量复核重点检查三类问题漏标、框压煤块边界、类别标错。复核没通过的单张帧打回重标通过率设定在 95% 以上才算合格。我见过只标一遍就直接训练的数据集煤矸石类别的 mAP 看起来有 0.85但现场测试时每 3 分钟误报一次把皮带值班员搞到关停报警系统追根溯源是标注时大量边界矸石被标成煤块模型学到了一个偏移的特征空间。模糊帧的归属需要特别提一下。有人会把运动模糊严重的帧也硬标进去理由是增加样本多样性。这个做法不适合异物识别——井下皮带速度高、目标特征本来就小模糊帧引入的是噪声而不是多样性正确做法是让它单独成为一个小样本集后续训练完成后专门用来测试模型的鲁棒性而不是进入训练集。3. 训练前要把煤矿输送带数据集转成 YOLO 格式转换脚本与四个边界坑3.1 从 VOC/COCO 到 YOLO 的坐标转换脚本现场标注工具输出的格式五花八门最常见的是 LabelImg 生成的 VOC XML以及部分标注平台导出的 COCO JSON。YOLO 系列训练需要的是每张图对应一个同名 txt 文件每行一个目标格式是 class_id center_x center_y width height坐标全部除以图像宽高做归一化。转换脚本建议写成幂等脚本——每次跑完检查输出不覆盖旧结果方便反复核对。import os import xml.etree.ElementTree as ET def voc_to_yolo(xml_path, output_dir, class_names): 将单个 VOC XML 转为 YOLO txt 参数说明 - xml_path: LabelImg 导出的 XML 文件路径 - output_dir: txt 输出目录 - class_names: [bolt, wood, ...] 与训练配置里的 names 顺序必须一致 tree ET.parse(xml_path) root tree.getroot() img_width int(root.find(size/width).text) img_height int(root.find(size/height).text) image_id os.path.splitext(os.path.basename(xml_path))[0] yolo_path os.path.join(output_dir, image_id .txt) objects root.findall(object) # 空标签文件: 训练时 YOLO 需要存在同名空 txt, 不能省略 with open(yolo_path, w, encodingutf-8) as f: for obj in objects: if obj.find(name).text not in class_names: print(f{image_id}: 跳过未知类别 {obj.find(name).text}) continue class_id class_names.index(obj.find(name).text) bndbox obj.find(bndbox) x1 float(bndbox.find(xmin).text) y1 float(bndbox.find(ymin).text) x2 float(bndbox.find(xmax).text) y2 float(bndbox.find(ymax).text) # 边界框越界裁剪: 归一化后可能出现 1.0 以上或 0 以下 x1, x2 max(0, x1), min(img_width, x2) y1, y2 max(0, y1), min(img_height, y2) center_x (x1 x2) / 2 / img_width center_y (y1 y2) / 2 / img_height box_width (x2 - x1) / img_width box_height (y2 - y1) / img_height f.write(f{class_id} {center_x:.6f} {center_y:.6f} f{box_width:.6f} {box_height:.6f}\n) print(f完成: {image_id})脚本逻辑不复杂但三个细节决定成败。第一class_names 的顺序必须与训练配置里 YOLO 的 names 完全一致anchor 分配是按 class_id 来的顺序错位会让模型把锚杆当木头学。第二坐标归一化后要检查除数——脚本中 img_width 从 XML 读取如果标注工具输出 PNG 而 XML 里记录的是 JPG 尺寸所有框整体偏移。第三空标签文件必须保留YOLO 训练时一张图没有对应 txt 会直接报错但空 txt 表示图中有负样本这种信息对煤矿皮带场景很重要——大多数帧本来就没有异物。3.2 空标签、越界框、重复框清洗顺序不能乱转换完不等于能直接训练。先跑一轮清洗脚本按以下顺序处理顺序颠倒会让数据问题互相掩盖。第一步删除重复框。一个目标被标注两次在 VOC 里表现为两个几乎重合的矩形IoU 超过 0.8 且类别相同时保留置信度高的一个。第二步过滤极小区块。长边小于 24 像素的框直接剔除这是经验阈值低于这个尺寸的锚杆在 1200 万像素原图上占不到 2%即使训练出高 mAP 也很难在检测阶段被稳定召回这属于小目标策略问题第 5 章再展开。第三步统一处理越界框。框超出图像边缘的部分裁掉裁完后宽或高小于 8 像素的直接丢弃。第四步检查类别文件与图片是否一一对应。皮带场景会经常遇到相机抽帧过程中有 0.5 秒的丢帧标注文件在但图片缺失训练时会被随机跳过导致验证集数据泄漏的假象。import os import glob def validate_dataset(img_dir, label_dir): imgs set(os.path.splitext(os.path.basename(p))[0] for p in glob.glob(os.path.join(img_dir, *))) labels set(os.path.splitext(os.path.basename(p))[0] for p in glob.glob(os.path.join(label_dir, *.txt))) missing_label imgs - labels missing_img labels - imgs if missing_label: print(警告: 无标签文件, len(missing_label), 张) if missing_img: print(警告: 无对应图片, len(missing_img), 个标签)这个验证代码是一个快速健康检查。训练集和验证集都会通过它能提前暴露 90% 的“Lack of label” 报错问题。3.3 按时间段而不是随机划分 train/val/test煤矿输送带异物识别数据集与常规目标检测数据集不同它的样本是视频抽帧来的相邻帧高度相关。如果像 CIFAR 那样直接随机切分同一个锚杆的 20 帧会被同时塞进训练集和验证集验证时的 mAP 虚高到离谱。我之前在某个项目里随机划分测试集 mAP0.5 达到 0.93现场却漏检严重就是因为验证集里全是训练集见过的同一根锚杆的不同姿态。正确划分方法按采集时间戳分组。采集的 40 小时数据按时间切三段前 70% 作训练、中间 20% 作验证、最后 10% 作测试。这种切分称为“时序留出法”它保证测试集里的异物是训练时完全没有见过的目标实例而不是同一物体的连续帧。实际操作中遇到的一个常见问题是同一异物可能在时间点上跨越切分边界解决办法是以异物首次出现的时间为准做整段迁移。4. 用缩小版煤矿输送带异物识别数据集跑通基线YOLOv8 参数怎么设不翻车4.1 先用 2000 张缩样验证标注质量拿到一版标注完成的数据集别急着全量训练。煤矿皮带场景下标注错误率往往比想象高先抽 2000 张覆盖不同班次、光线条件的样本训练一个缩样模型用这个模型反过来检查标注质量。这一步成本低、反馈快通常半天就能跑完。缩样训练时的做法是固定一个种子保证每次实验的训练、验证、测试划分完全一致。代码上在 ultralytics 的 data.yaml 里配置绝对路径和类别列表# data.yaml # 类别顺序必须与第3.1节脚本里的class_names保持一致 path: /data/conveyor_dataset train: images/train # 相对 path 的路径 val: images/val test: images/test names: 0: ore 1: bolt 2: rope 3: wood 4: metal 5: hazard缩样阶段的作用是发现三类问题一是有没有标注类别与名称不一致比如 code 里写 bolt 实际标的是 rope二是样本分布是否严重失衡比如 ore 有 3000 多个框hazard 只有 80 个三是图像分辨率、曝光度是否存在明显波动。这些问题会在训练日志的 loss 曲线上有迹可循验证集 mAP 也会明显偏低。4.2 关键参数imgsz、mosaic、close_mosaic、hsv训练 YOLOv8 跑煤矿输送带异物识别数据集参数默认值不能直接用。以下四个参数的调整逻辑是从几十次实验中固定下来的经验值按实际情况变化参数默认值推荐值调整理由imgsz6401280 或 1536锚杆、钢丝绳头是细长小目标640 下可能只占 8x8 像素模型根本无法学习mosaic1.01.0第 50 epoch 后设 0.1皮带背景单调mosaic 能增加上下文多样性但后期保留会干扰小目标学习close_mosaic1010控制 mosaic 在最后 10 个 epoch 关闭让模型适应真实场景的目标分布hsv_h / hsv_s / hsv_v0.015/0.7/0.40.0/0.2/0.3矿井下光照相对恒定过强的 HSV 扰动会让模型学习到不真实的色彩分布imgsz 的影响最大尤其在细长目标上。井下皮带图像多数是 2.5 米宽的视野锚杆宽度只有 4 到 6 厘米在整幅图像里占的比例极小。把 imgsz 从 640 提高到 1280小目标在特征金字塔第 3 层的特征图尺寸翻倍能缓解一半的小目标漏检问题。显存不够时优先减小 batch 而不是降低 imgsz——batch 16 改 8模型收敛慢一些但指标不会退化imgsz 降下来小目标能力立刻垮。mosaic 这个参数在皮带场景里要辩证看待。皮带本身的纹理和背景高度重复mosaic 拼图可以让模型看到不同时间、不同载荷下的背景组合提升背景分类能力所以前 40 个 epoch 保持高比例。但到训练后期mosaic 带来的多尺度变化会让模型对小目标的定位精度变差表现为 mAP0.5:0.95 停滞、单独看 mAP0.5 却在上升这时 close_mosaic 发挥作用。yolo train \ datadata.yaml \ modelyolov8m.pt \ imgsz1280 \ batch16 \ epochs150 \ optimizerAdamW \ lr00.002 \ lrf0.01 \ hsv_h0.0 hsv_s0.2 hsv_v0.3 \ mosaic1.0 close_mosaic10 \ seed42选 yolov8m 而不是 s 或 x是在精度与部署速度之间做的折中。皮带异物识别要满足实时性通常跑在边缘盒子上x 模型在 Jeston 上只能到 15 帧m 模型能到 30 帧以上。训练时 lr0 从默认的 0.01 降到 0.002是因为井下图像背景重复度高学习率过大会让损失震荡收敛到 mAP 平台期难突破。seed42 保证每次实验可复现这对跨班采集的数据集尤为重要——数据分布变化时稳定复现才能判断是数据问题还是参数问题。4.3 少样本类别怎么办过采样与拷贝粘贴hazard 和 wood 这类类别在煤矿输送带异物识别数据集里经常样本不足。不要尝试用简单复制来提高权重模型会过拟合到重复样本的噪声上。常用做法有两个过采样加小随机扰动把少样本帧在训练时以 2 到 3 倍概率取到配合轻微的亮度、对比度变化能小幅提升该类别的 recall。更有效的是拷贝粘贴增强——把少样本目标从原图中剪切出来贴上另一张不包含该类别的皮带背景图生成合成样本。井下皮带的背景变化不大这类增强非常适配。可以用 OpenCV 写一个合成器把锚杆的 mask 按随机位置贴到背景图上同时保留不超过 25 度的旋转import cv2 import numpy as np def paste_object(bg_img, obj_img, obj_mask, max_rot25): # 随机旋转目标图像与 mask h, w obj_img.shape[:2] angle np.random.uniform(-max_rot, max_rot) rot_mat cv2.getRotationMatrix2D((w / 2, h / 2), angle, 1.0) obj_rot cv2.warpAffine(obj_img, rot_mat, (w, h)) mask_rot cv2.warpAffine(obj_mask, rot_mat, (w, h)) # 在背景中找一块灰度差异小的区域粘贴, 避免边缘突兀 bg_h, bg_w bg_img.shape[:2] y np.random.randint(0, bg_h - h) x np.random.randint(0, bg_w - w) region bg_img[y:yh, x:xw] bg_gray cv2.cvtColor(region, cv2.COLOR_BGR2GRAY) obj_gray cv2.cvtColor(obj_rot, cv2.COLOR_BGR2GRAY) if np.abs(bg_gray.mean() - obj_gray.mean()) 50: return None # 背景差异太大, 丢弃本次合成 mask_3d np.stack([mask_rot] * 3, axis-1) / 255.0 bg_img[y:yh, x:xw] (bg_img[y:yh, x:xw] * (1 - mask_3d) obj_rot * mask_3d) return bg_img, (x, y, w, h)这段代码的关键在于粘贴位置的选择逻辑——用背景灰度与目标灰度差异做筛选差异过大贴出来的合成样本模型一眼看穿反而不利于收敛。合成样本的框坐标与目标掩膜对应标注框这时是精确的比人工标注质量还稳定。一般把少样本类别的样本量通过这种方式补到 300 个以上训练效果就会明显改善。5. 煤矿输送带异物识别常见避坑误报、漏报与脏标签5.1 误报率高居不下煤矸石界定标尺没立住现象模型在测试集上 mAP 不错一上现场就频繁误报皮带空载时也报警值班员开 40 分钟屏幕就被刷屏。原因排查后发现训练集里煤矸石类别标注边界混乱不同标注员对“矸石”的理解差异大有人将煤流里带棱角的煤块标成矸石有人把表面有纹理的矸石漏标。模型学到的 ore 特征空间既宽且散和煤块高度重叠。解决重新翻看煤矿输送带异物识别数据集的 ore 类别标注与现场技术人员定一个量化标准。常见可靠做法是以亮度、纹理、棱角三个维度打分满足两项以上才可标注为 ore拿不准的整帧剔除。改完标注重训后误报率从每 10 分钟 3 次降到每班 1 次以内。5.2 小异物漏检最小标注框设太大或太小现象验证集 mAP0.5 超过 0.9但锚杆掉在黑色皮带纹路里时完全检测不到。原因标注时把长边小于 30 像素的小框全部剔除了导致模型训练集里根本没有小目标样本或者反过来标注时保留了 8x8 像素级的小框这类框信号极弱模型学到的是噪声模式。解决把最小标注框阈值设为长边 24 像素同时在数据增强时多尺度策略要显式包含小目标。yolov8 里可以用 nms 参数配合调整但根源在数据端——抽帧时回收原始分辨率图像不压缩到 640 再标。24 像素的经验值在 1280 输入下对应目标在图像中占比约 2%是人眼能可靠辨别的下限低于此值的异物只能靠提高相机分辨率或安装第二路近摄相机解决。5.3 数据泄漏连续帧随机划分导致指标虚高现象测试集 mAP 0.93、现场漏检率 20%。原因数据划分用了随机 split一系列连续的皮带图像中同一根锚杆同时出现在训练集和验证集模型只是记住了这个具体目标。解决按第 3.3 节的时间序列划分并以第一次出现的时间为准对齐异物实例。修正后测试集 mAP 回落到 0.82与现场表现基本吻合这个 0.82 才是真实水平。5.4 训练 loss 居高不下脏标签太多现象训练第三个 epoch loss 开始震荡验证集 mAP 低且验证 loss 曲线呈上升趋势。原因标注框有的过大把煤流边缘也框进去了有的框中心偏移导致 YOLO 的 anchor 无法学习到稳定的物体中心。解决训练一个缩样模型用它对全量标注做预测找到置信度低但有标注的样本人工复查。这一招叫“模型反哺清洗”一次至少能发现 5% 的脏标签重标后 loss 曲线恢复平滑最终 mAP 提升 3 到 5 个点。6. 验证与迭代误报率统计和二次标注让数据集越用越值钱煤矿输送带异物识别数据集的价值不只是训一个模型而是持续迭代。我习惯在训练完成后留一天时间做现场试用重点不是跑 mAP而是记录 24 小时内模型的误报率和漏报率——比离线指标更有说服力。具体做法在皮带控制室部署一台测试机模型跑起来但只做记录不联锁动作同时安排一个小程序把触发报警的前后 5 帧自动存盘。下班后统计误报次数按小时画一条曲线如果集中在某几个时间段基本可以判定是特定光照或料流工况下的问题把对应的图像帧抽出来回灌训练集。这时候做一个轻量难例池每次模型训练完成都跑一遍这个难例池比调参靠谱得多——难例池里的样本是真实环境反馈的“错题本”。验证之后进入二次标注阶段把误报帧和漏报帧按第 2.3 节的规范重新标注补进原数据集。常见的做法是每两周做一轮每轮新增 500 到 1000 帧模型每季度重训一次。这样数据集会从一个静态的 5 万张快照变成一个持续增长、贴近现场工况的活资产。最后说一个我自己的习惯动作每次训练前把数据集的类别统计跑一遍打印每类的框数量、平均框尺寸、图像分辨率分布。如果连续两次实验这类统计差异很大那问题多半出在采集端或标注端而不是模型端。这套数据思维帮我少走了很多弯路也让我体会到判断一个数据集靠不靠谱先看它的类别分布和标签一致性比任何先进网络都管用。希望帮到你。本文还有配套的精品资源点击获取