基于YOLOv5的疲劳驾驶检测:从模型训练到实时预警的完整实践
2026/9/23 1:38:47 网站建设 项目流程

简介:本资源是一套完整的基于YOLOv5的疲劳驾驶检测识别毕业设计项目,面向计算机、人工智能及相关专业本科生,解决驾驶员实时状态监测与安全预警的实际问题,适用于毕业设计、课程设计及期末大作业等实践场景。压缩包共93个文件,涵盖31个Python源码(含main.py、train.py、smoke.py等核心模块)、24个YAML配置文件(定义模型结构与训练参数)、2个PT模型文件(best.pt与yolov5s.pt)、2个MP4演示视频、2个Markdown说明文档及配套数据集、Dockerfile、Flask API接口、人脸关键点检测dat模型等,整体大小为136.48MB。已有972人学习下载。项目经导师指导并高分通过(评审97分),包含全部可运行源码、预训练模型、详细使用说明txt、环境配置requirements.txt及实测图像/视频样例,目录结构规范,模块划分清晰,支持一键训练、检测与Web API部署,显著降低毕设开发门槛与调试成本。

1. 项目概述:从毕业设计到实用工具的跨越

最近在整理硬盘时,翻出了一个压箱底的“宝贝”——一个名为“基于yolov5的疲劳驾驶检测识别项目”的完整压缩包。这让我想起了几年前带学生做毕业设计时,为了让他们能快速上手并做出有实际价值的成果,我花了不少心思搭建的这个项目框架。如今,yolov5虽然已不是最前沿的模型,但其在目标检测领域的经典地位、出色的易用性和丰富的社区资源,使其依然是入门计算机视觉、特别是想快速实现一个可演示应用的绝佳选择。这个项目不仅仅是一堆代码和模型文件,它更像是一个精心设计的“脚手架”,旨在帮助学习者避开初期那些令人头疼的坑,直接触及疲劳驾驶检测这个应用场景的核心逻辑。

这个项目能做什么?简单说,它利用摄像头实时捕捉驾驶员的面部图像,通过yolov5模型快速定位眼睛和嘴巴等关键区域,然后基于这些区域的动态特征(如眼睛闭合时长、打哈欠频率)来判断驾驶员是否处于疲劳状态,并发出预警。它解决的不仅仅是“检测到人脸”的问题,更是“如何从人脸中提取有效的疲劳指标”以及“如何设计一个稳定可靠的预警逻辑”这一系列工程问题。无论你是计算机视觉的初学者,想通过一个完整的项目理解从数据到模型的 pipeline;还是相关领域的开发者,需要一个快速验证想法的原型工具;亦或是高校学生,正在寻找一个既有理论深度又有实践价值的毕业设计课题,这个项目都能提供一个扎实的起点。

2. 项目核心思路与技术选型解析

2.1 为什么选择YOLOv5?

在众多目标检测模型中,为这个疲劳驾驶项目选择YOLOv5,是基于多方面的权衡。首先,速度与精度的平衡是核心考量。疲劳检测需要实时或准实时处理视频流,延迟过高就失去了预警意义。YOLO系列一贯以“快”著称,而YOLOv5在继承这一优点的同时,通过引入新的网络结构(如CSPNet、SPP)和更高效的训练策略,在精度上也有不错的表现。对于检测眼睛、嘴巴这类尺寸相对固定、特征明显的目标,YOLOv5的精度完全够用。

其次,极致的易用性是YOLOv5的杀手锏。PyTorch框架的友好性自不必说,YOLOv5项目本身提供了极其清晰的代码结构、详尽的文档和丰富的预训练模型。从数据准备(使用特定格式的标注文件)、模型训练(一行命令或一个脚本)、到模型导出(支持ONNX、TorchScript等多种格式),整个流程都被高度封装和自动化。这对于教学和快速原型开发来说,极大地降低了门槛,学生或开发者可以将精力更多地集中在业务逻辑(疲劳判定算法)上,而不是纠结于模型本身的调试。

最后,活跃的社区生态提供了强大后盾。任何在部署、训练中遇到的问题,几乎都能在GitHub Issues或相关论坛中找到讨论和解决方案。这种“站在巨人肩膀上”的感觉,能让项目推进得更顺利。当然,我们也要认识到,YOLOv5并非没有缺点,例如对小目标、密集目标的检测在某些场景下可能不如一些两阶段检测器,但对于车内相对单一环境下的面部关键点检测,这个缺点并不突出。

2.2 疲劳驾驶检测的逻辑链条设计

一个完整的疲劳驾驶检测系统,远不止“运行一个目标检测模型”那么简单。它是一条环环相扣的逻辑链。我们的项目设计遵循了“检测 -> 追踪 -> 分析 -> 决策”的流程。

第一步是面部与关键点检测。这是整个系统的基石。我们使用YOLOv5模型,其输出不仅仅是“人脸”这个框,更关键的是要能同时输出“左眼”、“右眼”、“嘴巴”等关键区域的坐标。这就要求我们的训练数据必须包含这些细粒度的标注。在模型设计上,我们可能会采用一个多类别的检测头,同时输出人脸、左眼、右眼、嘴巴的边界框和置信度。

第二步是跨帧目标追踪。由于视频是连续的帧序列,单纯对每一帧进行独立检测,会导致目标ID跳变,无法持续计算某个驾驶员的疲劳指标。因此,需要引入简单的追踪算法,如基于IOU(交并比)的关联,或者集成更轻量的追踪器(如DeepSORT的简化版),以确保同一驾驶员的眼睛和嘴巴在连续帧中被正确关联。

第三步是疲劳特征提取与分析。这是算法的“大脑”。对于追踪到的眼睛区域,我们计算其纵横比(Eye Aspect Ratio, EAR),这是一个对眼睛开合程度不敏感的度量。通过连续帧的EAR值,我们可以判断眼睛是否闭合以及闭合的持续时间。对于嘴巴区域,类似地计算其纵横比(Mouth Aspect Ratio, MAR)或高宽比,来检测打哈欠动作。此外,头部姿态估计(如通过面部关键点计算头部偏转角度)也可以作为注意力分散的辅助判断依据。

第四步是疲劳状态决策与预警。这是逻辑的终点。我们不会因为一帧的眨眼就判定为疲劳。通常采用基于时间的状态机或滑动窗口统计。例如,设定一个时间窗口(如2秒),统计窗口内眼睛闭合帧数占总帧数的比例(PERCLOS,一种常用的疲劳度量标准),当该比例超过阈值(如0.2),且可能伴随打哈欠频率过高,则触发“疲劳”状态,并启动声光预警。

注意:阈值(如EAR阈值、PERCLOS阈值)的设定需要根据实际场景数据进行校准。不同人种、光照条件、摄像头角度都会影响这些数值。项目中提供的阈值是一个经验起始值,在实际部署前必须用目标环境的数据进行验证和调整。

3. 项目结构与核心模块详解

3.1 源码目录结构剖析

解压项目压缩包后,你会看到一个清晰的结构,这反映了模块化的设计思想。下面是一个典型的目录树及其功能说明:

fatigue_detection_yolov5/ ├── data/ │ ├── images/ # 存放训练、验证、测试用的图片 │ ├── labels/ # 存放对应图片的YOLO格式标注文件 (.txt) │ └── dataset.yaml # 数据集配置文件,定义路径、类别名等 ├── models/ │ ├── yolov5s.yaml # YOLOv5s网络结构定义文件 │ └── yolov5s_fatigue.pt # 训练好的针对疲劳检测的模型权重(示例) ├── utils/ │ ├── datasets.py # 数据加载与预处理工具 │ ├── general.py # 通用函数(画框、计算IOU等) │ ├── metrics.py # 评估指标计算 │ └── fatigue_utils.py # **核心**:疲劳特征计算与状态判断函数 ├── detect_fatigue.py # **主程序**:实时疲劳检测脚本 ├── train.py # 模型训练脚本 ├── requirements.txt # Python依赖包列表 └── README.md # 项目详细使用说明

关键文件解读:

  1. dataset.yaml:这是数据集的“地图”。它定义了训练集、验证集图片的路径、类别数量以及类别名称列表。例如,我们的类别可能是[‘face’, ‘left_eye’, ‘right_eye’, ‘mouth’]。正确配置这个文件是训练的第一步。
  2. fatigue_utils.py:这是项目的“智慧核心”。它不包含YOLO的检测代码,而是专注于处理YOLO检测后的结果。其主要函数可能包括:
    • calculate_ear(eye_landmarks):根据眼睛的6个关键点坐标计算EAR值。
    • calculate_mar(mouth_landmarks):根据嘴巴的坐标计算MAR值。
    • is_eye_closed(ear, threshold):判断当前帧眼睛是否闭合。
    • fatigue_state_machine(ear_history, mar_history, time_window):基于历史数据,实现疲劳判定的状态机。
  3. detect_fatigue.py:这是应用的“总控制器”。它集成了YOLO检测、追踪、调用fatigue_utils进行分析、以及绘制结果和发出预警的整个流水线。通常,你可以通过命令行参数指定模型路径、摄像头ID、置信度阈值等。

3.2 模型训练与数据准备要点

如果你不想使用项目提供的预训练模型,或者想用自己的数据优化模型,那么训练是必经之路。YOLOv5的训练流程已经非常标准化。

数据准备:你需要收集大量包含驾驶员面部(最好是不同光照、角度、表情)的图片。然后,使用标注工具(如LabelImg、CVAT、Roboflow)进行标注。关键点在于,你需要标注出四个类别:整个人脸框、左眼框、右眼眶、嘴巴框。标注完成后,工具会生成YOLO格式的.txt文件,每行格式为:<class_id> <x_center> <y_center> <width> <height>,坐标是归一化后的值(0-1之间)。

配置文件调整:修改models/yolov5s.yaml中的nc(类别数)为4。在data/dataset.yaml中,正确指向你的imageslabels文件夹路径,并更新names列表。

启动训练:训练命令通常很简单,例如:

python train.py --img 640 --batch 16 --epochs 100 --data ./data/dataset.yaml --cfg ./models/yolov5s.yaml --weights yolov5s.pt --name fatigue_detection
  • --img 640:输入图像尺寸。YOLOv5会自适应缩放,但固定一个尺寸有利于批量处理。
  • --batch 16:批大小。根据你的GPU内存调整,越大训练越快,但需要更多显存。
  • --epochs 100:训练轮数。通常需要观察损失曲线不再明显下降为止。
  • --weights yolov5s.pt:从官方的YOLOv5s预训练权重开始训练,这是非常重要的技巧,能极大加快收敛速度并提升最终性能,这称为迁移学习。
  • --name fatigue_detection:本次训练运行的名称,用于创建保存结果的目录。

实操心得:在训练自己的数据集时,最常见的坑是标注错误。务必仔细检查标注文件,确保边界框紧贴目标,且类别ID正确。可以使用YOLOv5自带的utils.plots模块中的函数,将标注框画回图片上进行检查。另一个关键是学习率,如果从头训练(不加载预训练权重),学习率要设得很小(如1e-3);如果使用预训练权重,可以用稍大的学习率(如1e-2),并在后期衰减。

4. 核心算法:疲劳特征提取与状态判定

4.1 眼睛纵横比与嘴巴纵横比计算

疲劳检测的可靠性,很大程度上取决于特征提取的鲁棒性。我们主要依赖两个几何特征:眼睛纵横比和嘴巴纵横比。

眼睛纵横比(EAR)的计算基于眼睛的6个关键点(在2D图像上,这通常由人脸关键点检测器提供,但在我们这个项目中,我们直接用YOLO检测出的眼睛框来近似。更精确的做法是,在检测到眼睛框后,再用一个小型的关键点网络或传统图像处理来定位眼皮点)。经典的EAR公式是:

EAR = (||p2-p6|| + ||p3-p5||) / (2 * ||p1-p4||)

其中p1...p6是眼睛轮廓上的六个点(从左眼角开始顺时针)。这个比值在眼睛睁开时相对稳定,闭合时会迅速趋近于0。在我们的项目中,如果只有边界框,我们可以用一个简化版本:EAR = height / width。即眼睛区域框的高度除以宽度。当眼睛睁开时,框是扁长的(宽度远大于高度),EAR值小;当眼睛闭合时,框更接近正方形或竖长条(高度相对增加),EAR值会变大。这里需要注意,这个简化方法对头部姿态变化比较敏感,但在正对摄像头的情况下效果尚可。

嘴巴纵横比(MAR)的计算类似,用于检测打哈欠。可以用嘴巴外轮廓的关键点计算,简化版同样可以用检测框的高度/宽度。打哈欠时,嘴巴张大,高度显著增加,MAR值会变大。

fatigue_utils.py中,相应的函数可能如下所示:

def calculate_simple_ear(eye_box): """ 根据眼睛检测框计算简化的EAR值。 eye_box: [x1, y1, x2, y2] 像素坐标 """ width = eye_box[2] - eye_box[0] height = eye_box[3] - eye_box[1] if width == 0: # 避免除零错误 return 0 ear = height / width return ear def is_eye_closed_simple(ear, threshold=0.25): """ 根据简化的EAR值判断眼睛是否闭合。 threshold: 经验阈值,需要根据实际数据调整。 """ return ear > threshold

4.2 基于时序分析的疲劳状态机

单帧的判断毫无意义,疲劳是一个持续的状态。因此,我们需要一个基于时间窗口的状态机。一个简单而有效的设计如下:

  1. 数据缓冲:为每个追踪到的驾驶员维护两个固定长度的队列(或列表),分别存储最近N帧(例如,对应2秒,假设30fps则N=60)的EAR值和MAR值。
  2. 特征统计
    • PERCLOS计算:在EAR队列中,统计EAR值低于“闭合阈值”的帧数,除以总帧数N,得到眼睛闭合时间比例。
    • 打哈欠频率:在MAR队列中,统计MAR值超过“哈欠阈值”的帧数,可以计算单位时间内的打哈欠次数。
  3. 多级预警决策
    • 正常状态:PERCLOS低于阈值P1(如0.1),且打哈欠频率低。
    • 预警状态:PERCLOS超过阈值P1但低于P2(如0.2),或打哈欠频率开始升高。系统可以发出轻度提示(如屏幕闪烁)。
    • 疲劳状态:PERCLOS超过阈值P2,或短时间内打哈欠次数超过阈值。系统触发强预警(如持续蜂鸣声、语音提示)。

这个状态机可以在fatigue_utils.py中用一个类来实现:

class FatigueDetector: def __init__(self, ear_thresh=0.25, perclos_thresh=0.2, time_window=60): self.ear_thresh = ear_thresh self.perclos_thresh = perclos_thresh self.time_window = time_window self.ear_history = [] # 保存历史EAR值 self.fatigue_counter = 0 def update(self, current_ear): self.ear_history.append(current_ear) if len(self.ear_history) > self.time_window: self.ear_history.pop(0) # 保持队列长度固定 # 计算当前窗口内的PERCLOS closed_frames = sum([1 for ear in self.ear_history if ear > self.ear_thresh]) perclos = closed_frames / len(self.ear_history) # 状态判断 if perclos > self.perclos_thresh: self.fatigue_counter += 1 if self.fatigue_counter > 5: # 连续多帧判定为疲劳,避免抖动 return "FATIGUE", perclos else: self.fatigue_counter = max(0, self.fatigue_counter - 1) return "NORMAL", perclos

注意事项:所有阈值(ear_threshperclos_threshtime_window)都不是金科玉律。它们需要在实际部署环境中进行校准。最好的方法是录制一段目标环境下的驾驶员视频(包含清醒和疲劳状态),人工标注出疲劳时间段,然后用程序跑一遍,调整阈值使得程序的判断与人工标注尽可能吻合。这个过程可能有点枯燥,但至关重要。

5. 项目部署与实时检测流程

5.1 环境配置与依赖安装

要让项目跑起来,第一步是搭建Python环境。强烈建议使用Anaconda创建独立的虚拟环境,避免包版本冲突。

# 1. 创建并激活虚拟环境(以conda为例) conda create -n fatigue_yolo python=3.8 conda activate fatigue_yolo # 2. 安装PyTorch(请根据你的CUDA版本到PyTorch官网选择对应命令) # 例如,对于CUDA 11.3: pip install torch==1.12.1+cu113 torchvision==0.13.1+cu113 torchaudio==0.12.1 --extra-index-url https://download.pytorch.org/whl/cu113 # 3. 安装项目依赖 cd path/to/fatigue_detection_yolov5 pip install -r requirements.txt # requirements.txt 通常包含:opencv-python, pandas, seaborn, tqdm, matplotlib, pyyaml等

关键依赖说明:

  • PyTorch:YOLOv5的运行基础。务必选择与你的GPU(如果有)及CUDA版本匹配的安装命令。如果没有GPU,则安装CPU版本。
  • OpenCV:用于图像/视频的读取、显示、预处理和结果绘制。
  • 其他pandas,seaborn等主要用于训练过程中的数据分析与可视化,实时检测脚本可能不需要全部。

5.2 实时检测脚本运行与参数调优

环境准备好后,运行实时检测脚本通常很简单:

python detect_fatigue.py --source 0 --weights ./models/yolov5s_fatigue.pt --conf-thres 0.5
  • --source 0:指定视频源。0代表系统默认摄像头。你也可以传入视频文件路径(如--source ./test.mp4)或图片路径。
  • --weights:指定训练好的模型权重文件路径。
  • --conf-thres 0.5:置信度阈值。只有检测框的置信度高于此值才会被保留。调高它可以减少误检,但可能漏检;调低则相反。

运行后,会弹出一个窗口显示摄像头画面,并在检测到的人脸、眼睛、嘴巴上画框,同时在画面顶部或侧边显示当前的EAR、MAR值和疲劳状态(如“NORMAL”, “WARNING”, “FATIGUE”)。

性能调优实战:

  1. 帧率(FPS)提升:如果感觉卡顿,首先尝试降低推理分辨率。在detect_fatigue.py中,找到加载模型后对图像进行预处理的地方,通常有一个img_size参数。将其从640降低到416或320,可以显著提升速度,但可能会轻微降低小目标的检测精度。
  2. 减少抖动:检测框和状态判断可能会帧间抖动。可以在fatigue_utils.py的状态机中引入“迟滞”机制,如上文代码中的fatigue_counter,只有连续多帧满足条件才切换状态。对于检测框,可以使用简单的移动平均滤波来平滑坐标。
  3. 多线程处理:对于高性能应用,可以考虑将图像采集、模型推理、后处理与UI显示放在不同的线程中,通过队列进行通信,避免因显示或I/O操作阻塞推理。

6. 常见问题排查与实战技巧

6.1 模型训练与评估中的典型问题

问题现象可能原因排查方法与解决方案
训练损失(loss)不下降1. 学习率设置过高或过低。
2. 数据标注存在大量错误。
3. 模型结构或配置文件有误。
1. 尝试使用默认学习率,或使用学习率预热(warmup)和余弦退火(cosine annealing)策略。
2. 使用utils.plots中的plot_labels函数可视化检查标注框是否合理。
3. 检查dataset.yaml中的类别数和models/*.yaml中的nc是否一致。
验证集精度(mAP)很低,但训练集损失正常模型过拟合。1. 增加数据增强(YOLOv5默认已包含较强的增强)。
2. 如果数据集很小,尝试使用更小的模型(如yolov5n)。
3. 加入正则化,如权重衰减(weight decay)。
4. 检查训练集和验证集的数据分布是否差异过大。
模型检测不到目标(漏检)1. 置信度阈值conf-thres设得过高。
2. 训练数据中目标尺寸差异大,模型未学好。
3. 推理图像尺寸与训练尺寸不匹配。
1. 逐步调低conf-thres(如从0.5调到0.25)。
2. 检查数据集中目标框的尺寸分布,确保训练时使用了多尺度训练(YOLOv5默认开启)。
3. 确保推理时输入的图像被缩放到与训练相同的尺寸(如640)。
检测框位置不准1. 标注框不精确。
2. 数据增强过于激进,导致目标变形严重。
1. 重新检查并修正标注数据。
2. 适当减少数据增强的强度,特别是旋转和剪切变换。

6.2 实时检测中的工程挑战与应对

  1. 光照变化:这是车载环境最大的挑战。强烈逆光、隧道明暗交替、夜晚光线不足都会导致检测失败。
    • 应对:在图像预处理阶段加入自适应直方图均衡化对比度受限的自适应直方图均衡化来增强图像。考虑在模型训练数据中尽可能包含各种光照条件的图片。
  2. 遮挡问题:驾驶员可能戴眼镜、墨镜,或者用手托腮,遮挡部分面部。
    • 应对:训练数据中必须包含足够多的遮挡样本。对于墨镜导致的完全遮挡,需要引入其他辅助判断,如头部姿态(是否低垂)或车辆方向盘操作信号(如车道偏离)。
  3. 侧脸与姿态:驾驶员经常转头看后视镜或侧窗。
    • 应对:训练数据需要包含多角度的面部图片。在算法层面,当检测到侧脸时,可以只依赖能看到的单只眼睛进行判断,或暂时降低疲劳判断的权重,主要依赖头部姿态角(如俯仰角过大)进行预警。
  4. 误报与漏报的权衡:过于敏感的系统会频繁误报,干扰驾驶员;过于迟钝的系统则起不到预警作用。
    • 应对:这是一个产品层面的决策。需要通过大量实车路测数据来调整疲劳判定算法的阈值和逻辑。可以考虑引入二级预警机制,一级为轻度提醒(如仪表盘图标闪烁),二级为强烈警告(持续声音)。

6.3 项目扩展与进阶方向

如果你已经成功运行了基础项目,并希望将其深化或用于更实际的场景,这里有几个进阶方向:

  1. 模型轻量化与嵌入式部署:将PyTorch模型转换为ONNX格式,然后利用TensorRT或OpenVINO等工具在Jetson Nano、RK3568等边缘计算设备上加速推理,实现真正的车载嵌入式部署。
  2. 多模态信息融合:单一的视觉信息在极端情况下可能不可靠。可以尝试融合其他传感器数据,例如:
    • 方向盘操作信号:通过CAN总线获取方向盘转角波动频率和幅度。
    • 车辆状态信号:车道偏离预警系统的输出。
    • 生理信号(如果可获取):心率、皮肤电反应等。设计一个基于多传感器数据的融合决策模型(如卡尔曼滤波、简单的加权投票或深度学习融合网络),能显著提升系统的鲁棒性。
  3. 更精细的关键点检测:用YOLO框出眼睛和嘴巴区域后,可以在这些区域内部署一个轻量级的面部关键点检测模型(如MobileNet+回归头),获取更精确的眼角、嘴角坐标,从而计算更稳定的EAR和MAR值,减少对边界框的依赖。
  4. 加入注意力机制:在YOLOv5的主干网络或检测头中引入注意力模块(如SE, CBAM),让模型更关注面部关键区域,提升在复杂背景下的检测精度。

这个基于YOLOv5的疲劳驾驶检测项目,就像一把钥匙,为你打开了计算机视觉应用开发的大门。从数据准备、模型训练、到算法集成和问题调试,它涵盖了一个AI项目从0到1的主要环节。在实际动手的过程中,你遇到的每一个报错、每一次调参、对每一个阈值的纠结,都是比理论更宝贵的经验。我个人的体会是,把项目跑通只是第一步,真正理解每一行代码背后的意图,并能根据实际遇到的新问题去调整和优化它,甚至推翻重来某些部分,才是学习和成长的关键。最后一个小建议,在开始动手前,先花点时间通读一遍README.md和主要的源代码,在脑子里画出整个程序的数据流图,这会让你在后续的调试中事半功倍。

本文还有配套的精品资源,点击获取

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

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

立即咨询