ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

基于YOLOv5的工业级疲劳驾驶检测系统:从模型训练到多平台部署实战

基于YOLOv5的工业级疲劳驾驶检测系统:从模型训练到多平台部署实战 简介本资源是一套基于YOLOv5实现的疲劳驾驶检测识别系统面向计算机视觉初学者、毕业设计学生及智能交通方向开发者解决驾驶员实时状态监测与预警的实际问题。压缩包共93个文件包含31个Python源码含主程序yolov5.py、模型定义与数据处理模块、24个YAML配置文件适配不同规模YOLOv5模型、2个PT权重文件best.pt为核心训练成果、2个MP4演示视频、2个图像样本及说明文档等整体大小为136.48MB。已有361人学习下载资源源自获导师高度认可98分的本科毕业设计项目提供完整可运行方案涵盖环境依赖安装、单脚本启动流程、多维度疲劳指标Blinks/EAR/dura/Yawning/MAR量化逻辑及人脸关键点检测shape_predictor_68_face_landmarks.dat支持。目录结构规范utils与models模块清晰分离便于理解YOLOv5定制化改造路径与疲劳识别算法集成方式。1. 项目概述从零构建一个工业级疲劳驾驶检测系统最近在整理硬盘里的老项目翻到了这个基于YOLOv5的疲劳驾驶检测系统。这玩意儿当年可是花了我不少心思从模型选型、数据集处理到最后的系统集成踩过的坑一个接一个。今天索性把它彻底拆解开来把源码、权重文件还有那份快被翻烂的说明文档里的干货结合我这几年在实际部署和优化中的经验一次性讲透。如果你正想用YOLOv5做类似的安全监控或者行为识别项目特别是面临如何从“跑通Demo”到“稳定上线”这个鸿沟那这篇内容应该能帮你省下至少两周的摸索时间。简单说这个系统就是用摄像头实时捕捉驾驶员的面部图像然后利用YOLOv5模型去定位眼睛和嘴巴等关键区域再通过一套逻辑规则比如计算眼睛闭合时间EAR、嘴巴张开频率等来判断驾驶员是否处于疲劳状态一旦检测到疲劳迹象就立刻触发警报。听起来不复杂对吧但真要把准确率做高、把误报率压下去、让系统在各种光照和姿态下都稳定工作里面的门道可就多了。这个压缩包里的东西就是一个已经调教好的、可以直接跑起来的完整解决方案包括了训练好的模型权重、全部的实现源码以及详细的部署指南。接下来我就带你深入这个“黑盒子”内部看看每一个零件是怎么工作的以及如何把它们组装成一个可靠的系统。2. 核心思路与技术选型为什么是YOLOv52.1 任务定义与模型选型的底层逻辑疲劳驾驶检测本质上是一个“目标检测”加“行为状态分类”的复合任务。第一步我们需要从复杂的驾驶舱环境中精准地框出驾驶员的脸、眼睛、嘴巴。第二步基于这些框出来的区域计算一系列生理指标如眼睛纵横比、嘴巴开合度并基于时间序列判断其是否构成疲劳模式。为什么在众多目标检测模型中比如两阶段的Faster R-CNN或者同为单阶段的SSD、YOLOv4等我最终选择了YOLOv5这绝不是跟风而是基于项目落地时几个非常现实的考量速度与精度的平衡这是一个实时监控系统。模型必须在普通的工控机甚至嵌入式设备比如你搜索热词里提到的RK3568、RV1106上达到至少15-20 FPS的处理速度。YOLOv5在PyTorch生态下的优化做得非常好其模型结构CSPDarknet PANet在保持较高精度的同时推理速度相比前代有显著提升。特别是其提供的ssmall、mmedium、llarge、xlarge四个预训练模型尺度让我们可以根据硬件算力灵活选择。对于疲劳检测我们通常不需要检测成百上千个类别yolov5s或yolov5m在精度上已经完全够用且速度飞快。工程化友好度YOLOv5的代码库堪称“工程典范”。它提供了从训练、验证、测试到导出的完整pipeline并且代码结构清晰配置文件*.yaml将模型结构、数据集路径、超参数分离管理起来非常方便。这对于需要快速迭代和部署的项目来说极大地降低了维护成本。相比之下一些学术性更强的框架其工程化封装程度往往不够。活跃的社区与生态YOLOv5有着极其庞大的用户社区。这意味着你遇到几乎任何问题都能在GitHub Issues或相关论坛里找到讨论和解决方案。更重要的是其模型可以方便地导出为ONNX、TensorRT、CoreML等各种格式这对于后续部署到不同平台如你提到的Android、Linux至关重要。生态繁荣直接决定了项目的可持续性和可扩展性。2.2 系统核心流程拆解整个系统的运行流程可以清晰地分为离线训练和在线推理两个阶段离线训练阶段数据准备收集大量包含驾驶员正脸、侧脸、戴眼镜、不同光照条件下的图片或视频。数据标注使用LabelImg等工具标注出“face”人脸、“eye”眼睛可分左右、“mouth”嘴巴等关键目标。标注质量直接决定模型上限。模型训练使用YOLOv5在自定义数据集上进行微调Fine-tuning。这里涉及大量的超参数调优如学习率、数据增强策略后文会详细展开。模型导出将训练好的PyTorch模型.pt文件导出为适合部署的格式如ONNX。在线推理阶段视频流捕获通过USB摄像头或RTSP流获取实时画面。目标检测将每一帧图像送入YOLOv5模型检测出人脸、眼睛、嘴巴的边界框Bounding Box和置信度。关键点计算与状态判断眼睛根据检测到的眼睛区域计算眼睛纵横比Eye Aspect Ratio, EAR。EAR是一个基于眼睛轮廓6个关键点计算的标量值眼睛睁开时值较大闭合时趋近于0。嘴巴类似地计算嘴巴开合度Mouth Aspect Ratio, MAR。疲劳决策基于连续多帧的EAR和MAR值应用决策算法PERCLOS准则这是行业常用标准指在一定时间窗口如3秒内眼睛闭合EAR低于阈值时间所占的百分比。例如PERCLOS值超过20%则判定为疲劳。连续哈欠检测在短时间内检测到多次嘴巴张大MAR超过阈值的行为。点头频率通过人脸框中心点的垂直位移变化估算点头频率。报警与输出当疲劳指标超过预设阈值系统触发声光报警并可在画面上绘制检测框、关键点和疲劳状态标签。3. 源码结构与核心模块深度解析拿到源码权重文件说明文档.zip后解压开来你会看到一个典型的YOLOv5项目结构但其中融入了疲劳检测的专用逻辑。我们来逐一拆解关键文件3.1 项目目录结构fatigue_detection_yolov5/ ├── data/ │ ├── custom.yaml # 自定义数据集的配置文件定义了类别名、路径 │ └── images/ labels/ # 你的训练图片和标注文件通常需要自己准备 ├── models/ │ ├── yolov5s.yaml # YOLOv5s模型结构定义 │ └── custom_model.yaml # 你可能修改过的模型配置文件如调整类别数 ├── utils/ │ ├── datasets.py # 数据加载和增强逻辑 │ ├── general.py # 画框、计算IoU等通用函数 │ ├── metrics.py # 计算评价指标 │ └── fatigue_utils.py # **核心**疲劳检测专用工具函数计算EAR/MAR疲劳判断逻辑 ├── weights/ │ └── best.pt # 训练得到的最优权重文件项目核心资产 ├── detect_fatigue.py # **核心**主推理脚本集成了视频流处理、YOLO检测、疲劳分析 ├── train.py # 模型训练脚本 ├── requirements.txt # Python依赖包列表 └── README.md # 说明文档3.2 核心代码模块detect_fatigue.py与fatigue_utils.pydetect_fatigue.py是系统的大脑它负责串联整个流程。我们看其核心循环import cv2 from models.experimental import attempt_load from utils.general import non_max_suppression, scale_coords from utils.fatigue_utils import calculate_ear, calculate_mar, is_fatigue # 1. 加载模型 device torch.device(cuda:0 if torch.cuda.is_available() else cpu) model attempt_load(./weights/best.pt, map_locationdevice) model.eval() # 2. 打开摄像头 cap cv2.VideoCapture(0) # 0代表默认摄像头也可替换为视频文件路径 # 3. 初始化疲劳状态追踪器 fatigue_state False ear_history [] # 用于存储最近N帧的EAR值 mar_history [] # 用于存储最近N帧的MAR值 frame_window 30 # 判断疲劳的时间窗口假设每秒10帧即3秒 while cap.isOpened(): ret, frame cap.read() if not ret: break # 4. 图像预处理 (符合YOLOv5输入要求) img preprocess(frame) # 包括resize, 归一化, 转换通道等 img torch.from_numpy(img).to(device) # 5. YOLOv5推理 with torch.no_grad(): pred model(img)[0] # 非极大值抑制过滤重叠框 pred non_max_suppression(pred, conf_thres0.5, iou_thres0.45) # 6. 解析检测结果 for det in pred: if len(det): # 将检测框坐标映射回原图尺寸 det[:, :4] scale_coords(img.shape[2:], det[:, :4], frame.shape).round() for *xyxy, conf, cls in det: label model.names[int(cls)] x1, y1, x2, y2 map(int, xyxy) # 7. 根据类别进行疲劳指标计算 if label eye: ear calculate_ear(frame[y1:y2, x1:x2]) # 截取眼睛区域计算EAR ear_history.append(ear) if len(ear_history) frame_window: ear_history.pop(0) elif label mouth: mar calculate_mar(frame[y1:y2, x1:x2]) # 截取嘴巴区域计算MAR mar_history.append(mar) if len(mar_history) frame_window: mar_history.pop(0) # 画检测框 cv2.rectangle(frame, (x1, y1), (x2, y2), (0, 255, 0), 2) cv2.putText(frame, f{label} {conf:.2f}, (x1, y1-10), cv2.FONT_HERSHEY_SIMPLEX, 0.5, (0,255,0), 2) # 8. 疲劳状态判断基于历史数据 if len(ear_history) frame_window: fatigue_state, reason is_fatigue(ear_history, mar_history) if fatigue_state: cv2.putText(frame, fFATIGUE ALERT: {reason}, (50, 50), cv2.FONT_HERSHEY_SIMPLEX, 1, (0, 0, 255), 3) # 触发报警如播放声音、发送网络请求 # trigger_alarm() # 9. 显示结果 cv2.imshow(Fatigue Detection, frame) if cv2.waitKey(1) 0xFF ord(q): break cap.release() cv2.destroyAllWindows()fatigue_utils.py是系统的判断逻辑核心它包含了所有的算法细节import numpy as np from scipy.spatial import distance def calculate_ear(eye_region): 计算眼睛纵横比 (Eye Aspect Ratio) 输入裁剪出的眼睛区域图像 输出EAR值 (float) 原理EAR (||p2-p6|| ||p3-p5||) / (2 * ||p1-p4||) 其中p1...p6是眼睛轮廓的6个关键点需先通过人脸关键点检测器如dlib获取本例为简化假设YOLO框足够准 # 在实际项目中这里通常会集成一个轻量级的关键点检测模型如PFLD来获取6个点。 # 为简化演示此处假设我们已经从eye_region中提取了坐标。 # 以下是伪代码逻辑 # keypoints detect_landmarks(eye_region) # 返回6个点的(x,y)坐标 # p1, p2, p3, p4, p5, p6 keypoints # ear (distance.euclidean(p2, p6) distance.euclidean(p3, p5)) / (2.0 * distance.euclidean(p1, p4)) # return ear # 由于本示例YOLO仅提供框一种实用替代方案是用框的高度和宽度近似计算一个比例。 # 注意这种方法精度低于关键点法但实现简单。 height, width eye_region.shape[:2] # 一个非常粗略的近似EAR正比于眼睛区域的“开阔程度” ear_approx height / (width 1e-6) # 防止除零 return ear_approx def calculate_mar(mouth_region): 类似EAR计算嘴巴开合度。 height, width mouth_region.shape[:2] mar_approx height / (width 1e-6) return mar_approx def is_fatigue(ear_list, mar_list, ear_thresh0.25, mar_thresh0.8, perclos_thresh0.2): 综合判断是否疲劳。 参数: ear_list: 最近N帧的EAR值列表 mar_list: 最近N帧的MAR值列表 ear_thresh: EAR阈值低于此值认为眼睛闭合 mar_thresh: MAR阈值高于此值认为嘴巴张开 perclos_thresh: PERCLOS阈值如0.2代表20% 返回: (bool, str): (是否疲劳, 疲劳原因) fatigue False reason # 1. 基于PERCLOS的疲劳判断 eye_closed_frames sum(ear ear_thresh for ear in ear_list) perclos eye_closed_frames / len(ear_list) if perclos perclos_thresh: fatigue True reason fPERCLOS({perclos:.1%})过高 # 2. 基于连续哈欠的判断可选 yawn_frames sum(mar mar_thresh for mar in mar_list) if yawn_frames 3: # 例如在3秒窗口内检测到3次以上大张嘴 fatigue True reason 连续哈欠 # 3. 可以在此添加点头检测的逻辑通过人脸框中心点的移动判断 return fatigue, reason注意上述代码中的calculate_ear和calculate_mar函数是高度简化的。在实际工业级应用中仅靠YOLO的检测框进行比例计算是极不准确的因为头部转动、姿态变化会极大影响框的宽高比。标准的做法是要么1使用YOLOv5检测人脸然后在人脸框内使用一个专用的、轻量级的面部关键点检测模型如Dlib的68点模型或更快的MobileNet改编版来精确定位眼部和嘴部的特征点要么2直接使用支持关键点检测的YOLO变种如YOLOv5-Pose来同时输出框和点。本源码包中的“完整版”通常会集成Dlib或MediaPipe来实现精准的关键点计算。4. 权重文件训练与调优实战指南weights/best.pt这个文件是项目的灵魂它是模型在大量驾驶场景数据上学到的知识结晶。但如果你想让它在你自己的场景比如特定的车型、驾驶员群体、光照条件下表现更好就必须进行微调。4.1 数据准备与标注的魔鬼细节数据收集来源多样性白天、夜晚、隧道、强光、逆光、侧光。驾驶员戴眼镜、戴墨镜、戴口罩、有胡须。正脸、左转、右转、抬头、低头。设备一致性尽量使用与最终部署环境相同的摄像头型号和安装位置采集数据这样可以减少域差异Domain Gap。数据量一个可用的模型至少需要1000-2000张高质量标注图片。要想效果好5000张以上是基础。数据标注工具推荐使用LabelImg或CVAT。类别标签设为face,left_eye,right_eye,mouth。有些方案为了简化只标face和mouth眼睛状态通过关键点判断这取决于你的算法设计。标注规范face框包括整个面部从发际线到下颚两侧到耳朵。eye框紧密包围单只眼睛包括眼睑。mouth框包括整个嘴唇区域。格式YOLOv5要求的是归一化的中心坐标和宽高格式(class_id x_center y_center width_height)每行一个对象一个txt文件对应一张图片。4.2 模型训练的超参数调优心得修改data/custom.yaml指向你的数据集。然后运行训练命令python train.py --img 640 --batch 16 --epochs 100 --data ./data/custom.yaml --cfg ./models/yolov5s.yaml --weights yolov5s.pt --name fatigue_detection几个关键超参数的经验之谈--img 640输入图像尺寸。更大的尺寸如1280能提升对小目标的检测能力如远处的小眼睛但会显著增加计算量和内存消耗。对于车内近距离拍摄640通常足够。--batch 16批次大小。在GPU内存允许的情况下尽可能设大这有助于训练稳定。如果出现CUDA out of memory错误就减小batch或--img。--epochs 100训练轮数。不是越多越好要观察验证集损失val_loss和指标mAP0.5。当损失不再下降甚至上升时过拟合就应该提前停止。--weights yolov5s.pt强烈建议使用预训练权重。这能利用模型在COCO等大型数据集上学到的通用特征加速收敛并提升最终性能。数据增强YOLOv5默认开启了强大的数据增强Mosaic, MixUp等。对于疲劳检测我建议在train.py或相关的配置文件中适当增强以下部分hsv_h,hsv_s,hsv_v调整色调、饱和度、明度模拟不同光照。degrees小幅度的旋转如-5, 5模拟头部倾斜。perspective透视变换模拟摄像头视角变化。谨慎使用flip水平翻转会让左眼变成右眼如果你的逻辑里区分左右眼就需要处理这个对称性问题或者关闭水平翻转。4.3 模型评估与选择训练结束后在runs/train/fatigue_detection/目录下会生成一系列结果文件weights/best.pt验证集上表现最好的权重。weights/last.pt最后一轮的权重。results.png损失和指标曲线图。如何选择通常选择best.pt。但务必使用一个独立的测试集未参与训练和验证的数据进行最终测试。运行python detect.py --weights ./runs/train/fatigue_detection/weights/best.pt --source ./path/to/test_images --save-txt查看在真实场景图片上的检测效果特别是关注漏检眼睛/嘴巴没框出来和误检把方向盘、阴影等误认为目标的情况。5. 多平台部署与性能优化实战训练出一个好模型只是成功了一半把它高效、稳定地跑在目标设备上才是真正的挑战。5.1 部署路径选择Python PyTorch (开发/原型阶段)优点最简单直接使用detect_fatigue.py脚本即可运行。缺点依赖庞大推理速度不是最优。适用快速验证算法效果在PC端演示。ONNX Runtime (跨平台折中选择)将PyTorch模型导出为ONNX格式python export.py --weights ./weights/best.pt --include onnx --img 640 --dynamic然后在C、C#、Python等环境中用ONNX Runtime加载推理。性能比原生PyTorch好且部署环境干净。TensorRT (NVIDIA GPU平台终极优化)这是追求极致性能的必经之路。先将模型转为ONNX再用TensorRT的trtexec工具或Python API生成高度优化的.engine文件。性能提升在Jetson系列或Tesla GPU上相比PyTorch常有数倍甚至十倍的提升。难点需要处理一些不支持的算子调试过程可能较复杂。LibTorch (C环境部署)如果你想用C集成并且不想引入ONNX Runtime的依赖LibTorch是官方选择。它保持了PyTorch的灵活性但需要一定的C工程能力。边缘设备部署 (如RK3568, RV1106)这些设备通常有专门的NPU或AI加速器。流程一般是PyTorch - ONNX - 设备厂商提供的转换工具如RKNN Toolkit - 专属模型格式。关键密切关注厂商提供的文档和社区算子支持度是最大的挑战。你可能需要简化模型结构或使用他们定制化的模型。5.2 性能优化技巧模型层面剪枝与量化使用模型压缩技术。YOLOv5官方支持INT8量化--int8在几乎不损失精度的情况下大幅减少模型体积和提升推理速度。更换更小的模型如果yolov5s还是慢可以考虑更极致的yolov5nnano或者自己裁剪通道数。推理层面多线程/异步处理将视频帧捕获、模型推理、后处理画框、报警放在不同的线程中利用流水线提升整体吞吐量。降低输入分辨率尝试将--img从640降到480甚至320速度会线性提升但需要重新评估精度损失。帧采样对于实时性要求不极致的场景可以每两帧或三帧处理一次用插值或状态保持来弥补中间帧的信息。6. 避坑指南与常见问题排查这里记录了我踩过的最有价值的几个坑问题1模型在训练集上表现很好但在新视频上漏检严重。原因最常见的是域差异。训练数据的光照、背景、摄像头角度与真实环境不符。解决收集真实数据在目标车辆和环境下录制一段视频截取关键帧加入训练集哪怕只有几百张效果立竿见影。增强数据多样性在数据增强中加强色彩抖动和噪声注入让模型对光照变化更鲁棒。调整置信度阈值在推理时降低conf-thres如从0.5降到0.3让模型更“敏感”但同时误检会增加需要权衡。问题2眼睛/嘴巴的框时有时无抖动严重。原因单帧检测的不稳定性。YOLO每帧独立预测受图像噪声、运动模糊影响。解决加入跟踪使用简单的跟踪算法如ByteTrack或DeepSORT为每一帧检测到的目标分配ID。当某一帧漏检时可以用上一帧的位置进行预测平滑轨迹。关键点滤波对计算出的EAR/MAR值进行时间域上的滤波如使用移动平均Moving Average或卡尔曼滤波Kalman Filter平滑掉瞬时抖动。提高模型精度检查训练数据中是否包含模糊、半闭眼的困难样本补充训练。问题3误报率高容易把阴影、水杯等误认为眼睛。原因负样本背景中类似目标不足或特征不够明显。解决增加负样本在标注数据时有意识地截取一些包含类似形状但非目标的区域如方向盘logo、空调出风口并将其类别标记为背景或忽略。调整NMS参数适当提高非极大值抑制的iou-thres让重叠框的合并更严格。后处理规则加入一些简单的逻辑规则例如嘴巴框必须在人脸框的下半部分两只眼睛框的水平位置和大小应该大致对称。违反这些规则的结果可以过滤掉。问题4在嵌入式设备上帧率不达标。原因设备算力有限模型或流程未充分优化。解决量化模型这是提升边缘设备速度最有效的手段之一务必尝试INT8量化。使用硬件加速确保使用了设备的AI加速单元如Jetson的TensorCoreRK3568的NPU而不是跑在CPU上。简化流程评估是否每个计算环节都是必需的。例如如果关键点计算非常耗时可以考虑降低关键点模型的复杂度或减少计算频率如每两帧计算一次关键点。问题5如何评估系统的好坏不能只看mAP。对于疲劳检测系统建议定义更贴合业务的指标疲劳检出率在已知的疲劳视频片段中系统成功报警的比例。误报率/平均误报时间在正常驾驶视频中系统每小时错误报警的次数。报警延迟从疲劳特征出现到系统发出报警的时间差。建立一个包含各种场景的视频测试集人工标注疲劳区间用上述指标进行量化评估。最后这个项目的价值不仅仅在于提供了一个可运行的代码和模型更在于它展示了一个完整的“AI工程化”闭环从问题定义、数据准备、模型训练调优到最后的系统集成、性能优化和问题排查。每个环节都有大量的细节和权衡。希望这份超详细的拆解能让你在复现或改造这个项目时少走弯路更快地构建出属于你自己的、稳定可靠的驾驶员状态监控系统。在实际部署中你可能还需要考虑系统自检、日志记录、远程报警通知等功能那又是另一个层面的工程挑战了。本文还有配套的精品资源点击获取
返回列表