简介:这份矿井煤仓传送带异物检测数据集,面向煤矿安全监测和计算机视觉研究人员,旨在解决传送带上石头、金属碎片等异物识别与定位问题。资源共73个文件,包含36张真实工况下的jpg现场图、36个配套的txt标注文件以及1个data.yaml配置,压缩包整体仅1.39MB,轻量易用,目录结构清晰。标注采用YOLO格式,记录每个异物的中心坐标、宽高和类别,并划分了train、valid、test子集,可直接用于YOLO系列模型的训练与验证,且便于模型评估与对比。数据集涵盖了不同光照、角度和传送带背景,配备的data.yaml可灵活调整训练参数,有助于训练出鲁棒性更强的检测模型,更好适应复杂工况。已有1911人学习下载,适合需要快速验证目标检测算法或开展煤矿安全智能化研究的开发者、科研人员及工程技术人员使用。使用该数据集可辅助构建实时异物告警系统,降低设备损坏和安全事故风险,提升煤矿生产效率。
1. 矿井煤仓传送带异物检测数据集:从 YOLO 标注格式到可直接启动训练的数据基础
煤炭运输环节里,传送带是最容易出“隐藏事故”的地方。一块从采面混进煤流里的金属锚杆、一段被矿石带偏的托辊碎片,如果没被及时发现,轻则划伤胶带,重则撕裂整条输送线,一次停机就是数小时的产能损失。矿井煤仓传送带异物检测数据集-yolo.zip 正是为解决这个问题准备的:它把现场照片整理成 YOLO 训练所需的标准目录结构,图片和 txt 标签一一对应,训练集、验证集划分完毕,还附带了 data.yaml。这意味着你不用从零开始采集、清洗和标注井下画面,拿到就能直接跑起目标检测训练。
这个资源适合三类人:一是做煤矿智能化改造的算法工程师,需要快速验证异物检测可行性;二是刚开始接触 YOLO 目标检测的学生或从业者,想用一张接近真实工况的数据集走通“数据到训练再到验证”的全流程;三是做工业视觉方案选型的技术负责人,需要评估现有数据能否满足识别精度和推理速度的双重要求。数据集本身只包含图像和标注文件,不含训练脚本和模型权重,但配合 Ultralytics 框架,从数据准备到模型评估是一条很顺畅的链路。
2. 数据集的真实构成:拆目录结构和 YOLO 标签的编码规则
2.1 目录结构里藏着什么:train、valid、test 的划分逻辑
解压 zip 后,第一件事不是急着跑训练,而是先看清目录里各文件夹承担的角色。常见做法是 train 用于模型学习,valid 用于训练过程中验证和调整超参数,test 则用来评估最终模型在未见数据上的表现。这套数据集的命名是 train、valid 和 test,和 Ultralytics 默认约定一致,不需要额外改文件夹名称。
实际使用前我一般会手动核对一个点:data.yaml 里指定的路径是绝对路径还是相对路径。由于解压位置不同,很多第一次运行时报错File not found的原因就是路径写死成了原作者机器上的目录。我的习惯是把 data.yaml 里的 path 字段改成../datasets/mine_conveyor这类相对路径,或者在训练命令里直接用data=/完整的绝对路径/data.yaml指定,避免路径问题干扰后续判断。
train 和 valid 下的布局是对称的:images 里存 JPEG 或 PNG 原图,labels 里存对应的 txt 文件。train 中包含的图片数量多、场景覆盖广,valid 相对少一些。test 目录在这套数据集里也存在,但训练时默认不会用到 test,它通常留给最终的评估验证。
2.2 YOLO 标签格式:归一化的四点标注为什么对训练友好
labels 目录下每个 txt 文件对应一张同名图片,文件内每一行描述一个目标实例。这一行由五个数值组成:class_id、x_center、y_center、width、height。class_id 是整数,从 0 开始计数;后面四个值是归一化后的浮点数,范围在 0 到 1 之间。归一化的意思是:坐标值除以图片宽高后得到的结果,因此和图像分辨率无关,无论原图是 640×640 还是 1920×1080,标注文件都能直接套用。
设图像宽度为 W,高度为 H,一个边界框的真实左上角坐标为 (x_min, y_min),右下角为 (x_max, y_max),那么转换公式为:
x_center = ((x_min + x_max) / 2) / W y_center = ((y_min + y_max) / 2) / H width = (x_max - x_min) / W height = (y_max - y_min) / H这套数据集里异物类别通常只有一类,class_id 固定为 0。读取某个标签文件时,可以用 Python 快速看一眼实际内容:
with open('labels/train/000123.txt', 'r') as f: lines = f.readlines() print(lines)输出类似0 0.5321 0.4877 0.1532 0.2184。四个浮点数值分别是归一化中心坐标和宽高。训练时 YOLO 模型会把原图缩放到网络输入尺寸,并通过归一化坐标映射回缩放后的特征图,所以不需要人工调整标注值。这种格式的优势在于,当训练时输入图片大小变化时,标注坐标不需要跟着变化,模型内部会自己处理尺度问题。
我还建议检查一下标注框是否超出图像边界。有些标注工具生成的框可能略微越界,训练时一般不会报错,但会影响边界框回归的精度。可以通过解析所有 txt 文件,过滤掉 width 或 height 为 0 的文件,这种文件代表空标注,通常出现在没有异物的负样本图片中。负样本对训练很有价值,它能让模型学习区分“正常煤流”和“含异物”的情况,减少误报。
2.3 data.yaml 的作用:类别映射和路径配置
data.yaml 是数据集的心脏。它定义了训练时框架从哪里读图片、有几个类别、类别名称分别是什么。典型内容如下:
path: ../datasets/mine_conveyor train: train/images val: valid/images test: test/images nc: 1 names: ['foreign_object']nc是类别数量,这里为 1,表示只检测异物一类。names是类别名称列表,长度必须和nc一致,否则训练直接报错。训练时模型输出的预测结果里会带类别名称,推理阶段在画框时也会用这里的名称做标签。
如果后续需要扩展检测类别,比如把“金属异物”和“非金属异物”分开标注,那么 nc 变成 2,names 变成['metal', 'nonmetal'],同时所有标签文件里的 class_id 也要做对应更新。这种改动建议写一个脚本批量处理,手动改几百个文件容易出错。
3. 训练前准备:把数据集整理成工程能用且能保证训练稳定的状态
3.1 划分验证集:为什么 valid 不能和 train 有重复图片
数据集中 train 和 valid 已经划分好了,但如果你是从别的来源收集图片后自己建数据集,一定要注意 train 和 valid 不能有重复图片。一旦验证集里出现训练集见过的图片,验证 loss 和 mAP 会虚高,模型实际部署后表现可能远低于预期。这个问题在公开数据集里不常见,但自己合并多个来源的图片时经常出现,我见过有人把同一个视频抽帧的图片随机分到 train 和 valid 中,导致验证结果失真。
检查重复图片的常见做法是用图片的哈希值做对比:
import hashlib from pathlib import Path def file_hash(path: Path) -> str: return hashlib.md5(path.read_bytes()).hexdigest() train_hashes = {file_hash(p) for p in Path('train/images').glob('*')} valid_hashes = {file_hash(p) for p in Path('valid/images').glob('*')} duplicates = train_hashes & valid_hashes print(f'重复图片数量: {len(duplicates)}')如果发现重复图片,优先把重复项从 valid 中移除,或重新从原始视频中抽帧补充。训练时一旦验证集“泄题”,你调参时看的所有指标都会失真,最后部署到现场摄像头前那一刻才发现,返工成本极高。
3.2 标签检查脚本:扫描空文件、格式错乱、坐标越界
标注文件的质量直接决定训练效果。拿到数据集后不要直接开训,先写一个脚本做全量检查。检查的内容包括三点:文件是否为空、行内是否有五个数值、坐标是否在 0 到 1 之间。代码示例:
from pathlib import Path for split in ['train', 'valid']: label_dir = Path(f'{split}/labels') for label_file in label_dir.glob('*.txt'): lines = label_file.read_text().strip().splitlines() if len(lines) == 0: print(f'空标注文件: {label_file}') continue for line in lines: parts = line.split() if len(parts) != 5: print(f'格式错误: {label_file} -> {line}') continue class_id, x_center, y_center, width, height = map(float, parts) if not (0 < x_center < 1 and 0 < y_center < 1): print(f'中心坐标越界: {label_file} -> {line}')这里要说明:x_center 和 y_center 理论范围是 0 到 1,但边界框中心恰好为 0 或 1 的情况很少见,一旦出现,多半是标注精度有问题。width 和 height 也可能出现接近 0 的极端小值,比如小于 0.001,这种小目标在训练时难以学习,需要判断是真实存在的远处小异物还是标注失误。发现问题后,用 LabelImg 或 X-AnyLabeling 打开原图,定位到对应目标,手动修正。批量修改时务必先做备份,避免误操作破坏原始数据。
3.3 类别平衡与负样本:异物占比低时如何防止模型“只见煤流不见异物”
煤矿传送带场景有一个典型问题:异物出现频率低,大部分画面是正常的煤流。如果数据集中负样本(无异物图片)过多,模型会倾向于把所有目标都预测为背景,精确率可能很高但召回率非常低。异物检测的核心矛盾在于漏检比误报更严重——漏掉一个金属物可能导致胶带撕裂,误报一次顶多让巡检人员多看一眼。
处理方法有两种:一种是过采样,复制含异物的图片若干次,让训练时模型更频繁地看到正样本;另一种是调整 loss 权重,在 Ultralytics YOLO 的配置里,可以在损失函数层面对类别做权重调整,但这套数据集是单类别,内部类别不平衡问题不严重。更需要关注的分布是“不同形态异物”的覆盖:金属棒、大块矸石、锚杆、手套等,如果含异物的图片只有某一种形态,模型泛化能力会受限制。
动手训练前,我建议统计一下 train 目录下含异物和空标注的图片数量,做到心里有数。写个脚本统计标签文件行数并分组:
find train/labels -name "*.txt" -exec wc -l {} \; | awk '{if($1==0) print $2}' | wc -l3.4 硬性问题:YOLOv8 训练前为什么不要手动改图像尺寸
很多第一次用 YOLO 的人会问:我的图片是 1920×1080,模型输入是 640×640,要不要先把图片裁剪或缩放?答案是不需要。Ultralytics 框架在训练时会自动做 letterbox 处理,即保持宽高比缩放到 640 以内,剩余部分用灰边填充。手动提前缩放反而会丢失细节,影响小目标检测效果。
真正需要关注的是图片中目标的大小。如果大多数异物在图片中的像素面积很小,比如 30×30 以下,在 640×640 输入下可能只剩 10×10 像素,模型很难学出有效特征。此时可以考虑提高输入分辨率,比如用imgsz=1280训练,但显存消耗会显著增加。这套数据集的图片如果来自工业相机,分辨率通常较高,用 640 或 1280 分别跑一次对比 mAP,再决定最终部署时的推理尺寸。
4. 完整训练流程:用 Ultralytics YOLOv8 跑通异物检测模型
4.1 环境准备:不需要重装框架,一个指令解决依赖
先安装训练依赖,推荐用 conda 创建独立 Python 3.10 环境,避免污染系统环境:
conda create -n yolo python=3.10 -y conda activate yolo pip install ultralytics opencv-pythonultralytics包自带训练、验证、推理的完整命令行接口,不依赖单独的 PyTorch 安装步骤——当你安装 ultralytics 时,pip 会自动处理 PyTorch 核心库的依赖。但如果你的机器有旧版 CUDA,建议单独安装对应版本的 PyTorch 再装 ultralytics,否则可能遇到驱动不兼容的问题。
安装完成后判断 GPU 是否可用:
import torch print(torch.cuda.is_available())如果输出 False,说明当前环境用的是 CPU 训练。CPU 训练不是不能用,但速度慢得多,一张 640×640 图片的 epoch 可能要数小时,建议先确认环境是不是 GPU 环境再决定训练轮数。
4.2 启动训练:命令参数里的关键配置和它们的影响
数据按前文整理好后,训练命令如下:
yolo detect train \ data=path/to/data.yaml \ model=yolov8n.pt \ epochs=100 \ imgsz=640 \ batch=16 \ device=0 \ patience=20model 参数指定预训练权重,yolov8n.pt 是 nano 版本,速度最快但精度略低;如果想追求更高精度,可以换成 yolov8s.pt 或 yolov8m.pt。**常见做法是先用 nano 版本跑通完整流程,确认数据没问题后再换大模型正式训练。**batch 大小取决于显卡显存,常见显卡如 RTX 3060 推荐 batch=16,更大显存可以上调到 32。patience 是早停参数,意思是验证集指标连续 20 轮没有提升就停止训练,可以避免无效等待。
训练过程中控制台会实时打印每个 epoch 的 box_loss、cls_loss、dfl_loss 和验证结果。需要重点看的是mAP50和mAP50-95,mAP50 表示 IoU 阈值为 0.5 时的平均精度,mAP50-95 是多个阈值下的平均结果。异物检测场景下,mAP50 达到 0.9 以上才算比较理想,mAP50-95 通常在 0.6 到 0.8 之间浮动,这两者的差距越大,说明模型对边框精度的把握越弱。
4.3 验证和评估:从指标到可视化,判断模型是否真的可用
训练结束后 Ultralytics 会在 runs/detect/train 目录下生成一堆文件,其中confusion_matrix.png、results.png、val_batch*.jpg是最需要看的三个结果。confusion_matrix 可以看到异物类别是 FF(真阳)还是 FN(假阴),在矿井异物检测中,FN 率过高意味着实际场景下会漏检,这是最危险的指标。
再看看results.png里包含的曲线:训练 loss 曲线如果一直在下降且没有剧烈震荡,说明模型没有过拟合或欠拟合;验证阶段的 mAP 曲线稳步上升后趋于平缓,则说明模型已收敛。如果 loss 曲线训练后期还在下降但 mAP 停滞,就要考虑加数据增强或提前停止训练。
验证命令也很简单:
yolo detect val \ model=runs/detect/train/weights/best.pt \ data=path/to/data.yaml它会输出 mAP50、mAP50-95、precision、recall 等指标。把 recall 单独列出来看,如果低于 0.85,在异物检测场景下风险较大,需要回到数据层面补充更多正例样本。
5. 避坑与常见问题排查:异物检测数据集训练中的实操案例
5.1 现象:训练 loss 正常下降,但验证集 mAP 始终在 0.3 以下
原因分析:最常见的情况是标签类别编号不匹配。data.yaml 里 n 为 1,如果 labels 目录下的 txt 文件中出现 class_id 为 1 或 2 的行,模型就会把不存在的类别当作空目标,导致训练信号混乱。另一个常见原因是图片 EXIF 旋转信息未被处理,导致标注框和实际目标朝向错位,模型学不到有效特征。
解决办法:批量扫描所有标签文件,统计 class_id 的分布,确认都等于 0。对 EXIF 问题,用 Python 的 Pillow 库统一转正并重新保存图片:
from PIL import Image from pathlib import Path for img_path in Path('train/images').glob('*'): img = Image.open(img_path) img = ImageOps.exif_transpose(img) img.save(img_path)转正后必须重新确认标签坐标是否正确,因为 EXIF 旋转后图片的宽高可能互换,而原有标注是按旋转前坐标系标注的。
5.2 现象:训练时 loss 出现 NaN,或训练过程中直接崩掉
原因分析:多为标签中存在非法值,比如宽高为负数、坐标无穷大,或者是标签行用逗号分隔(部分工具导出的是class,x,y,w,h而不是空格分隔),导致解析失败。另一种情况是 batch size 过大导致显存溢出,此时通常伴随 CUDA out of memory 报错。
解决办法:跑一遍标签清洗脚本,把非数字字符的标签剔除,检查每行是否用英文空格分隔。针对显存溢出,调小 batch,例如从 16 降到 8,或降低 imgsz 到 512。训练稳定性优先于单次 epoch 的训练速度,少量样本一样能学到有效特征。
5.3 现象:检测时对煤流中的正常煤块频繁误报
原因分析:数据集中异物形态和煤块的样本不够均衡,尤其是负样本中带有特殊纹理的煤块,模型容易把纹理复杂的煤块当作异物。训练时模型没见过足够多“像异物但实为煤块”的反例,决策边界就没法很好地区分。
解决办法:回到图片层面补充负样本,收集更多正常煤流但表面纹路相近的图片,放进 train 目录,同时将标签文件置空。也可以打开数据增强选项,Ultralytics 中增加hsv_h=0.015等色彩增强参数,让模型对颜色差异更敏感,减少对纹理的过拟合。
5.4 现象:相同数据集在另一台机器上训练后 mAP 数值差异很大
原因分析:除了随机种子和硬件浮点计算差异外,最可能的原因是两套环境里安装了不同版本的 ultralytics 或 PyTorch,模型结构或 Anchor 设置存在差异。工业场景里换机器训练是常态,如果指标波动超过 5%,需要固定依赖版本。
解决办法:在项目目录写一个 requirements.txt,锁定关键库版本:ultralytics==8.2.0、torch==2.2.0。训练前打印import ultralytics; print(ultralytics.__version__)确认版本一致。
5.5 现象:推理速度达不到实时要求,30 FPS 的摄像头只能跑 8 FPS
原因分析:模型参数量过大或推理分辨率过高。yolov8n 在 640 输入、GPU 上通常能超过 100 FPS,但如果笔记本只有 CPU 或显存不足,速度会急剧下降。另一个原因是摄像头的解码和帧率转换环节耗掉了大量时间,模型本身只占部分延迟。
解决办法:先用yolo predict在静态图片上跑一遍,确认单张耗时。若单张全流程超过 100ms,优先换小模型或降 imgsz。部署时把图像缩放放在预处理阶段做一次,避免每帧重复缩放。矿井环境的摄像头通常帧率不需要太高,15 FPS 足以覆盖传送带移动速度下的异物检测需求。
6. 部署中的进阶技巧:用训练好的权重跑实时视频推理并做帧率调优
训练完成后,权重文件best.pt才是最终交付物。把这个权重放到推理机上,跑一段模拟摄像头数据流,测试实际效果。Ultralytics 里自带了 VideoStream 的接口,也可以直接用 OpenCV 读取视频文件模拟实时数据:
import cv2 from ultralytics import YOLO model = YOLO('best.pt') video_path = 'conveyor_sample.mp4' cap = cv2.VideoCapture(video_path) frame_width = int(cap.get(cv2.CAP_PROP_FRAME_WIDTH)) frame_height = int(cap.get(cv2.CAP_PROP_FRAME_HEIGHT)) fps = cap.get(cv2.CAP_PROP_FPS) out = cv2.VideoWriter('result.mp4', cv2.VideoWriter_fourcc(*'mp4v'), fps, (frame_width, frame_height)) while True: ret, frame = cap.read() if not ret: break results = model(frame, imgsz=640, conf=0.5, verbose=False) annotated_frame = results[0].plot() out.write(annotated_frame) cv2.imshow('Conveyor Detection', annotated_frame) if cv2.waitKey(1) & 0xFF == ord('q'): break cap.release() out.release() cv2.destroyAllWindows()conf=0.5表示置信度阈值,低于这个值的预测框会被过滤掉。异物检测场景里,我通常会调低到 0.3 甚至 0.25,这并不是因为模型精度不足,而是因为漏检的代价远高于误检。误检最多让中控台多响一次警报,漏检一次可能就是在为以后的事故埋单。调低阈值后,如果误报率过高,可以换成更严格的 NMS 参数,或者加入一个二次确认逻辑:连续两帧都在相近位置检测到异物才触发警报。
调优时要注意一个层级:模型层(置信度阈值、NMS 阈值、推理帧率),系统层(相机分辨率、传送带速度、检测触发机制)。传送带速度是决定一切的前提——如果皮带速度是 3m/s,相机视野宽度是 2m,那么在视野内停留的时间只有 0.67 秒。这意味着从检测到发出停机信号,系统要在 0.5 秒内完成推理和响应。网络推理用时之外,还要把相机采集、图像传输、PLC 控制的延迟算进去,预留至少 100ms 的余量。
从那以后,我每次训练异物检测模型都会把“漏检代价”放在最前面来设计阈值和评估指标,而不是一味追求 mAP 数值好看。部署前我不只看测试集上的指标,还会专门取一段没有标注过的现场视频跑一遍推理,人工检查误报和漏报。这套流程陪我避开了不少坑,数据和实际现场之间的差距,往往就在这些细节里暴露出来。希望帮到你。
本文还有配套的精品资源,点击获取