☰
煤矸石识别数据集实战:102张现场原图跑通YOLOv8训练与部署
2026/10/1 4:54:31 网站建设 项目流程

简介:这份煤矸石识别数据集面向煤矿智能化分选、矿物图像识别方向的算法工程师与高校研究者,用于训练和验证煤炭、煤矸石、高岭石三类目标的检测模型,适合具备一定深度学习基础、正在开展YOLO系列目标检测实践的人员。资源包共205个文件,以102张现场采集的原始jpg图片和102个同名txt标注文件为主,另含1个yaml配置文件,整体约2.26MB,标注采用YOLOv8格式,可直接接入主流检测框架进行训练与评估。图片均来自真实煤矿现场,覆盖不同光照与堆叠状态,能较好反映实际工况下的类间差异与识别难点。目前已有459人学习下载。借助该数据集,读者可快速搭建三分类检测基线,完成数据加载、模型微调与指标对比,并据此分析煤与煤矸石、高岭石在纹理和灰度上的区分特征,为后续扩充样本、优化标注与提升分选精度提供可复用的实验基础。

1. 煤矸石识别数据集:102 张现场原图能跑出什么结果

在煤矿智能化改造的现场,煤矸石分选一直是个绕不开的环节。人工选矸劳动强度大、效率低,而基于机器视觉的自动识别方案,第一步卡住的往往不是模型结构,而是数据。这份煤矸石识别数据集,包含 102 张现场采集的原始图片,标注格式为 YOLOv8 可直接读取的 txt 文件,覆盖煤炭、煤矸石、高岭石三个类别。它不是那种从公开数据集里裁剪拼接出来的“干净样本”,而是带着现场光照波动、粉尘干扰、传送带背景的真实图像。适合谁用?如果你正在做煤矿场景的目标检测落地验证,或者需要一个小规模但真实的样本集来跑通 YOLOv8 训练全流程,这份资源能让你跳过最耗时的数据采集阶段,直接进入模型调参与部署测试。102 张的体量不算大,但对于验证技术路线、调试数据增强策略、评估标注质量对检测精度的影响,已经够用了。

2. YOLOv8 数据格式拆解:从文件名到标注文件的对应关系

2.1 目录结构与文件命名规律

拿到数据集后,先别急着写训练脚本。我一般会先花十分钟把目录结构摸清楚,因为标注文件和图片的对应关系一旦错位,后面训练 loss 不降你都不知道是模型问题还是数据问题。这份数据集的图片命名带有明显的预处理痕迹,类似012_png.rf.1fcc9085833b5c1b93d64d030804ac7e.jpg这种格式,rf通常是 Roboflow 导出时的标识,后面跟的哈希值用于保证文件名唯一。图片格式统一为 jpg,标注文件为同名的 txt,放在labels目录下。标准 YOLOv8 数据集目录长这样:

dataset/ ├── images/ │ ├── train/ │ │ ├── 001_png.rf.xxxx.jpg │ │ └── ... │ └── val/ │ └── ... ├── labels/ │ ├── train/ │ │ ├── 001_png.rf.xxxx.txt │ │ └── ... │ └── val/ │ └── ... └── data.yaml

如果你拿到的压缩包里没有预先划分 train/val,那就需要自己写脚本按比例拆分。常见做法是 8:2 或 9:1,102 张图的话,验证集留 10 到 20 张比较合适。注意,拆分时要保证图片和标注文件同步移动,别只挪了 jpg 忘了 txt。

2.2 标注文件内容解析与类别索引确认

YOLO 格式的标注文件每一行代表一个目标,格式为:

<class_id> <x_center> <y_center> <width> <height>

其中坐标都是归一化到 0 到 1 之间的浮点数。这份数据集定义了三个类别:煤炭、煤矸石、高岭石。类别索引通常是 0、1、2,但不同标注工具导出的顺序可能不一样。我踩过的坑是:拿到数据集直接开训,结果模型把煤矸石识别成了煤炭,排查半天才发现data.yaml里的names顺序和标注文件里的 class_id 对不上。所以第一步应该是打开几个标注文件,确认 class_id 的分布,再和data.yaml核对。

import os label_dir = "dataset/labels/train" class_count = {} for txt_file in os.listdir(label_dir): if not txt_file.endswith(".txt"): continue with open(os.path.join(label_dir, txt_file), "r") as f: for line in f: class_id = int(line.strip().split()[0]) class_count[class_id] = class_count.get(class_id, 0) + 1 print("类别分布:", class_count) # 预期输出类似:{0: 45, 1: 38, 2: 22} # 如果某个类别数量为 0,说明标注有问题或类别索引写错了

这段脚本遍历所有标注文件,统计每个 class_id 出现的次数。如果某个类别计数明显偏低甚至为 0,要么是标注遗漏,要么是类别索引映射错了。参数方面,label_dir指向你的标注目录,确保路径正确。统计结果还能帮你判断类别是否均衡——如果煤炭样本远多于高岭石,训练时可能需要做类别加权或过采样。

2.3 data.yaml 配置文件的正确写法

data.yaml是 YOLOv8 训练入口文件,路径和类别名都在这里定义。一个容易翻车的地方是路径写法:path建议用绝对路径,train和val用相对路径,这样在不同机器上迁移时不容易出错。

path: /home/user/dataset # 数据集根目录,建议绝对路径 train: images/train # 相对 path 的训练集图片目录 val: images/val # 相对 path 的验证集图片目录 nc: 3 # 类别数量 names: # 类别名称,顺序必须和 class_id 一致 0: coal 1: gangue 2: kaolinite

注意names的键值对写法,YOLOv8 支持字典格式也支持列表格式。如果你用列表['coal', 'gangue', 'kaolinite'],索引默认从 0 开始,效果一样。但字典格式更直观,不容易搞错顺序。改完 yaml 后,建议用 Python 快速加载验证一下:

import yaml with open("data.yaml", "r") as f: data = yaml.safe_load(f) print("类别数:", data["nc"]) print("类别名:", data["names"]) # 确认 nc 和 names 长度一致,且顺序与标注文件中的 class_id 对应

这一步花不了一分钟,但能避免训练跑了一半才发现类别数写错的尴尬。

3. 用 YOLOv8 跑通训练:从环境配置到第一轮收敛

3.1 环境搭建的版本选择与依赖安装

YOLOv8 对环境的要求不算苛刻,但版本不匹配导致的报错足够让人头疼。我一般推荐 Python 3.8 到 3.10,PyTorch 选 1.13 到 2.0 之间的稳定版。如果你用的是 CPU 版本,训练速度会慢很多,102 张图跑 100 轮大概需要几十分钟到一小时,具体看机器性能。有 GPU 的话,GTX 1660 Ti 这个级别就能跑,显存 6GB 足够应付 640 尺寸的输入。

# 创建虚拟环境 python -m venv yolov8_env source yolov8_env/bin/activate # Windows 用 yolov8_env\Scripts\activate # 安装 PyTorch,CPU 版本示例 pip install torch torchvision --index-url https://download.pytorch.org/whl/cpu # 安装 ultralytics pip install ultralytics # 验证安装 yolo checks

yolo checks会输出当前环境的关键信息,包括 PyTorch 版本、CUDA 是否可用、ultralytics 版本号。如果 CUDA 显示不可用但你有 GPU,检查驱动和 PyTorch 版本是否匹配。CPU 版本训练时记得把workers调小,不然数据加载可能成为瓶颈。

3.2 训练命令与关键参数含义

YOLOv8 的训练命令很简洁,但参数背后的含义值得逐一看清楚。下面这条命令是我在 102 张图数据集上常用的配置:

yolo detect train \ data=data.yaml \ model=yolov8n.pt \ epochs=100 \ imgsz=640 \ batch=8 \ lr0=0.01 \ patience=20 \ workers=4 \ project=runs/train \ name=coal_gangue_exp1

逐项拆解:model=yolov8n.pt用的是 nano 版本,参数量小,适合小数据集快速验证;epochs=100是上限,配合patience=20做早停,验证集 loss 连续 20 轮不降就停;batch=8在 6GB 显存下比较稳妥,显存不够就降到 4;lr0=0.01是初始学习率,小数据集不建议设太大,否则 loss 震荡;imgsz=640是输入尺寸,现场图片如果分辨率很高,可以适当增大到 800 或 1024,但显存占用会上升。workers=4是数据加载线程数,Windows 下有时需要设为 0 避免多进程报错。

训练开始后,终端会输出每一轮的 box_loss、cls_loss、dfl_loss 和 mAP 指标。前几轮 loss 下降快是正常的,如果 10 轮后 cls_loss 还在 2.0 以上不降,大概率是标注有问题或者学习率太大。

3.3 训练过程监控与损失曲线解读

YOLOv8 默认会在runs/train/下生成results.csv和损失曲线图。我习惯在训练启动后另开一个终端,用脚本实时看 loss 变化:

import pandas as pd import matplotlib.pyplot as plt df = pd.read_csv("runs/train/coal_gangue_exp1/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"], label="box_loss") axes[0].plot(df["epoch"], df["train/cls_loss"], label="cls_loss") axes[0].set_xlabel("epoch") axes[0].set_ylabel("loss") axes[0].legend() axes[1].plot(df["epoch"], df["metrics/mAP50(B)"], label="mAP50") axes[1].set_xlabel("epoch") axes[1].set_ylabel("mAP50") axes[1].legend() plt.tight_layout() plt.savefig("training_curve.png")

这段代码读取results.csv,画出损失和 mAP 曲线。重点看两个信号:一是cls_loss是否稳定下降,如果震荡剧烈,考虑降低学习率;二是mAP50是否在 50 轮后趋于平稳,如果还在上升,说明可以增加 epoch。102 张图的数据集,mAP50 能到 0.7 以上就算不错了,别指望和公开大数据集比。

3.4 验证集评估与混淆矩阵分析

训练结束后,用验证集跑一次评估:

yolo detect val \ model=runs/train/coal_gangue_exp1/weights/best.pt \ data=data.yaml \ imgsz=640 \ conf=0.25 \ iou=0.5

conf=0.25是置信度阈值,低于这个值的检测框会被过滤;iou=0.5是 NMS 的 IoU 阈值。评估结果会输出每个类别的 precision、recall 和 mAP。如果某个类别的 recall 明显偏低,说明漏检多,可能是标注框太小或者样本太少。混淆矩阵图在runs/val/下,能直观看到类别之间的误判情况。煤炭和煤矸石在视觉上确实有相似之处,如果混淆严重,可以考虑增加这两个类别的区分性特征,或者在数据增强时加入更多对比度变化。

4. 小样本数据集的避坑与排查:102 张图踩过的五个坑

4.1 标注框越界导致训练报错

现象:训练启动后几轮就报AssertionError,提示坐标超出 0 到 1 范围。原因:标注文件里某些框的 x_center 或 width 计算后超出了图像边界,常见于标注时拖拽超出图片边缘。解决:写脚本扫描所有标注文件,把越界的坐标裁剪回 0 到 1 之间,或者直接剔除这些异常标注。

import os def clamp(value, min_val=0.0, max_val=1.0): return max(min_val, min(value, max_val)) label_dir = "dataset/labels/train" for txt_file in os.listdir(label_dir): if not txt_file.endswith(".txt"): continue path = os.path.join(label_dir, txt_file) with open(path, "r") as f: lines = f.readlines() new_lines = [] for line in lines: parts = line.strip().split() if len(parts) != 5: continue cls_id = parts[0] coords = [clamp(float(x)) for x in parts[1:]] new_lines.append(f"{cls_id} {' '.join(f'{c:.6f}' for c in coords)}\n") with open(path, "w") as f: f.writelines(new_lines)

这段脚本遍历标注文件,把越界坐标裁剪到合法范围。注意clamp函数对 x_center 和 width 都做了限制,但严格来说 width 和 height 不应该超过 1,x_center 加减 width/2 也不应越界。更严谨的做法是重新计算框的边界,但小数据集上直接裁剪通常够用。

4.2 图片与标注文件名不匹配

现象:训练时提示找不到标注文件,或者某些图片被跳过。原因:图片文件名和标注文件名不完全一致,比如图片是.jpg但标注是.JPG.txt,或者哈希值部分有细微差异。解决:写脚本对比 images 和 labels 目录下的文件名,找出不匹配的项。

import os img_dir = "dataset/images/train" lbl_dir = "dataset/labels/train" img_names = {os.path.splitext(f)[0] for f in os.listdir(img_dir) if f.endswith(".jpg")} lbl_names = {os.path.splitext(f)[0] for f in os.listdir(lbl_dir) if f.endswith(".txt")} missing_labels = img_names - lbl_names missing_images = lbl_names - img_names print("有图无标注:", missing_labels) print("有标注无图:", missing_images)

输出结果如果非空,就需要手动处理。有图无标注的图片要么补标注,要么从训练集移除;有标注无图的直接删掉标注文件。

4.3 类别不均衡导致小类别漏检严重

现象:高岭石类别的 recall 只有 0.3 左右,而煤炭和煤矸石都在 0.7 以上。原因:102 张图里高岭石样本数量太少,模型学到的特征不够充分。解决:两个方向——一是数据层面,对高岭石样本做过采样或复制增强;二是损失层面,在训练时给类别加权。YOLOv8 本身没有直接的类别权重参数,但可以通过调整数据集分布来间接实现。我一般会先把高岭石图片单独复制几份,配合 mosaic 增强,让模型多看到这个类别。

4.4 验证集 mAP 波动大

现象:训练过程中 mAP50 时高时低,没有稳定上升趋势。原因:验证集只有 10 到 20 张图,样本量太小,评估结果随机性大。解决:如果数据量允许,把验证集比例提高到 20% 到 30%;或者用 K 折交叉验证,虽然麻烦但评估更可靠。另一个办法是固定随机种子,减少数据加载顺序带来的波动。

4.5 CPU 训练速度过慢的优化

现象:用 CPU 训练时,每轮耗时超过 5 分钟,100 轮跑了大半天。原因:CPU 并行能力有限,数据加载和矩阵运算都慢。解决:减小imgsz到 416 或 320,降低batch到 4,开启cache=True把图片缓存到内存。如果机器支持,装 GPU 版本 PyTorch 是最直接的提速方案。另外,workers设为 CPU 核心数的一半左右比较合适,设太大反而因为进程切换开销变慢。

5. 从 102 张到可用模型:数据增强与推理验证的实操技巧

5.1 针对煤矿场景的增强参数调整

YOLOv8 默认的增强策略包括 mosaic、mixup、HSV 调整、翻转等。对于煤矿现场图片,我一般会调整几个关键参数。hsv_v控制亮度变化,现场光照不均,适当增大到 0.5 能提升模型对明暗变化的鲁棒性;hsv_s饱和度调整设 0.7 左右,因为煤和煤矸石的颜色差异是重要特征,不能让增强把颜色信息抹掉;degrees旋转角度设 10 以内,现场相机角度相对固定,太大角度的旋转反而引入噪声。

yolo detect train \ data=data.yaml \ model=yolov8n.pt \ epochs=150 \ imgsz=640 \ batch=8 \ hsv_h=0.015 \ hsv_s=0.7 \ hsv_v=0.5 \ degrees=10 \ translate=0.1 \ scale=0.3 \ mosaic=1.0 \ mixup=0.1 \ patience=30

mosaic=1.0表示始终启用 mosaic 增强,mixup=0.1以 10% 概率混合两张图。小数据集上 mosaic 很关键,它能让模型在一张图里看到多个尺度的目标。但注意,如果图片本身分辨率不高,mosaic 拼接后目标会变得更小,可能适得其反。

5.2 推理脚本编写与置信度阈值调优

训练完模型后,写一个推理脚本验证实际效果:

from ultralytics import YOLO import cv2 model = YOLO("runs/train/coal_gangue_exp1/weights/best.pt") results = model.predict( source="test_images/", conf=0.3, iou=0.45, imgsz=640, save=True, project="runs/detect", name="test_result" ) for r in results: boxes = r.boxes for box in boxes: cls_id = int(box.cls[0]) conf = float(box.conf[0]) print(f"类别:{model.names[cls_id]},置信度:{conf:.2f}")

conf=0.3是推理时的置信度阈值,比验证时的 0.25 稍高,能减少误检。iou=0.45控制 NMS 合并重叠框的力度。实际部署时,这个阈值需要根据业务需求调——宁可误检不可漏检的场景就调低 conf,反之调高。save=True会把标注后的图片保存到指定目录,方便肉眼检查。

5.3 模型导出与部署前的验证清单

如果要把模型部署到边缘设备,比如 RK3588 或 Orin,需要先导出为 ONNX 格式:

yolo export \ model=runs/train/coal_gangue_exp1/weights/best.pt \ format=onnx \ imgsz=640 \ simplify=True \ opset=12

simplify=True会调用 onnx-simplifier 优化计算图,opset=12是 ONNX 算子集版本,兼容性较好。导出后别急着上板子,先在 PC 上用 onnxruntime 跑一遍,确认输出和 PyTorch 版本一致。我一般会对比同一张图在两个框架下的检测框坐标,偏差超过 1 个像素就要查原因。部署前还要确认输入尺寸、归一化方式、类别顺序和训练时完全一致,任何一项对不上都会导致精度下降。

从那以后我每次拿到新数据集,都强制走一遍“看目录、查标注、对类别、跑单图”的流程,确认数据没问题再开训。希望帮到你。

本文还有配套的精品资源,点击获取

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询