ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

YOLOv8煤矿传送带异物检测:矸石与锚杆识别实战

YOLOv8煤矿传送带异物检测:矸石与锚杆识别实战 简介本资源面向煤矿智能化巡检与工业视觉检测方向的开发者、研究生及工程技术人员提供一套基于YOLOv8的煤矿传送带矸石与锚杆异物检测完整方案可直接用于推理部署也可基于数据集重新训练。包内包含3000多张标注图像标签为txt格式已按train、val、test划分完毕并附data.yaml配置文件yolov5、yolov7、yolov8、yolov9等主流算法均可直接接入训练。资源共2000个文件以1991个xml标注文件为主另含md说明、pdf环境配置教程与py脚本压缩包约323.4MB目录结构清晰便于快速上手。配套PyQt可视化界面可直观展示检测结果适合课程设计、科研实验与工程验证。已有233人学习下载能为煤矿异物检测任务提供从数据到模型再到交互界面的完整参考。1. 煤矿传送带异物检测YOLOv8 在矸石与锚杆场景里到底能解决什么煤矿主运输巷道的传送带一旦混入矸石或锚杆轻则划伤皮带、卡死托辊重则撕裂输送带造成停产甚至锚杆端头扎穿皮带引发火灾隐患。传统做法靠人工盯监控或金属探测器前者疲劳漏检后者对非金属矸石无能为力。YOLOv8 算法做煤矿传送带矸石与锚杆异物检测本质是把目标检测模型部署到皮带上方摄像头实时框出矸石和锚杆两类目标并联动停机或报警。这套方案适合煤矿智能化改造团队、做安全监测的集成商以及想用真实工业数据集练手 YOLOv8 的算法工程师。3000 多张数据集加 PyQt 可视化界面意味着从训练到演示的链路是完整的不是只跑个 mAP 就结束。2. 数据集怎么处理才能喂给 YOLOv8从 Labelme 标注到训练格式2.1 矸石与锚杆两类目标的标注规范拿到 3000 多张煤矿传送带图像后第一件事不是直接训练而是统一标注口径。矸石和锚杆在图像里形态差异大矸石多为不规则块状颜色偏灰黑与煤块容易混淆锚杆是细长杆状有时只露出一截端头有时横跨整个画面。标注时我一般要求矸石框住可见轮廓外沿锚杆框住整根可见杆体被遮挡超过 50% 的目标标为 difficult 或直接不标避免模型学到半截特征。常见做法是用 Labelme 做多边形或矩形标注导出 JSON 后再转 YOLO 格式。但 Labelme 默认输出的是多边形点集YOLOv8 需要的是归一化中心点加宽高的 txt。转换脚本必须处理两个边界一是图像尺寸不一致时按各自宽高归一化二是类别名到类别 ID 的映射要固定矸石和锚杆的 ID 顺序一旦定下就不能在后续训练中改动。import json import os from pathlib import Path # 类别映射顺序固定后续训练和推理必须一致 CLASS_MAP {gangue: 0, anchor: 1} def labelme_to_yolo(json_path, output_dir): with open(json_path, r, encodingutf-8) as f: data json.load(f) img_w data[imageWidth] img_h data[imageHeight] lines [] for shape in data[shapes]: label shape[label] if label not in CLASS_MAP: continue points shape[points] xs [p[0] for p in points] ys [p[1] for p in points] x_min, x_max min(xs), max(xs) y_min, y_max min(ys), max(ys) # 归一化中心点与宽高 cx (x_min x_max) / 2.0 / img_w cy (y_min y_max) / 2.0 / img_h w (x_max - x_min) / img_w h (y_max - y_min) / img_h lines.append(f{CLASS_MAP[label]} {cx:.6f} {cy:.6f} {w:.6f} {h:.6f}) out_name Path(json_path).stem .txt with open(os.path.join(output_dir, out_name), w) as f: f.write(\n.join(lines)) # 批量转换 for jf in Path(labels_json).glob(*.json): labelme_to_yolo(str(jf), labels_yolo)这段脚本的核心逻辑是取多边形外接矩形再归一化。参数上CLASS_MAP的 ID 必须与后续data.yaml里的names列表索引一致否则训练时类别会错位。cx、cy、w、h都除以图像宽高保证不同分辨率图像统一到 0-1 区间。转换后要抽查几张可视化确认框位置没偏移。2.2 数据集划分与 data.yaml 配置3000 多张图按 8:1:1 划分训练、验证、测试集比较稳妥。煤矿场景有个坑同一段皮带连续帧高度相似如果随机划分训练集和验证集会出现近乎重复的图导致验证 mAP 虚高。我一般按时间或按皮带段做分组划分同一组只进一个集合。# 目录结构 dataset/ images/ train/ val/ test/ labels/ train/ val/ test/# data.yaml path: /home/user/dataset train: images/train val: images/val test: images/test nc: 2 names: [gangue, anchor]path写绝对路径最稳相对路径在 ultralytics 不同版本里解析基准可能不一致。nc为 2names顺序与转换脚本的CLASS_MAP严格对应。如果后续要加第三类异物改nc和names后必须重新生成所有标签不能只改 yaml。2.3 数据增强参数怎么设才不破坏矸石与锚杆特征YOLOv8 默认增强里mosaic和mixup对煤矿异物检测要谨慎。mosaic 把四张图拼一起锚杆这种细长目标被裁切后可能只剩一小段模型学到的锚杆特征不完整。我的经验是mosaic保留但把close_mosaic设到 10 左右让最后 10 个 epoch 关掉 mosaic 用原图微调mixup直接设 0因为煤矿背景单一mixup 产生的半透明叠加反而引入噪声。from ultralytics import YOLO model YOLO(yolov8s.pt) model.train( datadata.yaml, epochs150, imgsz640, batch16, mosaic1.0, close_mosaic10, mixup0.0, hsv_h0.015, hsv_s0.7, hsv_v0.4, degrees5.0, translate0.1, scale0.5, fliplr0.5, flipud0.0, )hsv_h调小是因为矸石和煤块颜色接近色相扰动太大会让矸石变成不存在的颜色。flipud设 0传送带图像上下翻转不符合物理场景。degrees只给 5 度锚杆方向在图像里基本固定大角度旋转会引入不真实样本。scale给 0.5 是让模型适应不同距离的异物大小。3. YOLOv8 训练煤矿异物检测模型的参数与显存调优3.1 模型选型n/s/m 在煤矿场景的取舍YOLOv8n 最快但小目标召回低锚杆端头在 640 分辨率下可能只有十几个像素n 版容易漏。YOLOv8m 精度好但显存吃紧GTX 1660 Ti 6G 跑 batch 16 会 OOM。我的建议如果部署端是 RK3588 或边缘盒子选 YOLOv8s 做蒸馏或直接量化如果服务器端 GPU 推理YOLOv8m 加 imgsz 960 对锚杆小目标提升明显。3000 张数据量下s 版通常能到 mAP50 0.85 以上m 版能到 0.9 左右但推理速度差一倍。# 查看显存占用与训练日志 nvidia-smi -l 2 # 训练时观察 loss 曲线 tensorboard --logdir runs/detect/train3.2 学习率与优化器煤矿数据集的收敛技巧YOLOv8 默认用 SGDlr00.01。煤矿数据集背景单一、目标类别少我一般把lr0降到 0.005lrf设 0.01让后期学习率足够小避免在最优解附近震荡。warmup_epochs给 3因为预训练权重已经很好不需要太长预热。model.train( datadata.yaml, epochs150, lr00.005, lrf0.01, warmup_epochs3, optimizerSGD, momentum0.937, weight_decay0.0005, cos_lrTrue, )cos_lrTrue用余弦退火比阶梯下降更平滑。weight_decay保持默认煤矿数据量不大正则太强会欠拟合。如果发现训练 loss 下降但验证 mAP 不涨先查验证集划分是否泄漏再考虑加 dropout 或减小模型。3.3 训练过程监控与早停策略YOLOv8 自带patience参数默认 50 个 epoch 没提升就停。煤矿数据 150 epoch 通常够但如果你加了新类别或换了相机角度建议patience30早点停省时间。监控时重点看metrics/mAP50-95和val/box_loss如果 box_loss 持续降但 mAP 平说明模型在过拟合背景。model.train( datadata.yaml, epochs150, patience30, save_period10, plotsTrue, )save_period10每 10 epoch 存一次权重方便回滚。plotsTrue自动画混淆矩阵和 PR 曲线省得自己写脚本。训练完在runs/detect/train/weights/下拿best.pt做后续推理。4. PyQt 可视化界面把 YOLOv8 推理结果搬到操作台4.1 PyQt5 界面布局与视频流接入PyQt 界面要解决三件事显示实时视频、叠加检测框、给出报警状态。布局上我用 QLabel 显示视频帧QPushButton 控制启停QTableWidget 记录报警历史。视频流用 OpenCV 的VideoCapture读 RTSP 或本地文件每帧送 YOLOv8 推理后把boxes.xyxy画到帧上再转 QImage。import cv2 import sys from PyQt5.QtWidgets import QApplication, QMainWindow, QLabel, QPushButton, QVBoxLayout, QWidget from PyQt5.QtGui import QImage, QPixmap from PyQt5.QtCore import QTimer, Qt from ultralytics import YOLO class DetectWindow(QMainWindow): def __init__(self): super().__init__() self.model YOLO(best.pt) self.cap cv2.VideoCapture(rtsp://camera_ip:554/stream) self.label QLabel(等待视频流...) self.label.setAlignment(Qt.AlignCenter) self.btn QPushButton(开始检测) self.btn.clicked.connect(self.toggle) layout QVBoxLayout() layout.addWidget(self.label) layout.addWidget(self.btn) container QWidget() container.setLayout(layout) self.setCentralWidget(container) self.timer QTimer() self.timer.timeout.connect(self.update_frame) self.running False def toggle(self): if self.running: self.timer.stop() self.btn.setText(开始检测) else: self.timer.start(30) # 约 33 FPS self.btn.setText(停止检测) self.running not self.running def update_frame(self): ret, frame self.cap.read() if not ret: return results self.model(frame, conf0.5, iou0.45, verboseFalse) annotated results[0].plot() rgb cv2.cvtColor(annotated, cv2.COLOR_BGR2RGB) h, w, ch rgb.shape qimg QImage(rgb.data, w, h, ch * w, QImage.Format_RGB888) self.label.setPixmap(QPixmap.fromImage(qimg).scaled( self.label.width(), self.label.height(), Qt.KeepAspectRatio)) if __name__ __main__: app QApplication(sys.argv) win DetectWindow() win.show() sys.exit(app.exec_())conf0.5是置信度阈值煤矿场景宁可误报不可漏报可以降到 0.4。iou0.45控制 NMS 重叠阈值锚杆细长框重叠少保持默认即可。timer.start(30)约 33 FPS如果推理跟不上就调大间隔避免界面卡死。results[0].plot()直接返回带框图像省去手动画框。4.2 报警联动与结果导出检测到矸石或锚杆后界面要给出明显提示并记录时间戳。我一般用 QTableWidget 追加一行同时把帧存到本地alarm/目录方便事后追溯。如果要对接触发器停机通过串口或 GPIO 发信号这部分在 PyQt 里用QSerialPort或单独线程处理别阻塞 UI 线程。from datetime import datetime def log_alarm(self, frame, class_names): timestamp datetime.now().strftime(%Y%m%d_%H%M%S) filename falarm/{timestamp}.jpg cv2.imwrite(filename, frame) row self.table.rowCount() self.table.insertRow(row) self.table.setItem(row, 0, QTableWidgetItem(timestamp)) self.table.setItem(row, 1, QTableWidgetItem(,.join(class_names)))class_names从results[0].names取只记录检出的类别。存图用原帧不用标注帧保留原始证据。报警表加一列置信度更利于后续筛选。4.3 界面卡顿与推理线程分离PyQt 主线程跑推理帧率高时界面会卡。常见做法是把推理放到 QThread 里通过信号槽把结果传回主线程更新 UI。另一个坑是 OpenCV 的cap.read()在 RTSP 断流时会阻塞加超时或重连逻辑。from PyQt5.QtCore import QThread, pyqtSignal class InferThread(QThread): frame_ready pyqtSignal(object) def __init__(self, model, cap): super().__init__() self.model model self.cap cap self.running True def run(self): while self.running: ret, frame self.cap.read() if not ret: continue results self.model(frame, conf0.5, verboseFalse) self.frame_ready.emit(results[0].plot()) def stop(self): self.running Falseframe_ready发 numpy 数组主线程收到后转 QImage 显示。stop()在窗口关闭时调用避免线程泄漏。RTSP 断流时ret为 False这里用continue会空转实际项目里加time.sleep(0.1)或重连计数。5. 避坑与排查煤矿异物检测落地时最容易翻车的 5 个点5.1 验证集 mAP 很高但现场漏检严重现象训练日志里 mAP50 到 0.92现场部署后矸石漏检率却超过 30%。原因验证集和训练集来自同一段皮带、同一光照条件模型没学到泛化特征。解决按皮带段或时间段重新划分数据集验证集必须包含不同光照、不同煤流厚度的图像现场采集新数据做测试集别用训练时的验证集当最终指标。5.2 锚杆细长目标框回归不准现象锚杆检测框要么只框住一半要么把旁边煤块也框进去。原因锚杆长宽比大YOLOv8 默认 anchor 对细长目标不友好且标注时锚杆端头被遮挡部分没标。解决标注时锚杆可见部分全标不要截断训练时把imgsz提到 960小目标特征更清晰如果还不行改 CIOU 为 EIOU 或加角度回归但改动大先试前两步。5.3 PyQt 界面显示颜色偏蓝或偏红现象OpenCV 读的 BGR 帧直接转 QImage 后颜色不对。原因QImage 的Format_RGB888需要 RGB 顺序OpenCV 默认 BGR。解决cv2.cvtColor(frame, cv2.COLOR_BGR2RGB)后再构造 QImage注意bytesPerLine参数用ch * w否则图像会错位。5.4 训练时显存溢出但 batch 已经很小现象GTX 1660 Ti 6G 跑 YOLOv8s batch 8 还 OOM。原因imgsz设了 1280或者workers太多导致内存碎片。解决imgsz降到 640workers设 4 或 2batch用-1让 ultralytics 自动找最大 batch如果还不行用ampTrue混合精度显存能省 30% 左右。5.5 模型部署到 RK3588 后推理速度不达标现象PC 上 30 FPSRK3588 上只有 5 FPS。原因PyTorch 模型没转 RKNNCPU 推理慢。解决用 RKNN-Toolkit2 把best.pt先转 ONNX 再转 RKNN量化用i8或fp16输入分辨率降到 640NPU 核心数设 3。转换时注意 YOLOv8 的输出层名字不同版本 ultralytics 导出的 ONNX 节点名有差异转 RKNN 前用 Netron 看一眼。6. 从 3000 张到产线让矸石与锚杆检测模型持续可用的几个习惯模型训完不是终点。煤矿现场光照变化、皮带磨损、煤质变化都会让模型慢慢失准。我自己的习惯是每两周从现场抽 200 张图跑一遍best.pt把漏检和误检的图挑出来用 Labelme 补标后加入训练集用model.train(resumeTrue)增量微调 20 个 epoch。这样模型不会突然崩而是跟着现场数据缓慢进化。另一个习惯是给 PyQt 界面加一个「保存当前帧」按钮操作员发现异常时一键存图这些图比事后翻录像更有价值。报警记录表里加一列「是否误报」定期导出统计如果某类误报集中出现比如把某段皮带接头误判为锚杆就针对性地补负样本。验证模型是否真的可用别只看 mAP。我一般做三件事一是拿一段 10 分钟现场视频跑离线推理统计漏检次数二是把conf从 0.5 调到 0.3 看召回提升多少如果提升很大说明阈值卡太死三是让操作员盲测他们能一眼看出的异物模型必须也能检出否则就是特征没学好。这套方案从 3000 张数据集到 PyQt 界面链路是通的但真正落地时最花时间的不是调模型而是数据闭环和现场适配。我踩过最大的坑是拿训练集当验证集mAP 好看但现场翻车后来老老实实按皮带段划分数据指标降了 5 个点但现场漏检少了一半。希望帮到你。本文还有配套的精品资源点击获取
返回列表