
简介本资源是一个面向智能交通与车载AI开发者的疲劳驾驶实时监测系统实现方案聚焦驾驶员状态识别与分心行为检测两大核心任务适用于辅助驾驶系统研发、DMS算法验证及计算机视觉课程实践。压缩包共12个文件含10张模型测试效果示意图展示Perclos眼闭合分析、哈欠/喝水/抽烟/打电话等YOLOv7检测结果、1个关键处理脚本Concat.py用于多源行为特征融合或帧级结果拼接及1份README.md说明文档整体体积4.7MB轻量易部署。已有148人学习下载适合具备Python与PyTorch基础的中级开发者快速复现完整流程。读者可直接获取基于改进YOLOv7的多行为检测模型推理逻辑、Perclos计算模块集成方式、典型场景下的可视化检测输出样例以及系统级联设计思路为后续嵌入式移植或预警策略开发提供可运行基线代码与结构化参考。 做车载视觉这几年我接到过最多的需求就是“把疲劳驾驶检测落地”。这类DMSDriver Monitoring System项目最核心的坑不在算法本身多高深而在于怎么把眼睛的疲劳状态判断和嘴巴、手部的行为识别在一个不算宽裕的算力上稳住帧率。我这套方案用的是Perclos做疲劳核心指标用改进版YOLOv7做目标感知层覆盖哈欠、喝水、抽烟、打电话四个场景算是目前行业内比较主流、也比较平衡的一套打法。如果你正准备做DMS相关的课题或产品原型或者手里已经有一套目标检测代码但不知道怎么把它组织成完整的疲劳驾驶系统这篇整理应该能帮你省不少弯路。1. 项目整体认知与技术选型分析1.1 疲劳驾驶检测的核心逻辑疲劳驾驶检测从技术路径上分三类生理信号类、车辆行为类、视觉行为类。生理信号类脑电、肌电、心率准确度高但需要接触式穿戴设备前装车型很少直接用车辆行为类方向盘转角、车道偏离、跟车时距间接反映驾驶员状态但依赖车辆信号和道路条件且判断滞后视觉行为类是当前DMS的主流用一个摄像头对着驾驶员通过图像判断眼睛闭合、嘴部动作、头部姿态和手部行为非接触、成本低、可解释性强。基于视觉的疲劳检测核心要拆成两层感知层回答“眼睛在哪、嘴在哪、手在哪、有没有手机、烟、水杯”决策层回答“眼睛有没有持续闭合、嘴巴是不是在打哈欠、是不是在打电话”。目标检测模型负责前者Perclos和时序规则负责后者。这里最忌讳的是把两层混在一起直接拿分类网络做“疲劳/不疲劳”二分类要么在复杂光线下效果崩塌要么无法输出中间证据出了问题连排查都无从下手。1.2 为什么是Perclos YOLOv7的组合Perclos全称Percent of Eye Closure指单位时间内眼睛闭合时间所占百分比是疲劳判别领域公认的指标。它不像很多人想的那样是个AI算法而是一个带有明确物理含义的统计量。研究普遍采用P80准则眼皮遮挡瞳孔面积超过80%就算眼睛闭合当Perclos值超过0.4时判定为疲劳状态。YOLOv7在这里的角色是给Perclos提供“眼睛状态”的可靠输入。原版YOLOv7在通用检测任务上精度和速度的平衡度很好结构上有ELAN高效聚合模块、重参数化卷积、辅助训练头、SPPCSPC金字塔池化理论功底和工程底子都扎实。但原版模型对“眼睛”“烟”“手机”这类小目标、小物体不够敏感直接部署到Jetson一类边缘设备实时性也吃紧。所以项目标题里的“改进”是必须的不是锦上添花。说得直白一点Perclos负责“累不累”的判断YOLOv7负责“看到了什么”去掉任何一个这套系统都不成立。只靠传统Perclos框架没有深度模型眼睛定位在车辆晃动、光照变化下会崩只靠通用YOLOv7不解决小目标和实时性跑起来又慢又漏检。1.3 改进版YOLOv7的几个方向实际落地时我见过最多、也最稳妥的改进组合是三条轻量化主干、注意力模块、小目标检测层。轻量化主干解决速度问题。原始Backbone的ELAN模块在GPU上效率不错但在Jetson Nano、RK3588这类嵌入式芯片上还有压缩空间常用做法是引入MobileNetV3、GhostNet或者把普通卷积替换成GhostConv、DSConv在可控精度损失下换回20%到40%的帧率提升。注意力模块解决精度问题。DMS场景的背景是车内环境相对单一但驾驶员可能戴墨镜、帽子、口罩逆光和隧道光变化剧烈。在主干最后几层或Neck部分插入CACoordinate Attention、CBAM这类轻量注意力对眼睛和手部小目标的特征提取更聚焦。小目标检测层解决漏检问题。原始模型在P3、P4、P5三个尺度输出最小检测层的步长为8对于一张640x640的图眼睛区域可能只有十几个像素。常见做法是增加P2层融合更高分辨率的特征图或者在成本允许时把输入分辨率提到960。P2层带来的显存和计算开销不小需要按设备算力取舍。这三个方向的具体做法我后面逐个展开。2. 数据准备与标注规范2.1 数据采集方案数据质量决定模型上限。采集时我会刻意覆盖几个维度不同人种、性别、年龄段、是否戴眼镜、墨镜、帽子、口罩不同光线条件包含白天强光、逆光、夜晚红外补光、隧道内连续变化光不同姿态包含正常驾驶、转头看后视镜、低头看手机、仰头喝水、打哈欠、抽烟手势等。摄像头机位建议放在方向盘转向柱上方或仪表盘中央偏上略微俯拍角度大概10到20度能够同时看到完整脸部、双手和部分饮料杯。分辨率不需要特别高1280x720即可采样帧率在25到30帧每秒。同一个人连续录制的视频不能直接全进训练集需要做抽帧去冗余否则模型会对特定角度和光照过拟合。2.2 标注类别与工具类别设计会直接影响决策层逻辑。我习惯把目标拆细一点eye_open睁眼eye_closed闭眼mouth_open张嘴用于哈欠判断mouth_closed闭嘴face人脸框辅助区域约束phone手机cigarette香烟drink水杯/饮料瓶细拆的好处是Perclos能直接读取eye_open和eye_closed两类目标的置信度与坐标不用再单独做分类。如果标注时只笼统地标“喝水”“抽烟”整体行为框后面做规则判断时反而拿不到“水杯位置”和“嘴部位置”的关系可扩展性很差。标注工具用LabelImg最省事多人协作建议用CVAT或X-AnyLabeling支持视频标注和自动追踪能省不少重复劳动。眼睛这类小目标标注要格外小心框一定要紧贴目标宁可略小不要留白因为框太大或背景占比高正样本的特征会被干扰训练后框的回归精度也会变差。2.3 数据增强与样本均衡车内场景的负样本远多于正样本驾驶员大部分时间是正常驾驶哈欠、喝水、抽烟都是小概率事件。如果不做人工干预模型会严重偏向“不张嘴、没有手机”这类背景类测试时误检低但召回也低实车场景漏报会非常严重。我的做法是对哈欠、抽烟、喝水样本做5到10倍过采样同时配合Mosaic、MixUp、随机HSV扰动、运动模糊、随机遮挡等在线增强。Mosaic能把四张图拼在一起训练变相增大batch size还能让模型在小目标上看到更多上下文。特别提醒抽烟和喝水这类动作往往幅度大但持续时间短标注时最好把“拿起”“放下”的中间过程也标进去让模型见到更完整的动作序列决策层做时序判断时才有连续输入。增强后的数据集中每类目标建议不少于3000个实例数量太少的话训练出来的置信度会很不稳定。3. 改进YOLOv7网络结构解析3.1 YOLOv7网络结构图全拆解ELAN、SPPCSPC与检测头先回顾原版YOLOv7结构后面说改进才有参照。输入图像经过Stem卷积进入BackboneBackbone的核心是ELAN模块全称Efficient Layer Aggregation Network。它通过长跨度特征聚合把不同层输出按通道拼接让信息流动更充分同时控制梯度消失。下采样用MPConv模块在步长为2的卷积旁路并联一个MaxPool分支再把结果拼接。Backbone末端接SPPCSPC空间金字塔池化用不同池化核尺寸捕捉多尺度特征。Neck部分使用PANet结构自顶向下和自底向上各融合一轮把高层语义信息和低层空间信息交替结合。头部是三个尺度的Detect检测头分别负责小、中、大目标配合训练时的辅助头和推理时的重参数化卷积原版性能确实能打。但注意原版在COCO这类通用数据上表现好直接搬到DMS场景有明显短板小目标弱、模型偏重。整个结构里最值得改的是Backbone的卷积深度、主干选择以及检测头的尺度范围。3.2 改进方案一轻量化Backbone替换我在类似项目里常用一个平衡方案不整个换成MobileNet而是只把Backbone尾部几层做轻量化替换。全换MobileNet的好处是FPS高但精度损失太大眼睛的小目标信息容易在高层特征图中丢失只替换尾部前面保留ELAN的高效聚合能力速度和精度的平衡更好。具体做法可以参考基层保留原ELAN模块到P4、P5层时把标准3x3卷积替换为GhostConv用一次普通卷积生成内在特征再用线性变换生成冗余特征把计算量压下来。同时激活函数统一换成SiLU和原结构保持一致。这样改完同等输入分辨率下模型GFLOPs大约能降15%到25%帧率明显提升mAP只下降1到2个百分点可接受。3.3 改进方案二CA注意力机制插入位置注意力模块插入位置很关键。我试过在Backbone每一层后都插CA效果提升不明显训练还变慢也试过只在Neck末层插改善有限。最后效果比较稳的落点是两处一处是Backbone输出到SPPCSPC之前另一处是PANet上采样融合之后。CA坐标注意力比SE通道注意力更适合这个场景因为SE只建模通道关系CA还能把空间位置信息编码进来。眼睛、手机、香烟在画面里的位置相对固定CA学习到的位置先验能显著减少误检。比如把方向盘按键误检成手机、把车内装饰纹理误检成香烟这类问题加入CA后有效改善。3.4 改进方案三小目标检测层眼神状态判断依赖眼睛小目标这是整个系统精度最敏感的地方。原版输入640x640时最小特征图是80x80眼睛框往往只有十几像素在深层特征图里已经很难区分。改进方案是增加一个160x160的P2检测头利用特征金字塔把浅层高分辨率特征送进检测。代价是后处理耗时增加、显存上涨所以我只在推理端按需开启P2分支训练时仍用完整多尺度让网络学到更丰富的细节。如果设备实在吃紧还有个折中方案把输入从640x640提到960x960只保留P3及以上检测头检测效果接近P2层速度相对好一些。4. 模型训练与调参经验4.1 训练环境与依赖代码以官方yolov7仓库为基础。环境一般是Python 3.8以上PyTorch 1.10到1.13之间CUDA 11.x。核心依赖如下pip install torch1.13.1 torchvision0.14.1 opencv-python numpy matplotlib pyyaml tqdm显卡建议显存至少8G。我常用RTX 3070或3080训练batch size在16左右云端A10或A100训练体验更好但混合精度在小目标上要注意保留关键层的FP32梯度避免loss震荡。训练前把数据集组织成标准结构images/train、images/val、labels/train、labels/val标签用YOLO格式每行“class cx cy w h”坐标归一化到0到1。类别文件data.yaml里写清楚names列表顺序必须与标注时的class id一致这一步错了后面全白搭。4.2 超参数与训练策略输入分辨率设640x640训练轮数我一般跑200轮但真正有效的判定是看val mAP曲线的收敛平台不一定非要跑满。优化器用SGD加momentum 0.937初始学习率0.01warmup在3轮内完成后面用余弦退火慢慢降到0.0001。权重衰减设0.0005这是官方默认也比较稳。遇到小数据集时冻结Backbone前几层只训练Neck和Head可以显著防止过拟合。我的习惯是前30轮冻结等loss降下来再解冻全部参数。混合精度要谨慎DMS场景里小目标的梯度幅度小FP16容易丢失信息建议用torch.cuda.amp时关闭对检测头前两层的半精度或者直接用FP32训练加FP16推理稳定性更好。4.3 评估指标与验收标准不能只看mAP要看具体类别。小目标的mAP.5:.95往往比mAP.5低10个百分点以上这是正常的。对于这个系统我重点关注eye_closed类别的AP、phone、cigarette、drink的误检次数以及整链路端到端帧率。指标验收参考值说明眼睛闭合AP0.5≥90%疲劳判断的关键输入哈欠动作召回率≥85%覆盖张嘴到闭合完整过程分心行为误报率≤1次/小时按实拍整车场景统计端到端帧率≥15FPSJetson Orin Nano级别这个表里的数值不是拍脑袋是综合多个DMS公开数据集和自采数据交叉验证后得到的基准区间你可以按自己的场景调整。5. Perclos疲劳判定与多行为决策逻辑5.1 Perclos计算与阈值设定YOLOv7输出眼睛框后Perclos按如下公式计算Perclos 闭眼帧数 / 统计窗口总帧数判定单帧“闭眼”用P80准则眼皮遮挡瞳孔面积超过80%视为闭眼。工程上可以简化处理用眼睛框的宽高比或EAREye Aspect Ratio替代瞳孔遮挡面积。但纯EAR对头部姿态比较敏感驾驶员低头时比例剧变误判严重。我实际的方案是眼睛框宽高比与目标置信度结合如果eye_open置信度低于阈值且eye_closed置信度高于阈值判为闭眼。统计窗口用60秒滑动窗口每0.5秒计算一次当窗口内Perclos值超过0.4时触发疲劳告警。这个数值来自经典文献0.4到0.5之间是疲劳警戒区间。不同光照条件下需要微调夜间红外人眼特征明显闭眼判断更准阈值可以适当收紧。5.2 哈欠、喝水、抽烟、打电话的时序判断逻辑目标检测只能给出“这一刻画面里有什么”无法表达“正在做什么”这个连续动作所以决策层必须带时序。我采用的规则如下。哈欠mouth_open持续超过1.5秒且张嘴幅度大触发哈欠计数配合头部上扬动作可降低误报。哈欠在60秒内超过3次判定疲劳概率增加。喝水检测到drink目标且drink框与面部区域有接触或接近持续2秒以上才算喝水动作。如果只检测到水杯放在杯架上不能算喝水这一点很关键否则误报会非常多。抽烟检测到cigarette目标且cigarette框与嘴部区域有重叠或距离很近持续若干帧判断为吸烟动作。点烟、夹烟都不算避免过于敏感。打电话检测到phone目标且phone框与耳朵区域距离小于一定阈值同时结合面部角度如果手机出现在方向盘附近而人没靠近不算打电话。这套规则的缺点是边界参数多调起来繁琐。优点是可解释、可调、不依赖额外训练成本。如果你希望更智能可以在规则之上加一个轻量GRU或LSTM把检测结果序列映射到行为类别但参数可解释性会下降。5.3 综合疲劳评分与多级报警单一Perclos不好覆盖所有疲劳形态。有人开车时眼皮一直微眯但闭眼比例不高有人频繁哈欠但眼睛状态尚可。所以我把指标做加权综合疲劳分 0.4 * Perclos归一化值 0.3 * 哈欠频率归一化值 0.3 * 分心行为频次归一化值分心行为包括喝水、抽烟、打电话单位时间内各计一次。总分超过阈值后按等级触发提醒一级用语音提示“请勿疲劳驾驶”二级增加声光报警和座椅震动信号三级通过网络上报给车队管理平台并抓拍现场照片。这个三级设计不是技术难点但很影响项目验收客户往往最看重报警链路的完整性和可回溯性。6. 部署与工程化实践6.1 推理优化与边缘设备部署训练用的模型不能直接部署到嵌入式设备一般要过一遍TensorRT。FP16精度下模型推理速度通常能提升1.5到2.5倍INT8量化提升更多但小目标精度下降明显眼睛检测尤其容易崩所以我不建议对眼睛检测头做量化可以保留FP16只对Backbone做INT8或混合量化。我在Jetson Orin Nano上部署时端到端帧率能做到25到30FPS前提是输入分辨率控制在640、开启TensorRT的DLA加速、把NMS的后处理移到GPU上。RK3588的NPU对YOLOv7支持也不错但要注意算子的兼容性某些自定义模块如重参数化卷积在NPU上要预先折叠成普通卷积否则跑不起来。这一步经常是项目进度的最大坑建议先用SDK自带的demo验证算子支持再动模型。6.2 摄像头选型与光照鲁棒性夜间是DMS的主战场普通RGB摄像头在夜晚基本不可用。要选带红外补光的近红外摄像头常见波长850nm或940nm。850nm效果更好但会有轻微可见红爆940nm完全不可见但传感器灵敏度略低。安装在驾驶位时我推荐850nm窄带滤光片方案。摄像头安装高度最好与驾驶员眼睛平齐或略高俯仰角微俯5到15度避免仰拍导致眼眶阴影过重。镜头视野要覆盖驾驶员面部区域和部分方向盘区域同时尽量别拍到中控屏否则屏幕亮度会干扰红外成像。安装固定也非常重要车辆震动导致画面抖动的话后续所有识别都会变得不稳定。6.3 系统架构与线程模型实时检测系统不能写成一个main里循环跑完的demo。我建议分成采集线程、检测推理线程、逻辑决策线程、报警通信线程。采集线程通过V4L2或RTSP收帧带时间戳压入队列推理线程单帧或小批量处理输出目标数组逻辑线程跑Perclos和规则时间窗口独立报警线程负责播报语音、写入数据库或上报平台。用时间戳对齐而不是帧数对齐因为预处理、推理、后处理的耗时会漂移如果按帧排序逻辑层的“1秒前”和实际时间就对不上了。日志也要记录检测框原始输出和决策结果方便事后回放分析误报这一点在调车阶段能救命。7. 常见问题与排查技巧实录7.1 眼睛小目标漏检严重怎么办先别急着改网络先看标注和预处理。眼睛框是不是标得过大、背景占比高有没有做类别均衡这两点没问题再看训练配置。如果还是漏检依次尝试提高输入分辨率到960、增加P2检测头、把Mosaic增强的随机缩放范围改小、在数据集中增加眼睛特写裁剪样本。不要一上来就换Backbone那是最后手段。7.2 训练时Loss出现NaN原因通常是学习率太大或标签异常、框尺寸超出图像边界。优先做数据校验统计所有标签的cx、cy是否在0到1范围内、w和h是否为正。然后确认warmup没有失效。最后检查混合精度如果用了AMP试试FP32训练验证是不是小目标梯度回传时溢出。7.3 实车测试误报高误报来源一般是两类一类是检测层把方向盘按键、方向盘织物纹理误检成手机、香烟另一类是决策层把放杯子的动作误判为喝水。前者在数据集里补充大量无目标负样本和方向盘特写加CA注意力后者靠逻辑层加“接触面积、持续时间”双重条件明显缓解。还有一个容易被忽略的点车辆颠簸造成的画面抖动会让小目标在帧间忽隐忽现需要在逻辑层加去抖计数器同一行为连续出现3帧以上才算。7.4 帧率不达标优先看推理耗时分布。如果主要耗时在后处理和NMS考虑降分辨率、减少检测类别数量、用更早的置信度阈值在NMS之前过滤大量低分框。如果主要耗时在Backbone再考虑框架优化和量化。切忌盲目换轻量网络。我多次看到有人一上来就把YOLOv7换成更小的网络速度是够了精度崩了回头又花大量时间调数据集得不偿失。7.5 戴墨镜和口罩场景怎么处理戴普通墨镜时红外摄像头透不过镜片Perclos直接失效。我的处理是增加一个“墨镜遮挡”分类状态如果检测到墨镜且长时间无法获取眼部特征按“疑似疲劳”降额判定并提示驾驶员摘下墨镜。更高级的做法是改用透红外镜片但成本高一般只在高端前装项目里用。戴口罩时嘴部被遮挡哈欠检测失效可以改成用眼部闭合和额头皱纹配合判定。额头皱纹检测需要更高清的ROI区域实际部署中效果有限。比较务实的方案是把“持续性眼睛闭合”作为戴口罩情况下的主要疲劳指标哈欠检测暂时降级。8. 写在最后的一点体会做DMS系统算法只是其中一半另一半是数据采集和逻辑层的边界打磨。Perclos加YOLOv7这套组合胜在成熟、可控、好解释。真正上线前一定要花大量时间在实车场景里录制数据、跑干扰测试把误报率压到能接受的范围否则再高的mAP在车主面前都会被一句“怎么又瞎报警”打回原形。如果后续想继续扩展可以在现有基础上加方向盘握持检测、驾驶员身份识别以及基于毫米波雷达的呼吸和心率检测做成多模态融合方案。这个方向这几年行业关注度很高技术路径也基本跑通了值得持续投入。本文还有配套的精品资源点击获取