☰
基于YOLOv5的驾驶员状态检测与危险行为识别实战
2026/10/21 2:53:39 网站建设 项目流程

这两年智能驾驶相关的视觉项目里,基于YOLOv5的驾驶员状态与危险行为检测算是最常被问起的方向之一。我把这套方案从数据整理、模型训练到推理落地完整过了一遍,过程中踩了不少坑,也总结出一些规律性的东西。这篇就把关键环节的取舍逻辑和实操细节展开说说,给正在做类似项目的同学一个可参考的路线。

1. 项目需求拆解与技术选型

1.1 检测对象与场景定义

驾驶员状态检测系统要做的事,本质上就是实时监控驾驶员的面部和手部行为,判断当前是否处于疲劳、分心或危险驾驶状态。具体到检测目标,通常包括:闭眼(疲劳指示)、打哈欠(疲劳指示)、低头(分心)、玩手机(分心)、吸烟、喝水、双手脱离方向盘等行为。

这些目标看起来简单,但实际场景里难点不少。首先是车内光线环境复杂,白天有侧窗阳光直射导致面部过曝,夜晚只有仪表盘微光和路灯闪烁;其次是驾驶员会佩戴眼镜、墨镜、口罩,面部特征经常被遮挡;再者是目标的尺度差异很大——人脸可能占据画面三分之一,而手机可能只有几十个像素。这些因素都在逼迫检测模型既要看得准,又要看得稳。

从应用场景看,这套系统主要面向两类需求:一是商用车队的安全管理平台,把疲劳和分心报警实时推送给监管端;二是乘用车领域的驾驶员监控系统,作为辅助驾驶功能的一部分,在驾驶员注意力分散时给出提示。

1.2 框架选型逻辑:为什么是YOLOv5

目标检测框架可选的范围其实很宽。两阶段检测器在精度上有优势,但推理速度很难满足实时视频流的要求;基于Transformer的检测模型精度不错,可对部署环境要求偏高;而YOLOv5恰好卡在一个非常舒服的位置上:单阶段检测、推理速度快、精度能满足业务需求,而且工程化生态极其成熟。

选择YOLOv5s还是有更充分的考量的。项目中需要在车规级边缘设备或普通工控机上运行,算力有限,YOLOv5s模型体积约14MB,单张640x640图像的推理时间在GPU上约3-5ms,在CPU上也基本能做到实时;如果换成YOLOv5m或YOLOv5l,精度能提升两三个点,但推理时间成倍增加,在边缘设备上很难保证25FPS以上的帧率。

还有一个很现实的理由是部署生态。YOLOv5的仓库结构清晰,导出ONNX、TensorRT、OpenVINO等格式都支持,配合NMS后处理的实现也比较成熟。项目推进过程中往往需要快速验证、快速迭代,选一个团队上手快、文档全、社区活跃的框架,能省去大量环境适配的时间。

2. 数据准备:决定模型效果的上限

2.1 数据来源与采集策略

很多人上来就急着调模型,但实际效果的上限在数据阶段就已经定死了。我这次的数据主要由两个部分构成:一部分是开源的驾驶行为数据集,另一部分是自采数据。

开源数据集能提供比较丰富的场景覆盖,比如不同国家的驾驶员、不同光照条件、各种车内布局,适合做模型预训练的底子。但只靠公开数据不够,因为目标类别定义和标注风格跟我这边不完全一致,尤其是吸烟、喝水这类动作,公开数据里的样本数量往往偏少。所以自采数据是必须要做的。

自采的方式不复杂:用一台普通摄像头架在驾驶位侧前方,模拟真实DMS摄像头的安装位置,录制多名志愿者在模拟驾驶环境中的行为。采集时重点覆盖几个维度:不同时间段的光照(上午顺光、中午顶光、傍晚逆光、夜间弱光)、不同人员特征(是否戴眼镜、是否戴帽子、肤色差异)、不同行为强度(轻微闭眼与明显瞌睡、拿手机打电话与低头刷手机)。

采集的时候建议同时录制一段正常驾驶视频作为背景样本。背景样本非常重要,模型容易把所有画面内容都当成待检测目标,如果没有足够的"什么都不该检出来"的负样本,推理阶段会出现大量误报。

2.2 标注规范与类别体系

标注规范直接决定了模型能学到什么。我这个项目把检测目标划分成六个类别:

类别名称定义标注框准则
open_eye睁开眼睛面部可见时标注双眼区域
closed_eye闭眼双眼闭合时标注眼部区域
yawn打哈欠张嘴且嘴部区域明显张开
phone使用手机手持手机且手机可见
smoke吸烟烟或烟头在嘴部附近可见
normal正常驾驶无上述行为时的标准面部状态

这里有一个关键取舍:为什么不直接用整张脸作为检测目标,而是细分到眼睛和嘴部?因为疲劳判断需要在眼皮闭合和嘴部张开的粒度上工作。如果只检测整张脸,闭眼和睁眼无法区分,后续状态判断逻辑就无从下手。同理,打哈欠行为的核心特征是嘴部张开的形态,把它作为独立目标检测,比先检测人脸再做关键点分析要简单直接得多。

标注时容易踩的坑主要是遮挡处理。驾驶员低头时,脸部可能有一半被手或方向盘挡住;拿手机时手部可能遮住嘴部。我的处理原则是:目标的可辨识面积低于30%时不标,高于30%但部分遮挡时正常标注,并在备注里记录遮挡类型。这样模型既不会因为目标被大量遮挡而学出错误特征,又能在部分遮挡时保持鲁棒性。

2.3 数据增强与训练集划分

数据增强策略上,我采用了YOLOv5自带的Mosaic增强、随机仿射变换和HSV色域扰动。Mosaic增强把四张图随机拼接成一张训练图,好处是变相扩大batch多样性,让模型看到更多的小目标样本——这对检测远处的手机、烟头这类小物体尤其有帮助。

随机仿射变换包含旋转、平移、缩放和错切,能模拟驾驶员在不同坐姿、不同距离下的成像差异。HSV扰动则是把色调、饱和度、亮度随机拉伸,增强模型对光线变化的适应力。这三个增强用下来,闭眼和吸烟这两个小目标类别的mAP都能提升三到五个点。

训练集划分上有个很多人忽略的细节:必须先按人员分组,再按组划分训练集和验证集,而不是直接把所有图片随机打散。如果同一个人的大量画面同时出现在训练集和验证集里,模型等于记住了这个人,验证指标会虚高,一到实际部署就现出原形。我这边按人员以7:2:1比例划分训练、验证和测试集,确保验证集里出现的人完全没参与过训练。

3. 模型训练全流程

3.1 环境配置与超参数设定

训练环境方面,我用了PyTorch框架,CUDA版本与显卡驱动匹配好后,直接拉取官方YOLOv5仓库代码。这一版代码对新手友好,尤其是训练和验证的命令行入口设计得很规范,几乎不需要改代码就能跑通整个流程。

关键的训练超参设置如下表:

参数名设定值选择理由
模型大小yolov5s精度与推理速度的平衡点
输入尺寸640 x 640标准分辨率,小目标可辨识度与算力的折中
训练轮数150 epochs充分收敛,配合早停机制防止过拟合
batch size16根据16GB显存设定,显存不足时建议梯度累积
初始学习率0.01YOLOv5默认值,配合余弦退火策略
动量0.937默认值,训练过程稳定
权重衰减0.0005默认值,抑制过拟合

batch size的选择要单独说一下。很多人盲目追求大batch,但batch太大容易让训练曲线过早进入平台期,模型泛化能力反而下降。16这个数值在显存允许的范围内足够稳定,配合Mosaic增强,等效batch相当于64张图的有效信息量,训练收敛速度和最终精度都表现不错。

如果显存只有8GB,建议将batch降为8并启用梯度累积,或者直接使用YOLOv5官方推荐的auto batch模式自动寻找最大可用的batch值。个人经验是不要为了把batch调大而大幅压缩输入尺寸,640分辨率对眼部细节和小物体的检测影响很大。

3.2 训练过程与监控要点

训练过程中我最关注的指标是训练损失曲线和验证集mAP曲线,而不是单看训练集损失。训练集损失持续下降但验证集mAP停滞甚至下滑,说明模型已经开始过拟合;如果训练和验证的损失同步下降,说明模型还在有效学习。

我在150轮中开启了早停机制,patience设为30轮。也就是说,如果连续30轮验证集mAP没有提升,训练自动终止。这个策略在数据集规模不大时非常有效,能避免无意义的算力浪费。实际训练中大约到110轮左右验证指标到达峰值,早停机制也在这个区间生效。

YOLOv5训练过程会自动保存每轮权重,建议把best.pt和last.pt都留下来。best.pt用于最终评估和导出,last.pt留着可以在后续增补数据时做热启动训练,比从头训练省一半时间。

训练时的数据加载线程数需要根据机器CPU核心数调整。我这边设为8,磁盘读取速度足够,训练吞吐接近满载。如果训练时GPU利用率一直上不去,优先检查CPU数据加载是不是成了瓶颈。

3.3 评估指标解读与阈值选取

模型评估阶段,YOLOv5默认输出mAP@0.5和mAP@0.5:0.95两组指标。mAP@0.5是IoU阈值取0.5时的平均精度,更贴近实际使用中对定位精度的容忍度;mAP@0.5:0.95则是从0.5到0.95每隔0.05取一组IoU阈值的平均结果,更严格,对框位置的精度要求更高。

我这个项目最终目标是报警场景,框的位置稍微偏一点其实不影响行为判断。所以调参时以mAP@0.5为主要参考,mAP@0.5:0.95作为辅助参考。训练完成后,六个类别的mAP@0.5整体能到0.92左右,其中open_eye和closed_eye最高,yawn和phone中等,smoke因为样本量最少,指标也最低。

推理阶段的置信度阈值和NMS阈值需要单独调。默认的conf_thres=0.25在通用检测场景下没问题,但驾驶员监控场景误报容忍度很低,我把conf_thres提到了0.45,NMS的IoU阈值设为0.5。提高置信度阈值会牺牲少量召回率,但显著降低误报,这个交换在报警系统中是值得的。如果实际部署中发现漏报偏高,再逐步下调到0.35左右找一个平衡点。

4. 推理与状态判断逻辑

4.1 实时推理流程设计

训练完成的模型要接入实际视频流才能产生业务价值。推理流程的基本链路是:读取摄像头帧,缩放至640x640,送入模型推理,输出检测框和类别,在原始帧上叠加显示。

这里有一个效率问题:摄像头原始帧分辨率通常是1920x1080,直接缩放成640x640后送入模型,模型推理本身没问题,但缩放过程会损失大量细节。我建议先用OpenCV做一次ROI裁剪,把画面中驾驶员面部和手部活动区域裁剪出来,再缩放至640x640。这样既保留更多有效信息,又减少了背景区域对检测的干扰。

实际部署时,我采用了每隔一帧推理一次的策略。DMS画面中驾驶员的行为变化是渐进的,闭眼、打哈欠这类动作持续几百毫秒甚至更久,25FPS的推理频率已经足够。隔帧推理能把CPU占用降一半,在较低算力的设备上也能稳定运行。

4.2 状态判断与时序逻辑

这里要强调一个容易被忽视的点:目标检测模型输出的是单帧检测结果,但"状态"必须是跨帧的时间序列结论。单帧检测出closed_eye可能只是眨眼,连续几十帧都检测出closed_eye才是疲劳。单帧检测出phone可能只是拿起手机看时间,持续几秒才属于分心驾驶。

我这边设计了几个简单的状态判断规则:

行为类型判断逻辑报警条件
疲劳检测到closed_eye连续超过2秒
疲劳检测到yawn每分钟超过5次
分心检测到phone持续超过3秒
危险检测到smoke持续超过2秒

每帧检测结果进入一个滑动窗口队列,窗口长度按帧率换算成时间。比如25FPS下,闭眼2秒意味着连续50帧出现closed_eye检测结果。这个设计能有效过滤掉眨眼、低头系安全带等瞬态误判。

另外一个实用技巧是检测结果的置信度不只看单帧。如果一个目标的检测置信度忽高忽低,说明模型不太确定,这时可以结合前后几帧结果做一个简单的投票机制,被多数帧确认的目标才进入状态统计,能进一步压低误报率。

4.3 报警策略与边缘部署

报警逻辑的工程实现需要注意"静默期"设计。连续报警会让监控后台被无效消息淹没,我这边实现了两级报警机制:第一次触发危险行为后先发出提醒级消息,如果在30秒内再次触发,才升级为严重报警。这个设计在实际运营中非常有用,大大降低了值守人员的疲劳感和无效处理的概率。

部署层面,我在测试中做了ONNX导出,再转换成TensorRT引擎。TensorRT的FP16推理相比PyTorch原始推理,帧率提升约两倍。如果用CPU部署,可以尝试OpenVINO工具链,在Intel平台上通常能获得不错的加速效果。

对模型做轻量化时一定要重新验证精度。剪枝和量化都能带来速度收益,但闭眼和吸烟这类小目标的精度损失最明显。我实验下来,FP16精度几乎无损,INT8会掉两个点左右,但换来的是更大的速度提升,适合对成本敏感的大规模车队部署场景。

5. 常见问题与排查实录

5.1 误检漏检的典型场景

项目调试阶段遇到最多的问题是夜间和强光下的误检漏检。夜间光线弱,闭眼特征不清晰,模型经常漏掉closed_eye;白天强光直射时,脸部出现大面积过曝,open_eye会被误判成closed_eye。

排查后发现根本原因是训练数据里暗光和强光的分布太少。解决办法是针对性补采了夜间和逆光样本,同时用自适应直方图均衡化对图像做预处理,增强暗部细节后再送入模型。补采数据重新训练后,夜间闭眼召回率提升了约一成。

戴墨镜是另一个高频误判场景。墨镜遮挡了眼睛区域,模型很容易把"墨镜遮挡"学成"闭眼",导致一路报警。这里我在状态判断逻辑里增加了一路OpenCV检测:如果眼部区域存在大面积黑色矩形,判定为戴墨镜,跳过闭眼这一路的疲劳判断。虽然简单,但非常奏效。

5.2 性能瓶颈与加速手段

如果部署发现帧率不够,先从三个方向排查:模型输入分辨率是否过高、NMS后处理是否用的CPU单线程、数据预处理是否拖慢整体链路。这三个因素通常能解释80%的性能问题。

以我在一台低功耗工控机上的测试为例,初始端到端推理约12FPS。我把输入分辨率从640降到544后升到16FPS,但还是不够。进一步排查发现瓶颈在NMS是在CPU上跑的,改成GPU NMS后帧率直接到了28FPS,达到实时要求。

如果还需要更高的性能,最后的手段才是更换更轻量级的模型结构。但要注意,模型结构变轻通常会让小目标的精度下降,而驾驶员监控恰好对手机、烟这类小目标敏感。所以性能优化应该优先考虑工程侧手段,模型侧改动放在最后。

5.3 部署测试中的关键业务指标

除了模型指标,我建议项目上线前一定要定义清楚业务指标。模型mAP是技术层指标,业务侧更应该关注的是:危险行为检出率(真实危险行为中有多少被成功触发报警)和误报率(单位小时内非危险行为触发报警的次数)。

我验收时给自己定的标准是:疲劳和分心行为的检出率不低于90%,误报率不超过每小时1次。这个标准在真机上跑了五轮模拟驾驶测试后才稳定达标。如果模型单帧指标很漂亮但业务指标不达标,问题几乎一定出在状态判断逻辑上——阈值太高会漏报,太低会误报,需要根据实际路测数据反复调试。

5.4 项目实操中的几条经验

做完整个项目,我总结几条对后来者最有用的经验:

第一,数据准备阶段多花一倍时间,训练和调试阶段就能省回三倍时间。尤其是背景负样本和困难样本,直接影响系统落地后的误报率。把数据当成最重要的资产来管理,每次训练用到的数据集版本都要留档记录,方便回溯。

第二,单帧检测模型和业务状态判断逻辑要分开设计和测试。很多团队把精力全砸在模型上,结果上线后报警逻辑一塌糊涂。我的做法是模型只负责输出事实——画面里有什么目标、位置在哪,状态判断逻辑单独做单元测试,用录制的视频片段模拟各种时序场景,验证报警逻辑的可靠性。

第三,现场的软硬件环境远比训练环境复杂。摄像头安装角度差几度,模型表现就会差很多。建议在项目早期就用目标安装角度的摄像头采集训练数据,而不是先用理想位置的数据训练,再后期适配现场安装角度。

第四,所有报警事件要留痕。不仅仅是为了事后追溯,更重要的是积累真实场景的难例样本。我把每次触发报警的帧和前后各30帧的视频片段自动保存下来,定期筛选后补充到训练集里,模型的迭代效果非常明显。

这个项目的技术路线已经比较成熟,但远未到可以"一把梭"的程度。数据质量、工程细节和现场调优仍然主导着最终效果。如果后续要做更深入的方向,可以考虑接红外摄像头解决夜间光线问题,或者融合方向盘转角、车速等信号做多模态疲劳判断,这会比单靠视觉检测更稳健。但不管怎么扩展,扎实的数据基础和清晰的逻辑分层都是同一个起点。

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

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

立即咨询