ARTICLE DETAIL

建站实战干货

来自一线的建站与推广经验沉淀,每一条都经过真实交付验证。

煤矸石识别数据集与YOLO目标检测实战:从标注到产线部署

2026/10/2 8:19:00 拓冰建站 浏览量
煤矸石识别数据集与YOLO目标检测实战:从标注到产线部署 简介这份煤矸石识别数据集面向从事目标检测与深度学习实践的开发者、学生及科研人员尤其适合正在训练YOLO系列、Faster R-CNN、SSD等模型的用户用于解决煤与矸石分选场景下的图像识别与定位问题。资源包共2000个文件以1999个txt标签文件和1个yaml类别配置文件为主压缩包约166.01MB其中txt文件对应每张图像的标注信息yaml文件则指定了Coal与Rock两个类别的名称与路径便于直接接入训练流程。数据集包含3091张图片同时提供YOLO格式与VOC格式的xml标签并已按训练集、验证集和测试集完成划分省去自行切分的步骤。目前已有725人学习下载读者可直接获得一套结构完整、开箱即用的煤矸石检测数据用于模型训练、对比实验或算法验证快速推进目标检测相关项目。1. 煤矸石识别数据集从人工选矸到目标检测落地的第一手拆解在煤矿地面选矸车间待过的人都知道皮带上的煤和矸石混在一起靠人工拿铁锹分拣一个班下来胳膊都抬不起来而且分拣精度全凭老师傅的眼力年轻人根本顶不上。这几年不少矿上开始上机器视觉方案核心思路就是用目标检测模型把煤和矸石框出来再驱动气排枪或者机械臂去分。但真正动手做的时候第一个卡住大多数人的不是模型结构而是数据集——网上公开的煤矸石识别数据集少得可怜自己拿手机拍几百张又根本不够训练。这份煤矸石识别数据集就是冲着这个缺口来的它面向目标检测任务标注格式适配 YOLO 系列包含煤块、矸石以及混合状态下的多类目标框。适合谁用做矿山智能化改造的算法工程师、带学生做课题的高校老师、以及想拿真实工业场景练手目标检测的开发者。你拿到手之后不用再从零标注几千张图直接就能跑通训练和推理链路。2. 数据集结构与标注格式先搞清楚手里拿的是什么2.1 目录组织与文件命名逻辑拿到一个目标检测数据集第一件事不是急着写训练脚本而是把目录结构摸清楚。这份煤矸石数据集常见做法是按images和labels两个平行目录组织内部再按train、val、test划分。图片格式以.jpg为主标注文件是 YOLO 标准的.txt每行一个目标格式为class_id x_center y_center width height坐标全部归一化到 0 到 1 之间。先跑一段脚本把结构打印出来心里有数再动手import os from pathlib import Path root Path(coal_gangue_dataset) for split in [train, val, test]: img_dir root / images / split lbl_dir root / labels / split imgs list(img_dir.glob(*.jpg)) list(img_dir.glob(*.png)) lbls list(lbl_dir.glob(*.txt)) print(f[{split}] images{len(imgs)}, labels{len(lbls)}) # 检查图片和标注是否一一对应 img_stems {p.stem for p in imgs} lbl_stems {p.stem for p in lbls} missing img_stems - lbl_stems if missing: print(f 警告{len(missing)} 张图片没有对应标注例如 {list(missing)[:3]})这段代码做三件事统计每个 split 下的图片和标注数量、检查是否有图片缺标注、打印缺失样例。参数上root换成你实际解压后的路径即可。如果missing不为空说明数据集本身有脏样本训练前必须处理掉否则 YOLO 在加载时会直接跳过或者报错。2.2 类别定义与标注质量判断煤矸石检测的类别定义直接决定模型能不能用。常见做法是分两类coal煤和gangue矸石。但实际场景里还有一类容易被忽略——煤矸混合体也就是一块物料上既有煤又有矸石边界模糊。如果数据集里把这类也单独标了一类那类别数就是 3。你需要打开data.yaml或者类别映射文件确认# data.yaml 典型结构 path: ./coal_gangue_dataset train: images/train val: images/val test: images/test nc: 2 names: 0: coal 1: ganguenc是类别数names是类别名到 id 的映射。这里有个血泪经验如果你拿到的数据集nc2但标注文件里出现了class_id2YOLO 训练时会直接报索引越界。所以拿到数据后先跑一遍类别 id 分布统计from collections import Counter lbl_dir Path(coal_gangue_dataset/labels/train) counter Counter() for txt in lbl_dir.glob(*.txt): for line in txt.read_text().strip().splitlines(): if line: counter[int(line.split()[0])] 1 print(类别分布, dict(counter))如果统计出来的 id 集合和data.yaml里的names对不上要么改 yaml要么清洗标注没有第三条路。标注质量方面重点看框是否贴合目标边缘、有没有漏标小目标。煤矸石在皮带上经常是堆叠状态遮挡严重如果标注时只框了露出来的部分模型学到的就是残缺特征推理时容易漏检。3. 训练环境搭建与 YOLO 配置从零跑通第一条基线3.1 环境依赖与版本选择目标检测训练环境最怕版本打架。这份数据集适配 YOLO 系列当前主流选择是 YOLOv8 或 YOLOv11两者在 API 上基本兼容。我一般会锁定以下组合避免玄学报错组件推荐版本说明Python3.9 / 3.103.11 以上某些 torch 版本兼容性差PyTorch2.0.1cu118有 GPU 就用 CUDA 版没有就用 CPU 版ultralytics8.2.xYOLOv8/v11 统一接口opencv-python4.8.x读图、可视化推理结果numpy1.24.x避免 2.x 的 API 变动安装命令一行搞定pip install ultralytics8.2.0 opencv-python4.8.1.78 numpy1.24.3如果你用的是 30 系或 40 系显卡CUDA 版本建议 11.8驱动版本别低于 520。装完之后跑python -c import torch; print(torch.cuda.is_available())输出True才算 GPU 可用。这一步翻车的人最多明明装了 GPU 版 torch结果cuda.is_available()返回False多半是驱动和 CUDA 版本不匹配重装驱动或者换 torch 版本。3.2 训练脚本与关键参数设置环境通了之后写训练脚本。YOLOv8 的接口很简洁但参数设不对训出来的模型就是废的from ultralytics import YOLO # 加载预训练权重没有就自动下载 model YOLO(yolov8n.pt) # 开始训练 results model.train( datacoal_gangue_dataset/data.yaml, # 数据集配置文件 epochs100, # 训练轮数 imgsz640, # 输入图像尺寸 batch16, # 批次大小显存不够就调小 device0, # GPU 编号CPU 填 cpu workers4, # 数据加载线程数 optimizerSGD, # 优化器 lr00.01, # 初始学习率 lrf0.01, # 最终学习率因子 momentum0.937, # 动量 weight_decay0.0005, # 权重衰减 warmup_epochs3.0, # 预热轮数 patience50, # 早停耐心值 saveTrue, # 保存检查点 projectruns/coal, # 输出目录 namebaseline, # 实验名 )逐项说清楚imgsz640是 YOLO 的默认输入尺寸煤矸石目标在图像中占比中等640 够用如果矸石颗粒很小可以提到 1280但显存翻倍。batch16是 8G 显存的安全值12G 以上可以上 32。lr00.01配合SGD是 YOLO 官方推荐的基线如果你换AdamW学习率要降到0.001左右。patience50表示验证集损失 50 轮不降就停防止过拟合。workers在 Windows 上有时会卡死设成 0 用主进程加载最稳。训练启动后终端会打印每轮的 box_loss、cls_loss、mAP50 等指标。重点盯mAP50-95这个指标综合了不同 IoU 阈值下的精度比单纯看mAP50更能反映模型定位能力。如果mAP50很高但mAP50-95很低说明框的位置不够准可能是标注框偏大或偏小。3.3 训练过程监控与日志解读训练不是跑上就不管了。YOLO 会在runs/coal/baseline/下生成results.csv和weights/目录。results.csv每行是一轮列包括epoch、train/box_loss、train/cls_loss、metrics/mAP50、metrics/mAP50-95等。用 pandas 拉出来画个曲线比盯着终端刷屏直观import pandas as pd import matplotlib.pyplot as plt df pd.read_csv(runs/coal/baseline/results.csv) df.columns df.columns.str.strip() # 列名可能有空格 fig, axes plt.subplots(1, 2, figsize(12, 4)) axes[0].plot(df[epoch], df[train/box_loss], labelbox_loss) axes[0].plot(df[epoch], df[train/cls_loss], labelcls_loss) axes[0].set_xlabel(epoch) axes[0].set_ylabel(loss) axes[0].legend() axes[1].plot(df[epoch], df[metrics/mAP50], labelmAP50) axes[1].plot(df[epoch], df[metrics/mAP50-95], labelmAP50-95) axes[1].set_xlabel(epoch) axes[1].set_ylabel(mAP) axes[1].legend() plt.tight_layout() plt.savefig(training_curve.png, dpi150)正常收敛的曲线是box_loss 和 cls_loss 在前 10 轮快速下降之后缓慢下降并趋于平稳mAP50 在前 20 轮快速上升之后缓慢爬升。如果 loss 震荡剧烈多半是学习率太大或者 batch 太小如果 loss 不降检查数据标注是不是有问题或者预训练权重没加载上。results.csv里还有lr/pg0列可以看到学习率随轮数的变化YOLO 默认用的是余弦退火或线性衰减不用手动调。4. 推理验证与效果评估模型到底能不能用4.1 单张图片推理与可视化训练完拿到best.pt先别急着部署拿几张验证集图片跑推理肉眼看看框得准不准from ultralytics import YOLO import cv2 model YOLO(runs/coal/baseline/weights/best.pt) results model.predict( sourcecoal_gangue_dataset/images/val, conf0.25, # 置信度阈值 iou0.45, # NMS IoU 阈值 imgsz640, saveTrue, # 保存可视化结果 projectruns/coal, nameval_pred, )conf0.25表示只保留置信度高于 0.25 的框调低会召回更多目标但误检增加调高则相反。iou0.45是 NMS 的阈值控制重叠框的合并程度。煤矸石堆叠场景下如果两个目标挨得很近iou设太高会把其中一个框删掉设太低又会保留重复框。我一般会在 0.4 到 0.6 之间试几组看哪个在验证集上 mAP 最高。推理结果保存在runs/coal/val_pred/下每张图会画出框和类别标签。打开几张看看重点关注矸石和煤的边界是否清晰、有没有把煤误判成矸石、小颗粒矸石有没有漏掉。如果发现某类目标普遍漏检回去看训练集里这类样本是不是太少或者标注框是不是太小。4.2 评估指标解读与阈值调优YOLO 训练结束后会自动在验证集上算指标终端会打印类似这样的结果Class Images Instances P R mAP50 mAP50-95 all 500 1200 0.892 0.845 0.901 0.623 coal 500 700 0.910 0.870 0.920 0.650 gangue 500 500 0.874 0.820 0.882 0.596P是精确率R是召回率mAP50是 IoU0.5 时的平均精度mAP50-95是 IoU 从 0.5 到 0.95 每隔 0.05 取一次的平均值。煤矸石检测场景下mAP50能到 0.9 以上算不错mAP50-95能到 0.6 以上说明定位比较准。如果gangue的召回率明显低于coal说明矸石样本可能偏少或者特征不明显可以考虑过采样或者加数据增强。阈值调优可以用 YOLO 自带的val模式批量跑不同conffrom ultralytics import YOLO model YOLO(runs/coal/baseline/weights/best.pt) for conf in [0.1, 0.2, 0.3, 0.4, 0.5]: metrics model.val( datacoal_gangue_dataset/data.yaml, confconf, iou0.45, splitval, ) print(fconf{conf}, mAP50{metrics.box.map50:.4f}, mAP50-95{metrics.box.map:.4f})跑完对比一下选 mAP50-95 最高的那个conf作为部署阈值。注意验证集上的最优阈值不一定等于实际产线的最优阈值因为产线图像分布可能和验证集有差异最终还是要拿现场数据测。5. 避坑与常见问题排查那些让我熬夜的坑5.1 标注文件与图片不匹配现象训练启动时报FileNotFoundError或者IndexError提示某个标注文件找不到或类别 id 越界。原因通常是图片和标注文件名不一致比如图片叫IMG_001.jpg标注叫IMG_001.txt但实际是img_001.txt大小写敏感导致匹配失败。解决跑一遍前面 2.1 节的对应检查脚本把不匹配的文件找出来统一重命名。Windows 下文件名不区分大小写但 Linux 下区分所以本地跑得好好的传到服务器就翻车。5.2 显存溢出导致训练中断现象训练跑了几轮突然报CUDA out of memory进程被 kill。原因一般是batch设太大或者imgsz设太高或者workers太多导致数据加载占用显存。解决先把batch减半如果还不行就把imgsz从 640 降到 512再不行就设workers0。另外YOLO 默认会缓存图片到内存加速训练如果数据集很大可以设cacheFalse关掉缓存。5.3 验证集 mAP 虚高但实际推理效果差现象训练日志里mAP50到了 0.95但拿现场图片推理漏检和误检一大堆。原因是验证集和训练集来自同一批数据分布太接近模型过拟合了。解决检查数据集划分是不是随机分的如果训练集和验证集里有同一块煤矸石的不同角度照片模型等于在背答案。正确做法是按拍摄批次或场景划分确保验证集里的物料和训练集不重叠。另外可以加一些现场没见过的负样本比如空皮带、水渍、阴影让模型学会区分。5.4 类别不平衡导致小类漏检现象coal的 mAP 很高但gangue的召回率很低很多矸石没框出来。原因是训练集里煤的样本远多于矸石模型偏向于预测多数类。解决在data.yaml里给每个类加权重或者用 YOLO 的cls_pw参数调整类别损失权重。更直接的办法是过采样矸石样本把矸石图片复制多份或者用数据增强旋转、裁剪、色彩抖动扩充矸石样本。我一般会先把类别分布打出来如果某一类占比低于 20%就要警惕了。5.5 推理速度不达标现象模型精度够了但推理一张图要几百毫秒产线皮带速度一快就跟不上。原因是用了yolov8x这种大模型或者输入尺寸设了 1280。解决换yolov8n或yolov8s轻量模型输入尺寸降到 640 甚至 416再用 TensorRT 或 ONNX Runtime 加速。实测yolov8n在 640 尺寸下RTX 3060 上单张推理能到 5ms 以内完全够产线用。精度会掉一点但可以通过增加训练轮数和数据增强补回来。6. 进阶技巧把煤矸石检测模型推到产线可用6.1 数据增强策略的针对性调整YOLO 默认的数据增强包括 HSV 抖动、随机翻转、马赛克增强等。煤矸石场景下马赛克增强要慎用因为它会把四张图拼成一张导致矸石颗粒被切割模型学到的目标不完整。我一般会关掉马赛克改用mixup和copy_paste前者把两张图按透明度叠加后者把目标复制到另一张图上对堆叠场景更友好。配置写在data.yaml同级目录的hyps.yaml里训练时用hyp参数指定# hyps_coal.yaml mosaic: 0.0 # 关闭马赛克 mixup: 0.15 # 混合增强概率 copy_paste: 0.3 # 复制粘贴增强概率 hsv_h: 0.015 # 色调抖动 hsv_s: 0.7 # 饱和度抖动 hsv_v: 0.4 # 亮度抖动 degrees: 10.0 # 旋转角度范围 translate: 0.1 # 平移比例 scale: 0.5 # 缩放比例训练时加一行hyphyps_coal.yaml即可。这些参数不是拍脑袋定的mixup0.15和copy_paste0.3是我在几个矿山数据集上试出来的平衡点再高会引入太多噪声再低起不到增强效果。6.2 模型导出与产线部署验证训练完的.pt文件不能直接上产线一般要导出成 ONNX 或 TensorRT。导出命令from ultralytics import YOLO model YOLO(runs/coal/baseline/weights/best.pt) model.export( formatonnx, imgsz640, halfTrue, # FP16 量化GPU 推理加速 simplifyTrue, # 简化计算图 opset12, # ONNX 算子集版本 )导出后在产线工控机上用 ONNX Runtime 加载写一个简单的推理循环拿现场摄像头实时流测试。重点验证三件事推理延迟是否稳定在 20ms 以内、连续跑 8 小时有没有内存泄漏、不同光照条件下白天、夜晚、粉尘的检测效果是否一致。我习惯在产线部署前先拿一段录制的现场视频离线跑一遍统计漏检率和误检率和验证集指标对比如果差距超过 10%说明模型泛化不够得回去补数据。从那以后我每次拿到新的目标检测数据集都强制走一遍「结构检查 → 类别分布 → 基线训练 → 现场验证」的流程不再跳过任何一步。希望这份煤矸石识别数据集能帮你省掉从零标注的苦力活把时间花在模型调优和产线落地上。本文还有配套的精品资源点击获取