基于YOLOv5的DMS驾驶员监控系统设计与PyQt实时检测实现 📅 发布时间:2026/8/31 21:34:25 👁 浏览次数: 简介本资源面向智能交通、车载视觉与AI安全检测领域的开发者及高校研究者提供一套完整的驾驶员分神行为检测解决方案聚焦抽烟、打电话、喝水、吃东西四类高危驾驶行为识别。资源包含已标注的5000余张高质量图像数据集按train/val/test规范划分配套标准data.yaml配置文件nc:4, names:[drinking,eating,mobile use,smoking]支持YOLOv5至YOLOv9系列模型直接训练同时集成PyQt5可视化界面源码与三份环境配置PDF教程覆盖从环境搭建、数据加载到推理部署的全流程。压缩包共2000个文件以1994个YOLO格式txt标签为主辅以3个核心Python脚本和3份PDF说明文档整体大小356.88MB目录结构清晰、开箱即用。已有628人学习下载特别适合需快速验证DMS算法效果、开展课程设计或科研原型开发的技术人员。 DMS驾驶员监控系统这几年在商用车和乘用车领域越来越常见核心目的就是在驾驶过程中实时捕捉驾驶员的分神行为比如抽烟、打电话、喝水、吃东西。这些动作看起来不起眼却是交通事故中占比很高的诱因。我这次做的项目就是用YOLOv5算法实现一套可以本地运行的DMS检测demo支持抽烟、打电话、喝水、吃东西四类行为的识别并搭配一个PyQt界面方便连接摄像头实时展示结果也方便后续扩展告警、统计和报表功能。整套内容包含数据集整理、模型训练推理、界面封装三个部分覆盖了从数据标注到exe打包的完整链路。对正在做毕业设计、安全驾驶相关产品demo或者想入门YOLOv5实际落地的同学来说这套方案可以直接复现。下面我把每个环节的选型思路、踩坑记录和实操参数都展开聊一聊希望能帮你少走弯路。1. 项目整体设计与技术选型1.1 DMS场景为什么选YOLOv5而不是更重的模型做DMS检测首先要面对一个现实问题车辆座舱内的计算资源有限尤其是商用车后装设备很多时候用的还是嵌入式平台比如Jetson Nano、RK3588这类板子。模型必须同时兼顾精度和速度。YOLOv5在这一点上做得比较均衡s/m模型在主流GPU上能跑到几十甚至上百FPS转换成TensorRT后还能进一步提速部署资料也最全。我对比过YOLOv7、YOLOv8和YOLOv5的实际体验。YOLOv8代码更新、训练更方便但很多边缘部署工具链还是优先适配YOLOv5的export格式YOLOv7在精度上略有优势可工程化文档偏少。DMS场景下的检测目标比较集中主要是手部、面部、手机、水杯、食物等局部物体不需要像自动驾驶那样检测几百个类别所以YOLOv5s或YOLOv5m的容量完全够用。另一个考量是项目可维护性。YOLOv5的Ultralytics仓库写得很清楚数据格式、训练参数、模型导出API都比较稳定社区讨论多遇到问题容易搜到答案。对于个人项目或中小团队交付选择一个“稳”的框架比追求极致精度更重要。1.2 四个检测类别的识别难点很多人第一次接触这个项目会以为检测抽烟和打电话就是检测手部目标但其实没那么简单。抽烟这个动作一只手拿着烟靠近嘴部烟雾会干扰画面而且打火机点燃瞬间有火光容易误检成“打电话”或者“吃东西”。打电话的典型特征是手机贴近耳朵但如果驾驶员用的是蓝牙耳机或车载免提手部没有明显目标这时候模型很容易漏检。喝水通常是一个杯子或水瓶靠近嘴部可不同杯子的形状差异很大保温杯、纸杯、矿泉水瓶、吸管杯都会影响检测结果。吃东西更麻烦食物种类太多饼干、面包、水果、坚果外观差异巨大而且吃一口放下来再拿起来目标小、速度快。这些问题不能只靠模型结构解决更多要靠数据集中覆盖足够多的姿态、光照和个体差异。我在标注时会把“手持物体靠近面部”作为核心判定标准尽量保证每个类别都有不同性别、不同肤色、不同拍摄角度、不同车内光线的样本。1.3 PyQt界面在整个项目中的定位算法模型只负责输出检测框真正要交付给别人演示或者实际使用还需要一个界面把它包起来。PyQt在这里的价值是开发快、跨平台、控件丰富环境里也容易集成摄像头和视频文件。我的界面主要分三个区域左侧是实时视频显示右上是检测结果列表和置信度右下是行为统计和告警记录。这样现场测试时既能直观看到检测框也能看某个行为在什么时间被触发了几次方便后续做数据分析。界面还要处理线程并发。摄像头读取和模型推理都是耗时操作如果直接放在Qt主线程里拖动窗口就会卡死。所以我把采集、推理、显示分成三个线程通过信号槽来传帧这是这个项目里比较关键的设计点。2. 数据集准备与标注细节2.1 数据来源与采集思路DMS相关公开数据集并不多很多家用车监控数据涉及隐私不能直接下载。我一开始用了几种开源驾驶员行为数据集比如State Farm Distracted Driver Detection、AUC Distracted Driver Dataset但它们的类别定义和我的需求不完全一致很多图片是静态截图视角也偏多样直接拿来训练效果并不好。更好的做法是“公开数据 自采数据”结合。公开数据用来做预训练和扩充数量自采数据用来适配自己的摄像头安装位置和车内环境。我当时用一个普通USB广角摄像头放在仪表台位置模拟实际安装角度录了大概两小时不同时段的驾驶画面然后按帧切图。白天、夜晚、逆光、戴墨镜、副驾有人说话等场景都尽量覆盖。如果有条件还可以用合成数据补充极端情况。比如在3D软件里渲染一些手部动作模型或者用换脸/换背景的方式把检测目标贴到不同车内图上。这类数据对提升泛化能力帮助很大但要注意标注一致性。2.2 标注格式与类别平衡处理YOLOv5使用txt格式标注每行是class_id cx cy w h其中cx、cy、w、h都是归一化到0~1的小数。类别我定义成0: smoking抽烟1: calling打电话2: drinking喝水3: eating吃东西标注时最容易犯的错误是框的范围不统一。比如喝水有人只框瓶子有人会连手一起框进去导致同一个类别目标尺寸差异很大。我这里建议统一以“物体主体”为边界比如水瓶就框瓶身不要包含整只手吃东西就框食物和嘴部附近区域如果食物太模糊就框嘴部张开区域。类别不平衡也很常见。抽烟和打电话的样本相对容易找喝水、吃东西就少很多。我处理的办法是对数量少的类别做重复采样同时用数据增强生成更多变体让模型在训练时不会因为某个类样本太少而偏向忽略它。2.3 数据增强与划分策略YOLOv5自带的增强参数已经够用。我在训练时开启了Mosaic、随机翻转、HSV扰动和随机平移缩放。Mosaic相当于把四张图拼在一起训练能显著提高小目标检测能力尤其适合喝水、吃东西这种目标较小的场景。划分数据集时我严格遵守“按人物划分”也就是同一个人的不同帧图片不能同时出现在训练集和验证集。否则模型很容易记住这个人验证分数虚高实际换个人就失效。常规比例我用train:val:test 8:1:1测试集独立留着最后评估。另外还需要检查标注是否有越界框。YOLOv5训练时会对边界框做clip但如果标注太离谱模型学到的是错误坐标精度会明显下降。我写了一个简单脚本把每张图的标注和原图叠加画出来批量抽查了一遍这一步虽然花时间但性价比非常高。3. YOLOv5训练核心流程与参数调整3.1 环境搭建与依赖版本选择训练环境我建议直接用官方推荐的组合Python 3.8 PyTorch 1.12或2.0CUDA 11.x。yolov5的requirements.txt会列出opencv-python、matplotlib、numpy、Pillow等依赖直接pip install -r requirements.txt即可。这里有一个特别想提醒的点不要无脑升级到最新版PyTorch。我之前用PyTorch 2.1训练过一次发现个别算子在某些GPU上有兼容问题推理时会报错。后来换成1.13稳定版问题就消失了。做工程项目环境稳定比版本新更重要。3.2 配置文件修改与超参数设置训练前要准备好三个文件data.yaml、模型yaml、超参数yaml。data.yaml内容大概是这样train: ./datasets/dms/train/images val: ./datasets/dms/val/images test: ./datasets/dms/test/images nc: 4 names: [smoking, calling, drinking, eating]模型yaml我直接用的yolov5s.yaml把nc改成4。超参数我一开始没有大改基本沿用官方默认的hyp.scratch-low.yaml只调整了几个关键项img: 640输入分辨率batch: 16根据显存调整8GB显存可以16超过会OOM就降到8epochs: 100如果只是验证效果60也够lr0: 0.01官方默认warmup_epochs: 3.0训练命令是python train.py --img 640 --batch 16 --epochs 100 --data dms.yaml --cfg yolov5s.yaml --weights yolov5s.pt --name dms_exp加了--weights yolov5s.pt会用COCO预训练权重迁移学习比从零训练收敛快很多也更容易达到实用精度。3.3 训练过程监控与模型评估指标训练时我习惯开着TensorBoard看实时曲线重点关注三块总的box_loss、obj_loss、cls_loss以及验证集上的mAP50和mAP50-95。DMS场景下mAP50比mAP50-95更有参考意义因为检测框稍微偏移一点不影响告警判断。如果mAP50能到0.9以上实际使用基本够用。我还看了每种类别的混淆矩阵发现“喝水”和“吃东西”偶尔互相误判原因是动作相似度太高都是手持物体靠近嘴部。这个问题的解决方式不是调模型而是增加更多“水杯透明”和“食物颜色鲜艳”的样本。训练结束后best.pt会保存在runs/train/dms_exp/weights/下。我一般会先用test集执行python val.py --data dms.yaml --weights runs/train/dms_exp/weights/best.pt --task test得到最终指标再进入部署环节。3.4 模型导出与部署优化训练好的pt模型不能直接嵌到PyQt里跑虽然YOLOv5支持直接用torch.load加载但为了速度和兼容性我建议导出成ONNX再转成OpenVINO或TensorRT。导出命令python export.py --weights runs/train/dms_exp/weights/best.pt --include onnx导出时注意--opset版本我推荐12或13太高太低都可能遇到算子兼容问题。如果目标平台是Intel CPU可以继续转成OpenVINO IR格式推理速度能提升不少如果是NVIDIA GPU就转TensorRT的FP16模型延迟能降到个位数毫秒。部署时我还常用一个技巧稍微调低conf_thres和iou_thres。在DMS场景中漏检比误检更危险所以我一般把conf_thres设到0.25iou_thres设到0.45比官方默认更宽松能减少漏报。具体阈值可以根据实测效果调节不必强求统一。4. PyQt界面开发与实时检测集成4.1 界面布局与功能规划PyQt界面我用的是QMainWindow QGridLayout布局。左边放QLabel显示图像右边放两个QGroupBox一个是“检测结果”用QTableWidget记录类别、置信度和时间另一个是“行为统计”用QTextBrowser或者简单的QProgressBar展示每个行为累计次数。底部放一排按钮打开摄像头、打开视频文件、开始检测、停止检测、退出。这样配置灵活没有摄像头的时候也能用本地视频验证。界面设计不需要花哨但要注意三点分辨率适配不同屏幕、控件缩放时图像不变形、耗时操作不能卡UI。我用的方案是图像先通过cv2.resize转成固定宽度再转成QImage显示确保摄像头分辨率变化时界面保持稳定。4.2 摄像头/视频流接入逻辑摄像头接入我用OpenCV的cv2.VideoCapture(0)并设置了分辨率和帧率cap cv2.VideoCapture(0) cap.set(cv2.CAP_PROP_FRAME_WIDTH, 1280) cap.set(cv2.CAP_PROP_FRAME_HEIGHT, 720) cap.set(cv2.CAP_PROP_FPS, 30)读取视频流的线程会不停地cap.read()然后把帧放到一个队列里。推理线程从队列取帧运行模型把绘制好的结果放回另一个队列UI线程只负责显示。这里有个经验不要每帧都做推理。摄像头30帧但推理可能只有15帧如果队列积压画面会越来越卡。我给队列设置了最大长度超过就丢弃旧帧保证显示的是最新结果。4.3 检测结果实时绘制与告警联动模型输出的结果是坐标和类别我会先画框再在框上显示类别名和置信度同时更新右侧的统计表。告警逻辑我做了这样一个设计单帧检测到阳性行为不算告警只有连续3~5帧都检测到同一个行为才触发告警。这样能过滤掉偶发误检比如驾驶员只是抬手挠一下头不会因为模型误判成抽烟而一直报警。告警触发后界面会弹出系统托盘消息同时记录一条日志到CSV文件。也可以用蜂鸣器或者声音提示但声音在实测中会让人烦躁所以我只在界面上加了红色闪烁提示并保留了告警记录方便事后追溯。这个设计在真实场景下更可控。4.4 打包成EXE的注意事项项目最终交付很多场景需要一个双击就能运行的exe。我用PyInstaller打包命令大致是pyinstaller -w --add-data best.pt;. --add-data dms.yaml;. main.py-w表示不显示命令行窗口--add-data把模型权重和配置文件一起打包。PyTorch和YOLOv5依赖体积大最终exe可能超过500MB这在正常范围内。打包踩过的坑主要有三个一是OpenCV的dll有时不会被自动带上需要在spec文件里手动添加二是模型路径在打包后要用sys._MEIPASS来定位否则找不到best.pt三是PyInstaller和某些PyQt版本会有兼容问题建议PyQt5用5.15.xPyInstaller用最新稳定版。如果想把exe体积减小可以尝试排除不必要的CUDA库只用CPU推理或者改用ONNX Runtime。后者体积小很多部署也更干净适合演示环境。5. 常见问题与排查技巧实录5.1 训练loss不收敛/波动大的排查我一开始训练这个DMS数据集时遇到过loss反复振荡、mAP上不去的情况。排查下来最大的原因是标注中存在大量“背景框”也就是框住了手部但并没有对应行为。比如驾驶员只是拿着手机看导航模型会误认为打电话。这种标签与语义不符会导致训练时梯度方向混乱。建议每训练20轮就手动看一次验证集图片上的预测结果如果发现某类误检特别多回到标注阶段补标或删除歧义样本效果会好很多。另外学习率也可以适当降低比如lr0从0.01降到0.005让模型更稳定收敛。5.2 检测精度低、漏检误检优化如果mAP已经不错但实际检测还是漏检问题往往出在摄像头角度和画质上。DMS摄像头通常安装在方向盘中轴或A柱位置角度比较固定如果训练数据里都是正面视角实际测试时驾驶员低头看手机或转头看窗外模型就会失效。我的做法是增加一个简单的数据增强随机旋转正负15度、随机裁剪、随机仿射变换同时专门采集了一些侧脸和低头的样本。实际测试下来漏检率降低了不少。还要检查摄像头分辨率建议至少720P太低的画质会让小目标直接变成像素团模型再强也识别不了。5.3 PyQt界面卡顿、线程阻塞处理卡顿基本都出现在推理线程和UI线程抢资源。我最初把模型推理直接写在按钮点击槽函数里点击“开始检测”后整个界面就假死了。后来改成QThread用自定义信号把处理好的帧传回主线程问题就消失了。还有一个隐蔽问题摄像头线程如果读取失败会不断尝试cap.read()导致CPU空转。我在读取循环里加了超时判断连续20帧读取失败就自动断开并提示用户检查摄像头。这个小细节能让程序健壮很多。5.4 模型跨设备部署踩坑记录模型在台式机GPU上跑得好好的换到另一台只有CPU的笔记本上速度从60帧掉到5帧这是很多新手会遇到的落差。解决办法是根据目标设备选择不同模型尺寸CPU上跑YOLOv5n或YOLOv5s并把输入分辨率降到480虽然精度会略有下降但至少能保证实时。另外不同设备的OpenCV版本会影响图像编码方式有时候摄像头画面出现色偏不一定是模型问题而是cv2.cvtColor的通道顺序没处理好。我在代码里统一了BGR2RGB的处理并固定了显示端的通道顺序避免这类隐性bug。写在最后的实操建议如果你也准备做类似项目我建议按照“小数据→小模型→全流程跑通→再扩数据”的顺序来。不要一上来就追求80GB大模型和一万张标注图先用几百张图训练一版YOLOv5s把PyQt界面和告警逻辑调通再逐步加数据、调参数。这样做的好处是能快速发现流程中的问题比如标注格式错误、摄像头读取异常、打包路径丢失等这些问题越早暴露越容易解决。我个人实际踩过最大的坑不是模型训练而是标注一致性。同一类行为的框标准不统一后面所有工作都会受影响。所以如果你想复现第一步建议先用标注工具检查一遍所有数据保证框的都是想要检测的目标再谈训练和界面优化。希望这些细节能给你省下不少调试时间。本文还有配套的精品资源点击获取