尧图网站设计 尧图网站设计YAOTU DESIGN
ARTICLE DETAIL

资讯详情

深耕网站设计与一线实操的经验洞察。

YOLOv8+PyQt5实现安全帽佩戴检测:从训练到部署全流程

YOLOv8+PyQt5实现安全帽佩戴检测:从训练到部署全流程 施工安全一直是工地管理的重中之重而安全帽佩戴检测则是其中落地需求最广、技术方案最成熟的方向之一。很多同学在入门深度学习目标检测时都会拿安全帽检测作为练手项目但网上资料大多只写到“训练完出个 loss 曲线”就结束了离“能交给现场用的系统”还有明显距离。本文将以 YOLOv8 作为检测模型结合 PyQt5 开发桌面端识别系统完整串联数据集准备、模型训练、界面开发、推理部署全流程。无论是毕设选题、课设项目还是想往工业视觉方向转的开发同学这套方案都有直接参考价值。1. 项目背景与核心概念1.1 为什么需要安全帽佩戴检测建筑工地、工厂车间、电力检修等高危作业场景中头部伤害事故占比较高而规范佩戴安全帽是最基本也最有效的防护措施。实际情况中依靠安全员人工巡查存在两个明显问题一是工地范围大、作业面分散人工巡检存在盲区二是长时间盯监控屏容易疲劳漏看事后回放又失去了预警意义。基于深度学习的智能检测系统可以实时分析监控画面自动识别人员是否佩戴安全帽。当检测到未佩戴行为时系统可以截图留存、声音报警甚至联动闸机或广播系统。这类系统的核心流程是摄像头采集画面 - 目标检测模型推理 - 结果绘制与告警 - 数据记录。1.2 YOLOv8 是什么YOLOv8 是 Ultralytics 公司在 2023 年初推出的目标检测模型系列属于 YOLOYou Only Look Once家族。YOLO 的核心思想是把目标检测当作回归问题处理一次前向推理同时预测目标的类别和边界框因此速度极快非常适合实时视频流场景。YOLOv8 相比之前的 YOLOv5在网络结构上做了几个重要调整骨干网络使用 C2f 模块替代 C3增强了梯度流动和信息融合。头部结构采用 Anchor-Free 设计不再依赖预设锚框。分类分支和回归分支解耦训练收敛更稳定。支持目标检测、实例分割、姿态估计、图像分类等多种任务同一套代码框架。对我们做安全帽检测来说最关心的是 YOLOv8 在精度和速度上取得了一个很实用的平衡而且在 GTX 1660 Ti、RTX 3060 这类中端显卡上也能跑实时推理落地门槛较低。1.3 PyQt5 在项目中承担什么角色深度学习模型本身只是“检测引擎”给用户使用的是图形界面。PyQt5 是 Qt5 框架的 Python 绑定可以跨平台开发桌面应用。在本文项目中PyQt5 负责以下功能显示本地图片、视频文件的检测结果。显示摄像头实时画面。提供“选择图片 / 选择视频 / 打开摄像头 / 停止检测”等交互按钮。在检测到未佩戴安全帽时显示告警状态。展示检测日志和统计信息。整套系统的运行逻辑可以简化成下面的流程图输入图片/视频/摄像头帧 | v YOLOv8 模型推理 | v 解析检测结果类别 置信度 边界框 | v 绘制边界框和标签 | v PyQt5 界面显示 告警判断2. 环境准备与版本说明2.1 整体环境清单本文所演示的环境组合如下版本不必完全一致但思路相同。软件版本建议说明操作系统Windows 10/11 或 Ubuntu 20.04本文以 Windows 为例Python3.8 - 3.10YOLOv8 要求 Python 3.8 以上PyTorch2.0.0 及以上CUDA 版本需按显卡驱动选择CUDA11.8 或 12.1与 PyTorch 对应ultralytics8.xYOLOv8 官方库PyQt55.15.xQt 界面库OpenCV4.x图像和视频处理如果是 RTX 30 系及以后的显卡建议安装 CUDA 11.8 或 12.1 对应的 PyTorch 版本。如果电脑是纯 CPU 环境也可以运行但视频实时推理帧率会明显下降建议用 GPU 跑完整项目。2.2 安装步骤首先创建虚拟环境避免依赖冲突。打开终端执行conda create -n helmet python3.9 -y conda activate helmet安装 PyTorch。这里以 CUDA 11.8 版本为例其他版本可以到 PyTorch 官网选择对应命令pip install torch torchvision torchaudio --index-url https://download.pytorch.org/whl/cu118安装 yolov8 依赖库和 PyQt5、OpenCVpip install ultralytics pip install pyqt5 pip install opencv-python安装完成后可以快速确认核心库是否可用import torch import ultralytics print(PyTorch version:, torch.__version__) print(CUDA available:, torch.cuda.is_available()) print(ultralytics version:, ultralytics.__version__)输出中CUDA available: True说明 GPU 环境可用False则说明当前只能走 CPU 推理。3. 数据集准备与 YOLOv8 训练3.1 数据集结构YOLOv8 支持直接训练自定义数据集标注格式是 YOLO 格式的 txt 文件。一个完整的数据集目录结构如下helmet_dataset/ ├── images/ │ ├── train/ │ │ ├── img001.jpg │ │ └── ... │ └── val/ │ ├── img101.jpg │ └── ... ├── labels/ │ ├── train/ │ │ ├── img001.txt │ │ └── ... │ └── val/ │ ├── img101.txt │ └── ... └── data.yaml每张图片对应的 txt 文件中每一行代表一个目标格式为类别id 中心点x 中心点y 宽度 高度需要注意的是坐标值都是相对于图片宽高的归一化数值取值范围为 0 到 1。3.2 标注工具选择常用的标注工具是 LabelImg。标注完成后需要将 VOC 格式的 XML 文件转换为 YOLO 格式的 txt 文件也可以直接在 LabelImg 中选择 YOLO 格式保存。对于本文安全帽场景建议至少标注两个类别类别 0helmet佩戴安全帽类别 1no_helmet未佩戴安全帽如果现场需要区分“有戴安全帽的人”和“没戴安全帽的人”有些项目也会加一个 person 类别由模型先检测人再判断头部区域。但更常见的做法是直接标注“戴帽的人”和“不戴帽的人”这样在推理时直接输出两类目标业务逻辑更简单。3.3 编写数据集配置文件在数据集根目录下创建data.yamltrain: helmet_dataset/images/train val: helmet_dataset/images/val nc: 2 names: [helmet, no_helmet]其中train和val是图片文件夹所在路径nc是类别数量names是类别名称列表。注意类别编号必须和标注文件中的 id 一一对应。3.4 模型训练在终端执行下面的命令开始训练yolo detect train modelyolov8n.pt datahelmet_dataset/data.yaml epochs100 imgsz640 batch16 device0参数解释如下modelyolov8n.pt使用 YOLOv8 官方预训练权重作为初始权重。这里的 n 表示 nano 版本最轻量适合快速验证和 CPU 部署。data数据集配置文件路径。epochs训练轮数数据量小时 100 轮足够。imgsz训练图片分辨率一般 640。batch批大小根据显卡显存调整。device0使用第一块 GPUCPU 环境可改为devicecpu。如果显存有限可以把batch调小到 8 或 4。训练完成后模型权重保存在runs/detect/train/weights/best.pt这是验证集精度最高的权重文件后续推理就使用它。4. PyQt5 界面设计与核心代码4.1 界面整体布局整个应用主要包含一个主窗口功能区域分为三块顶部标题栏和功能按钮。中间实时画面显示区域使用 QLabel 显示图像。底部检测结果统计信息和日志区域。按钮包括打开图片、打开视频、打开摄像头、停止检测、退出系统。我们创建一个main_window.py文件来实现主窗口。4.2 主窗口初始化代码import sys import cv2 from PyQt5.QtWidgets import QMainWindow, QApplication, QLabel, QPushButton, QVBoxLayout, QHBoxLayout, QWidget, QTextEdit, QFileDialog from PyQt5.QtGui import QImage, QPixmap from PyQt5.QtCore import Qt, QTimer from ultralytics import YOLO class SafetyHelmetApp(QMainWindow): def __init__(self): super().__init__() self.setWindowTitle(工地安全帽佩戴检测系统 - YOLOv8 PyQt5) self.setGeometry(100, 100, 1000, 700) # 加载模型 self.model YOLO(runs/detect/train/weights/best.pt) # 视频源相关 self.cap None self.camera_timer QTimer() self.camera_timer.timeout.connect(self.update_frame) # 统计信息 self.total_count 0 self.no_helmet_count 0 # 初始化界面 self.init_ui() def init_ui(self): # 创建控件 self.image_label QLabel(请选择图片、视频或打开摄像头) self.image_label.setAlignment(Qt.AlignCenter) self.image_label.setMinimumSize(800, 500) self.btn_image QPushButton(打开图片) self.btn_video QPushButton(打开视频) self.btn_camera QPushButton(打开摄像头) self.btn_stop QPushButton(停止检测) self.btn_exit QPushButton(退出) self.log_text QTextEdit() self.log_text.setReadOnly(True) self.log_text.setMaximumHeight(120) # 布局 btn_layout QHBoxLayout() btn_layout.addWidget(self.btn_image) btn_layout.addWidget(self.btn_video) btn_layout.addWidget(self.btn_camera) btn_layout.addWidget(self.btn_stop) btn_layout.addWidget(self.btn_exit) main_layout QVBoxLayout() main_layout.addWidget(self.image_label) main_layout.addLayout(btn_layout) main_layout.addWidget(self.log_text) container QWidget() container.setLayout(main_layout) self.setCentralWidget(container) # 信号槽 self.btn_image.clicked.connect(self.open_image) self.btn_video.clicked.connect(self.open_video) self.btn_camera.clicked.connect(self.open_camera) self.btn_stop.clicked.connect(self.stop_detection) self.btn_exit.clicked.connect(self.close)4.3 图片检测功能图片检测是最简单的交互方式用户选择一张图片模型推理后把结果绘制在图片上再显示到界面上。def open_image(self): file_path, _ QFileDialog.getOpenFileName( self, 选择图片, , 图片文件 (*.jpg *.jpeg *.png *.bmp) ) if not file_path: return # 推理 results self.model.predict(sourcefile_path, conf0.5, saveFalse, verboseFalse) annotated_frame results[0].plot() # 统计 self.update_statistics(results[0]) # 显示 self.display_image(annotated_frame) self.append_log(f已处理图片{file_path})results[0].plot()是 ultralytics 提供的方法会把检测框、类别标签和置信度直接画在图像上返回 numpy 数组格式的图像数据非常方便。4.4 视频和摄像头检测功能视频文件的处理方式也是逐帧读取。为了不阻塞界面我们使用 QTimer 定时读取下一帧这里以摄像头为例def open_camera(self): self.stop_detection() self.cap cv2.VideoCapture(0) if not self.cap.isOpened(): self.append_log(错误无法打开摄像头) return self.camera_timer.start(30) self.append_log(摄像头已打开开始实时检测) def update_frame(self): ret, frame self.cap.read() if not ret: self.append_log(无法读取摄像头画面) self.stop_detection() return results self.model.predict(sourceframe, conf0.5, saveFalse, verboseFalse) annotated_frame results[0].plot() self.update_statistics(results[0]) self.display_image(annotated_frame) def stop_detection(self): self.camera_timer.stop() if self.cap is not None: self.cap.release() self.cap None self.append_log(检测已停止)视频文件检测与摄像头几乎一样区别只是cv2.VideoCapture(0)换成cv2.VideoCapture(file_path)。4.5 结果统计与图像显示统计逻辑需要遍历检测结果中的所有目标框def update_statistics(self, result): self.total_count 0 self.no_helmet_count 0 boxes result.boxes if boxes is None: return for cls, conf in zip(boxes.cls, boxes.conf): class_id int(cls) if result.names[class_id] no_helmet: self.no_helmet_count 1 self.append_log(f警告检测到未佩戴安全帽置信度 {float(conf):.2f}) self.total_count len(boxes)图像显示函数负责把 numpy 数组转换为 QImagedef display_image(self, frame): frame cv2.cvtColor(frame, cv2.COLOR_BGR2RGB) h, w, ch frame.shape bytes_per_line ch * w q_image QImage(frame.data, w, h, bytes_per_line, QImage.Format_RGB888) self.image_label.setPixmap(QPixmap.fromImage(q_image).scaled( self.image_label.width(), self.image_label.height(), Qt.KeepAspectRatio )) def append_log(self, message): self.log_text.append(message)4.6 主程序入口最后创建一个app.py入口文件import sys from PyQt5.QtWidgets import QApplication from main_window import SafetyHelmetApp if __name__ __main__: app QApplication(sys.argv) window SafetyHelmetApp() window.show() sys.exit(app.exec_())运行python app.py就会出现检测系统主界面。5. 推理优化浮点数格式与模型导出5.1 为什么需要关注浮点数精度很多同学在训练完模型后直接加载.pt权重做推理对精度和速度没有主动控制。实际上深度学习模型推理时可以用不同的浮点数格式来存储权重和计算中间结果选择不同格式直接影响显存占用、推理速度和检测精度。在工程化部署中常见的浮点数格式包括格式位数表示范围精度主要用途FP3232 位大高训练和原始权重FP1616 位较小较低GPU 推理加速BF1616 位与 FP32 相同精度较低大模型训练和推理TF3219 位与 FP32 相同介于 FP32 和 FP16 之间Ampere 架构 GPU 加速简单来说FP32 是标准单精度浮点精度最高但速度慢、显存占用大FP16 显存减半、速度更快但数值范围小训练时容易溢出BF16 解决了范围问题但精度更低TF32 是专门为深度学习设计的截断精度不牺牲太多精度的同时提升计算速度。5.2 YOLOv8 中如何切换推理精度在 YOLOv8 推理时可以通过model.predict()的half参数来控制是否使用 FP16 半精度推理# FP32 推理默认 results model.predict(sourceframe, conf0.5, halfFalse) # FP16 推理 results model.predict(sourceframe, conf0.5, halfTrue)在 NVIDIA GPU 上FP16 推理通常能带来明显的速度提升特别是在视频流实时检测场景中很有价值。不过要注意如果显卡不支持 FP16 快速计算比如部分入门级显卡实际提速效果可能不明显。5.3 模型导出为 ONNX 或 TensorRT如果想进一步加速推理还可以将 PyTorch 模型导出为 ONNX 或 TensorRT 格式。ONNX 格式通用性更强TensorRT 是 NVIDIA 专门针对自家 GPU 做的推理加速引擎。# 导出 ONNX yolo export modelruns/detect/train/weights/best.pt formatonnx opset12 # 导出 TensorRT需要 GPU 和 TensorRT 环境 yolo export modelruns/detect/train/weights/best.pt formatengine halfTrue导出 ONNX 后在 PyQt5 应用中就不一定非要加载 PyTorch 模型了可以使用 ONNX Runtime 来推理部署环境不需要再安装庞大的 PyTorch 依赖。对于毕设展示或项目演示来说直接加载.pt文件更省事如果目标是真实项目落地建议走 ONNX/TensorRT 路线。6. 常见问题与排查思路在开发这套系统时最容易踩坑的环节集中在环境安装、模型加载、摄像头处理和界面卡顿上。下面整理高频问题及解决思路。问题现象常见原因解决思路pip install pyqt5安装失败Python 版本过高与 PyQt5 版本不兼容使用 Python 3.8-3.10或升级 PyQt5 到 5.15.10运行时报module ultralytics has no attribute YOLOultralytics 未正确安装执行pip install -U ultralytics并确认版本加载权重时提示 CUDA error: out of memory显存不足换用更小的yolov8n模型或降低imgsz分辨率摄像头打开后画面卡住不动摄像头被其他程序占用或读取帧失败检查摄像头驱动重启应用确认摄像头编号检测速度特别慢使用 CPU 推理或视频分辨率过高使用 GPU 推理或制作检测前先缩放图像未佩戴安全帽的人检测不出来训练样本太少或背景复杂增加多样性样本提高训练轮数调整置信度阈值PyQt5 界面点击无响应推理耗时阻塞了主线程使用 QThread 把推理放到子线程避免阻塞 UIcv2.VideoCapture(0)返回 False笔记本摄像头权限被禁用检查系统相机权限设置其中“线程阻塞导致界面卡死”是最常见的 PyQt5 实战问题。本文示例为了便于讲解直接在定时器回调中做推理对于低帧率场景基本够用如果追求流畅体验建议把摄像头读取和模型推理放到 QThread 中主线程只负责更新画面。7. 工程化最佳实践与改进方向7.1 数据层面的建议安全帽检测的效果上限其实由数据决定。训练时建议注意以下几点样本要覆盖白天、傍晚、夜间、逆光、雨天等不同光照条件。画面中工人的姿态多样化正面、背面、侧面、弯腰、下蹲。安全帽颜色丰富一些黄色、红色、蓝色、白色都要有。适当做数据增强Mosaic 增强在 YOLOv8 中默认开启可以有效提升对小目标、遮挡目标的效果。如果现场误报多重点收集“远处小人”“反光区域”“与安全帽颜色接近的物体”等难例。7.2 模型训练层面的建议第一版先用yolov8n快速验证流程确认数据集没问题后再换yolov8s或yolov8m提升精度。默认 100 轮训练基本足够关注results.png中的验证集精度曲线即可不必盲目标高轮数。如果样本量很小可以加大预训练权重对模型参数的约束避免过拟合。推理时的置信度阈值conf可以后续按现场调整比如现场漏检多就把阈值调低到 0.3误检多就调高到 0.6。7.3 工程部署层面的建议真实工地环境下这套系统通常不是跑在一台连接摄像头的电脑上而是接入已有的监控网络。此时需要考虑视频流接入方式改为 RTSP 拉流替代本文演示的本地摄像头。检测结果需要写入数据库或者通过消息队列上报给平台。未佩戴安全帽的告警可以增加语音播报、微信通知、短信通知等联动方式。多路视频并发检测时建议用多进程或单独部署推理服务PyQt5 界面只做结果展示。生产环境中修改模型参数或推理逻辑先在测试环境验证再上线避免影响正在运行的监控业务。7.4 下文学习路线参考如果完成本文项目后想继续深入按顺序建议学习以下方向YOLOv8 网络结构深入拆解理解 C2f、SPPF、Detection Head 的实现细节。增量训练与模型微调解决现场数据持续积累后如何低成本提升模型能力的问题。TensorRT 量化部署将 FP32 模型压缩为 INT8进一步提高视频路数支持。PyQt5 多线程与信号槽机制把界面、推理、日志彻底解耦。多目标跟踪ByteTrack、DeepSORT从“检测到没戴帽子”升级为“跟踪这个人是否持续不戴帽子”。从项目角度来说本文这套“YOLOv8 检测 PyQt5 展示”的组合已经构成一个完整的演示系统。你可以在这个基础上从单张图片检测入手逐渐扩展到视频和摄像头实时检测再结合自己的业务场景加入记录、统计、告警等功能逐步打磨成一款真正能辅助现场安全管理的实用工具。代码量不大但每个环节都值得亲手跑一遍遇到报错不要急按上文排查表逐步检查很快就能把整套流程跑通。
返回列表