基于YOLOv8的电动车头盔检测系统:从训练到RK3588部署与GUI实现
发布时间:2026/10/2 3:45:37来源:尧图网络
简介本资源是一套基于YOLOv8的电动车佩戴头盔检测系统面向计算机视觉学习者、安全监管研发人员及需要目标检测实战项目的开发者可自动识别图像或视频中驾驶员、骑行者是否佩戴头盔及时发现安全漏洞。压缩包共129个文件约17.12MB以105张jpg样本图片、6个xml标注、6张png图表、3个py源码及1个onnx模型为主另含qrc资源与txt说明覆盖数据、训练、推理与界面全流程。系统在Windows10、Anaconda3Python3.8、PyTorch1.9.0cu111及ultralytics8.2.70环境下运行检测类别包括Bicyclist、driver、helmet、no-helmet并附带评估指标曲线便于量化分析准确率与召回率。GUI部分采用PyQt5构建界面美观、操作直观。目前已有1012人学习下载适合希望快速复现YOLOv8检测项目、理解模型评估与桌面端部署的读者参考。1. 电动车头盔检测这套源码拿到手先别急着点运行电动车骑行不戴头盔这件事说到底是个人安全习惯问题但落到工程上就是一个标准的单类目标检测任务从监控画面里把「戴头盔的骑手」和「没戴头盔的骑手」框出来。基于 YOLOv8 的电动车佩戴头盔检测系统核心就是拿 YOLOv8 训练一个能区分这两类的模型再配一套 Python 推理代码、一份 ONNX 模型、一组评估指标曲线最后套一个能直接点按钮的 GUI 界面。这套东西适合谁做毕业设计的学生、想快速验证检测方案的产品团队、以及需要把模型往 RK3588 或 Hi3516CV610 这类边缘板子上搬的嵌入式工程师。它解决的不是「从零研究检测算法」的问题而是「我已经知道要用 YOLOv8怎么把数据、训练、导出、界面这条链路一次性跑通」的问题。拿到压缩包之后先别双击那个 GUI 的 exe 或者 py因为一旦环境不对报错信息会把你带偏后面排查成本翻倍。2. 从数据集到 YOLOv8 训练头盔检测的完整链路2.1 头盔检测数据集长什么样Labelme 标注怎么转 YOLO 格式电动车头盔检测的数据集常见做法是两类helmet 和 head或者 no_helmet。图片来源一般是路口监控截图、行车记录仪抽帧、或者公开的骑行数据集。标注工具用 Labelme 的居多因为它画多边形方便但 YOLOv8 训练要的是 YOLO 格式的 txt每行是class_id x_center y_center width height全部归一化到 0 到 1 之间。Labelme 导出的 json 里shapes 字段存的是多边形点集转 YOLO 的时候要取外接矩形。下面这个脚本是我常用的转换逻辑处理单张图对应的 jsonimport json import os from PIL import Image def labelme_to_yolo(json_path, output_dir, class_map): 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 cls_id class_map[label] 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) # 归一化并转中心点加宽高 x_center (x_min x_max) / 2.0 / img_w y_center (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{cls_id} {x_center:.6f} {y_center:.6f} {w:.6f} {h:.6f}) base os.path.splitext(os.path.basename(json_path))[0] with open(os.path.join(output_dir, base .txt), w) as f: f.write(\n.join(lines)) class_map {helmet: 0, head: 1}逻辑说明class_map 把标签名映射成 0 和 1顺序要和后面 data.yaml 里的 names 一致否则训练出来的模型会把类别搞反。归一化用图像原始宽高不是缩放后的尺寸这点如果搞错框会整体偏移。参数上x_center 和 y_center 保留六位小数足够YOLOv8 内部会再处理。转换完之后目录结构要整理成 YOLOv8 认的格式dataset/ images/ train/ val/ labels/ train/ val/然后写 data.yamlpath: ./dataset train: images/train val: images/val nc: 2 names: [helmet, head]注意names 的顺序必须和 class_map 完全一致很多「训练 loss 正常但预测框类别全反」的问题都出在这里。2.2 YOLOv8 环境搭建Ubuntu 20.04 CPU 版本和 GPU 版本怎么选热词里有人搜「ubuntu20.04 搭建 yolov8 环境 cpu 版本」也有人搜「gtx1660ti 跑 yolov8」。我的建议是如果只是跑通推理和 GUICPU 版本足够如果要训练自己的数据集至少上一张 6G 显存的卡1660Ti 跑 yolov8n 在 640 分辨率下 batch 设 8 是能跑的再大就爆显存。CPU 版本安装Ubuntu 20.04 下我一般这么走conda create -n helmet python3.9 -y conda activate helmet pip install ultralytics opencv-python pyqt5 onnxruntimeGPU 版本多一步先确认 CUDA 版本然后装对应 torchpip install torch torchvision --index-url https://download.pytorch.org/whl/cu118 pip install ultralytics参数说明python 3.9 是兼容性最稳的版本3.11 以上有些 pyqt5 轮子会出问题。onnxruntime 装 CPU 版就够跑 ONNX 推理如果要 GPU 加速 ONNX换 onnxruntime-gpu但要注意 CUDA 版本匹配。装完之后用yolo checks验证能看到环境信息就说明通了。2.3 训练参数怎么设yolov8n 在头盔数据集上的最小配置头盔检测这种单场景两类任务yolov8n 就够没必要上 m 或 l。训练命令yolo detect train \ datadataset/data.yaml \ modelyolov8n.pt \ epochs100 \ imgsz640 \ batch16 \ lr00.01 \ patience20 \ projectruns/helmet \ nameexp1逻辑说明epochs 设 100 是起步值头盔数据集一般 3000 到 8000 张100 轮足够收敛。imgsz 640 是 YOLOv8 默认如果监控画面里目标很小可以提到 960但显存和速度要重新权衡。batch 16 在 8G 显存上跑 yolov8n 没问题显存小就降到 8。lr0 0.01 是 SGD 的初始学习率YOLOv8 默认会用 AdamW 自动调但显式写出来方便复现。patience 20 表示 20 轮没提升就早停省时间。训练完之后runs/helmet/exp1 下面会有 weights/best.pt 和 last.pt还有 results.csv 和一堆曲线图。评估指标曲线就是从这里来的后面单独讲。3. 评估指标曲线怎么看mAP、PR 曲线和损失函数的实际含义3.1 mAP50 和 mAP50-95 差在哪头盔检测该盯哪个YOLOv8 训练完会在 runs 目录下生成 results.png里面有 box_loss、cls_loss、mAP50、mAP50-95 这几条曲线。很多人只看 mAP50觉得到 0.9 就万事大吉但实际部署的时候发现漏检还是多。原因是 mAP50 只要求预测框和真实框 IoU 大于 0.5 就算对这个门槛在头盔检测里偏松因为头盔和头部的框本来就重叠大。mAP50-95 是把 IoU 从 0.5 到 0.95 每隔 0.05 算一次再平均更严格。头盔检测我一般盯 mAP50-95能到 0.6 以上就算可用0.7 以上算好。如果 mAP50 高但 mAP50-95 低说明框的位置不够准这时候要检查标注质量尤其是那些头盔只露一半的图。PR 曲线Precision-Recall在 results.png 里也有它反映的是不同置信度阈值下精确率和召回率的权衡。头盔检测场景下如果业务上更怕漏检没戴头盔的没抓出来就把置信度阈值调低牺牲一点精确率换召回率。3.2 用 Python 自己画损失函数曲线方便写报告训练日志在 results.csv 里字段包括 epoch、train/box_loss、train/cls_loss、metrics/mAP50 等。写毕业设计或者技术报告的时候用 matplotlib 重画一遍比直接截图好看import pandas as pd import matplotlib.pyplot as plt df pd.read_csv(runs/helmet/exp1/results.csv) df.columns df.columns.str.strip() fig, ax1 plt.subplots(figsize(10, 5)) ax1.plot(df[epoch], df[train/box_loss], labelbox_loss, colortab:red) ax1.plot(df[epoch], df[train/cls_loss], labelcls_loss, colortab:blue) ax1.set_xlabel(epoch) ax1.set_ylabel(loss) ax1.legend(locupper left) ax2 ax1.twinx() ax2.plot(df[epoch], df[metrics/mAP50-95(B)], labelmAP50-95, colortab:green) ax2.set_ylabel(mAP50-95) ax2.legend(locupper right) plt.title(Helmet Detection Training Curve) plt.tight_layout() plt.savefig(training_curve.png, dpi150)逻辑说明双 y 轴左边画 loss右边画 mAP这样一张图能同时看收敛和精度。参数上 dpi 150 够报告用再高文件太大。注意 results.csv 的列名可能带空格strip 一下避免 KeyError。提示如果 loss 曲线震荡厉害先别急着调模型检查 batch 是不是太小或者学习率是不是偏高。4. PyTorch 转 ONNX 再到 RK3588模型导出与部署的实操路径4.1 PyTorch 转 ONNX 的最小命令和三个必调参数训练完的 best.pt 要部署到非 Python 环境第一步就是转 ONNX。YOLOv8 自带导出命令yolo export modelruns/helmet/exp1/weights/best.pt formatonnx imgsz640 opset12 simplifyTrue参数说明imgsz 要和训练时一致否则检测框会偏。opset 12 是兼容性最好的版本RK3588 的 rknn-toolkit2 对 opset 12 支持最稳opset 17 有时候会报不支持的算子。simplifyTrue 会调用 onnx-simplifier 去掉冗余节点减小模型体积也方便后面转 rknn。导出完之后用 onnxruntime 验证一下能不能跑import onnxruntime as ort import numpy as np sess ort.InferenceSession(best.onnx) input_name sess.get_inputs()[0].name # 构造一个假输入NCHWfloat32 dummy np.random.randn(1, 3, 640, 640).astype(np.float32) outputs sess.run(None, {input_name: dummy}) print([o.shape for o in outputs])逻辑说明输出一般是 [1, 6, 8400]6 是 4 个框坐标加 2 个类别分数8400 是候选框数量。如果输出形状不对检查导出时的 imgsz 和类别数。4.2 ONNX 转 RKNN 部署到 RK3588 的关键步骤RK3588 部署 YOLOv8常见路径是 ONNX 转 RKNN。需要 rknn-toolkit2在 x86 机器上转换然后把 rknn 模型拷到板子上跑。转换脚本核心部分from rknn.api import RKNN rknn RKNN() rknn.config(mean_values[[0, 0, 0]], std_values[[255, 255, 255]], target_platformrk3588) rknn.load_onnx(modelbest.onnx) rknn.build(do_quantizationTrue, datasetquant_dataset.txt) rknn.export_rknn(best.rknn)参数说明mean 和 std 要和训练时的预处理一致YOLOv8 默认是 0 到 1 归一化所以 std 设 255。do_quantizationTrue 会做 int8 量化需要准备一个 quant_dataset.txt里面是几十张校准图片的路径。量化之后模型体积能降到四分之一左右速度提升明显但精度可能掉一两个点头盔检测这种两类任务一般能接受。注意量化校准集要覆盖白天、夜间、逆光这些场景否则量化后的模型在特定光照下会翻车。4.3 ONNX 量化 int8 之后精度掉了怎么办int8 量化掉精度是常见问题尤其是小目标。如果量化后 mAP 掉超过 5 个点先检查校准集是不是太少或者太单一。我一般会准备 200 张左右的校准图按场景分层抽样。如果还是掉可以只量化卷积层保留检测头为 fp16rknn-toolkit2 支持混合量化但配置起来麻烦一些。另一个办法是导出 ONNX 的时候不做 simplify保留更多原始结构量化时容错空间大一点。这个属于玄学范畴但实测有时候有效。5. GUI 界面怎么做PyQt5 套 YOLOv8 推理的避坑记录5.1 用 PyQt5 搭一个能选图片、能实时检测的界面GUI 部分用 PyQt5 是最常见的做法因为和 Python 结合紧打包也方便。核心逻辑是一个按钮选图片一个 QLabel 显示原图一个 QLabel 显示检测结果再加一个文本框输出检测到的类别和数量。推理线程要和 UI 线程分开否则检测的时候界面会卡死。用 QThread 包一层from PyQt5.QtCore import QThread, pyqtSignal from ultralytics import YOLO class DetectThread(QThread): finished pyqtSignal(object) def __init__(self, model_path, img): super().__init__() self.model YOLO(model_path) self.img img def run(self): results self.model(self.img, conf0.4) self.finished.emit(results)逻辑说明conf 0.4 是置信度阈值头盔检测场景下可以调到 0.3 提高召回。finished 信号把结果传回主线程更新界面。注意 YOLO 模型加载放在线程里如果放主线程第一次加载会卡几秒。5.2 界面卡顿和模型重复加载的排查现象点一次检测卡一次第二次更慢。原因每次点按钮都重新 YOLO(model_path)模型反复加载。解决把模型加载放到init里或者用单例模式全局只加载一次。现象检测大图的时候界面无响应。原因推理在主线程跑。解决上面那个 QThread 就是干这个的所有推理都丢线程里。现象打包成 exe 之后找不到模型文件。原因PyInstaller 打包后路径变了。解决用 sys._MEIPASS 处理资源路径或者把模型文件放到 exe 同级目录用绝对路径读。6. 从跑通到好用置信度阈值和 NMS 的调参习惯置信度阈值和 NMS 的 IoU 阈值是头盔检测从「能跑」到「好用」之间最关键的两个参数。默认 conf 0.25、iou 0.45 在通用场景下没问题但头盔检测有它的特殊性骑手密集的时候框和框重叠大NMS 的 iou 设高了会保留一堆重复框设低了会把相邻的骑手框误删。我的习惯是分两步调。第一步固定 iou 0.5把 conf 从 0.5 往下扫到 0.2看召回率和精确率的拐点。头盔检测如果业务上更怕漏检拐点可以往召回率那边偏。第二步固定 conf 在拐点值把 iou 从 0.4 扫到 0.6看密集场景下的框数量。一般 iou 0.5 到 0.55 之间比较稳。验证方法很简单准备一段路口视频用不同参数跑一遍把结果导出来人工数一下漏检和误检。别只看 mAPmAP 是数据集上的平均值实际场景的分布可能和数据集不一样。results model(frame, conf0.35, iou0.5, classes[0, 1])这行代码里的 classes 参数可以只保留头盔和头部两类如果模型还输出了其他类别过滤掉能减少后处理时间。最后一个习惯每次调完参数把 conf、iou、对应的漏检数和误检数记在一个表格里下次换数据集或者换场景的时候直接从历史值附近开始扫不用从零试。这个习惯帮我省了很多重复劳动也避免了一拍脑袋就改参数的翻车。希望帮到你。本文还有配套的精品资源点击获取
网站建设高端定制企业官网