当前位置: 首页 > news >正文

EffRes-DrowsyNet:结合 EfficientNetB0 与 ResNet50 的新型混合深度学习模型用于驾驶员疲劳检测算法实现

主要发现是什么?

  • EffRes-DrowsyNet 是一个集成了 EfficientNetB0 和 ResNet50 的混合深度学习模型,在 SUST-DDD 上实现了 97.71% 的准确率、92.73% 的 YawDD 和 95.14% 的 NTHU-DDD 的高性能。

  • 该模型在不同条件下表现出很强的泛化和可靠性,在所有数据集上保持高精度和召回率。

主要发现的含义是什么?

  • 混合架构在计算效率和深度视觉表示之间提供了有效的平衡,从而支持在驾驶员监控系统中进行实时部署。

  • 它的稳健性和适应性使其成为集成到安全关键应用中的有前途的解决方案,有助于减少汽车和相关领域中疲劳引起的事故。

1. 引言

驾驶员疲劳是全球交通事故的重要诱因,NHTSA 和欧盟数据显示其导致大量事故与伤亡。基于计算机视觉的高级驾驶员监控系统可通过非侵入式手段检测疲劳,而深度学习驱动的视频分析技术为此提供了新路径,如 CNN 结合 LSTM 能有效分析驾驶员面部表情、头部运动等疲劳迹象。本研究提出的 EffRes-DrowsyNet 混合模型,融合 EfficientNetB0 可扩展架构与 ResNet50 残差连接优势,前者能处理不同驾驶环境的视觉数据,后者可捕获细微疲劳特征。

2. 相关研究

各种研究提出了检测驾驶员疲劳和监测注意力的不同标准和解决方案。多年来,已经进行了大量研究来检测嗜睡并提醒驾驶员降低事故率 [15,16]。

在早期阶段识别嗜睡对于预防事故至关重要,通过人工智能实现这一过程的自动化增强了有效且具有成本效益地评估更多病例的能力 [17]。在探索用于眼状态分类的 CNN 模型时,作者开发了一种名为 4D 模型的新型 CNN 模型,该模型通过分析 MRL Eye 数据集中的眼睛状态,在检测嗜睡方面表现出 97.53% 的高精度,优于 VGG16 和 VGG19 等其他预训练模型。

[18] 的作者强调了一种使用最先进的 CNN(包括 InceptionV3、VGG16 和 ResNet50)的实时驾驶员干扰监测方法,其中 ResNet50 模型表现出 93.69% 的最高准确率。该研究利用了一个独特的数据集,其中包括驾驶员的侧视图和前视图,这显著提高了系统检测驾驶员睡意的性能和实时效率。

在 [19] 中,提出了使用面部标志来监测眨眼和打哈欠来检测驾驶员睡意的有效方法,以及采用 MobileNet-V2 和 ResNet-50V2 实时分析驾驶员活动的深度学习技术。利用迁移学习,该研究实现了 97% 的显着准确率,证明了这些方法在增强打瞌睡警报系统和防止驾驶员疲劳造成的事故方面的潜力。

[20] 中的方法表明,为了对抗驾驶员疲劳,研究人员采用了人工智能,特别是 CNN,来分析驾驶员的嘴巴和眼睛的状态,计算闭眼百分比 (PERCLOS) 和打哈欠频率 (FOM) 等特征。这种方法实现了 87.5% 的显着准确率,突显了 AI 在识别和减轻与驾驶员疲劳相关的风险方面的潜力。

[21] 中的研究利用深度学习方法,通过分析从实时摄像机镜头中提取的面部标志来检测驾驶员的困倦,并使用代表不同驾驶条件的 2904 张图像的数据集。该研究通过使用基于特征的级联分类器在实时场景中识别面部特征,实现了 95% 的高准确率,展示了一种有效的驾驶员疲劳持续监测策略。

[22] 的作者介绍了一种结合 2D-CNN 和 LSTM 网络来检测驾驶员疲劳的方法,在 YawDD 数据集上显示出 95% 的显着准确性。通过 2D-CNN-LSTM 网络集成空间和时间数据的有效性凸显了其在汽车安全技术中实际应用的潜力,明显优于几种现有方法。

[23] 的研究采用了集成 CNN 和 Dlib 的 68 个地标性人脸检测器,通过研究闭眼频率和打哈欠等面部线索来分析疲劳驾驶的早期症状。集成 CNN 模型展示了卓越的准确性,与眼睛相关的线索达到 97.4%,与嘴部相关的线索达到 96.5%,表现出优于其他预训练模型的性能,并为将困倦检测系统集成到车辆中以提高驾驶员安全性提供了有前途的解决方案。

[24] 中的研究通过实施基于 Dlib 的面部特征检测算法,采用静态和自适应帧阈值方法,利用闭眼率 (ECR) 和嘴孔比 (MAR) 来评估嗜睡水平,从而推进长途驾驶员的睡意检测。特别是自适应帧阈值方法,可以动态调整表示睡意的连续帧数,达到 98.2% 的显着准确率,从而提高了在实际条件下睡意检测的精度和可靠性。

为了满足对有效的驾驶员睡意检测系统日益增长的需求以提高道路安全,许多研究采用了先进的成像和机器学习技术。表 1 总结了近年来的关键研究,突出了使用各种 CNN 模型检测驾驶员疲劳所取得的不同方法和结果。

与基于视觉的方法相比,[25] 中的研究引入了一种混合模型,该模型利用脑电图 (EEG) 信号进行嗜睡检测,将用于特征优化的快速邻域成分分析 (FNCA) 与用于分类的深度神经网络 (DNN) 相结合。使用 SEED-VIG 数据集和在受控睡眠剥夺下收集的静息态 EEG 数据集对所提出的方法进行了评估,实现了 94.29% 的峰值准确率。通过从神经活动中提取认知特征,该模型有效地识别了嗜睡状态,并在分类准确性和学习效率方面表现出出色的表现。

Table 1. Recent advances in image and video-based driver drowsiness detection systems.

ReferenceYearParameters AnalyzedMethodologyImplementation DetailsAccuracyDataset Used
[26]2020Eye and mouthCNNGeForce GTX 1080 Ti (NVIDIA, Santa Clara, CA, USA); Python 3.5.2 (Python Software Foundation, Wilmington, DE, USA); Keras 2.2.4 (Chollet F., open source)93.62%Driving Image Dataset from Bite Company
[27]2020Eye, head, mouth3D Convolutional NetworksAlienware R17 (Dell, Round Rock, TX, USA); Ubuntu 16.04 LTS (Canonical Ltd., London, UK); 16 GB RAM; 8 GB GPU (Not specified)97.3%NTHU-DDD Public
[28]2020EyeFD-NN, TL-VGG16, TL-VGG19NVIDIA Jetson Nano (NVIDIA, Santa Clara, CA, USA); Near-Infrared camera (Not specified); Custom CNN on Ubuntu (open source)95–98.15%Self-prepared ZJU
[29]2020Eye and mouthMamdani Fuzzy InferenceNot applicable95.5%300-W Dataset
[30]2020EyeMultilayer Perceptron, RF, SVMNot applicable94.9%Self-prepared (DROZY Database)
[31]2020Respiration (thermal camera)SVM, KNNThermal camera recording at 7.5 FPS90%, 83%Self-prepared Thermal Image
[32]2020MouthCold and Hot VoxelsAmbient Temp. Control in Lab and Car71%, 87%Self-prepared
[33]2020Facial features, Head movements3D CNNPython 3.6.1, TensorFlow r1.4, reduced video resolution for training73.9%NTHU-DDD Public
[34]2021MouthCNNNot applicable99.35%YawDD, Nthu-DDD, KouBM-DFD
[35]2021Eye, head, mouthSVMNot applicable79.84%NTHU-DDD Public
[36]2021Eye and faceDeep-CNN EnsemblePython 3.6, Jupyter Notebook, Windows 10, Intel Core i5, 8 GB RAM85%NTHU-DDD Video
[37]2022Eye, head, mouthCNN and SVMNot applicable97.44%Newly Created: YEC, ABD
[38]2022Eye and faceDual CNNNVIDIA Xavier, Intel NCS2; 11-62 FPS performance97.56–98.98%CEW, ZJU, MRL
[39]2022FaceRNN and CNNNot applicable60%UTA-RLDD
[40]2023Eye and faceCNNNot applicable98.53%Self-prepared
[41]2023Eye and mouthDlib’s Haar CascadeDlib Toolkit98%Self-prepared
[42]2023Facial expressions (eyes open, closed, yawning, no yawning)CNN, VGG162900 images including gender, age, head position, illuminationCNN Accuracy 97%; VGG16: 74% AccuracySelf-prepared dataset
[43]2024Face for signs of tirednessResNet50Model trained on Kaggle dataset, test accuracy achieved at epoch 2095.02%, Loss: 0.1349Kaggle (Varied Dataset)

3. 方法

方法工作流程(参见图 1)遵循结构化过程,以准确检测驾驶员的睡意。它首先从驾驶员监控数据集中收集数据,然后对其进行预处理以分析面部特征,例如眼睛和嘴巴运动。接下来,两个深度学习模型(EfficientNetB0 和 ResNet50)从图像中提取重要细节。然后,将这些功能组合和优化以提高准确性。然后,系统会将驾驶员的状态分类为 drowsy 或 alert。最后,如果检测到困倦,输出会触发警告,有助于防止事故和改善道路安全。

图 1.驾驶员睡意检测方法的工作流程图。
3.1. 数据集描述
3.1.1. SUST-DDD 数据集
本节讨论 [ 44] 中引用的所采用的数据集。该数据集被称为 SUST-Driver Drowsiness Dataset,是 Sivas University of Science and Technology 的开源资源。它包括来自 19 名参与者的数据,这些参与者具有不同的年龄和性别特征,主要在夜间和清晨记录,以有效地捕捉他们的嗜睡高峰阶段。
每个视频的分辨率为 224 × 224 像素,被分割成 10 秒的剪辑,标记为“昏昏欲睡”或“警觉”。
3.1.2. YawDD 数据集
YawDD(Yawning Detection Dataset)在IEEE数据端口[ 45]上免费提供,是研究驾驶员疲劳检测的重要资源。该数据集包含来自 60 名参与者的 320 多段视频记录,展示了广泛的人口统计范围,包括性别、年龄和种族。这种多样性对于确保开发的检测模型在不同人群和条件下有效执行至关重要。
该数据集经过深思熟虑地分为两个子集:Driver Set(在模拟室内环境中包含 226 个视频)和 InCar Set(在真实驾驶条件下捕获 94 个视频)。这种设置使研究人员能够在受控环境中改进检测算法,然后再评估它们在更多变化的真实场景中的有效性。数据集中的每个视频都针对打哈欠和其他与睡意相关的面部表情实例进行了细致的注释,为高精度训练机器学习模型提供了详细的数据。视频长度的变化进一步促进了疲劳的短期和长期指标的研究,支持综合预测模型的开发。
选择使用 YawDD 是由于其可访问性和数据深度,这不仅有助于开发复杂的算法,还允许在模拟和实际条件下对这些模型进行基准测试。将这些模型集成到高级驾驶辅助系统 (ADAS) 中,可以通过减轻与疲劳相关的事故来显着提高道路安全性。因此,YawDD 数据集是推进驾驶员疲劳检测和改进汽车行业安全措施研究的宝贵资产。
3.1.3. NTHU-DDD 数据集
NTHU驾驶员睡意检测(NTHU-DDD)数据集[ 46]由国立清华大学开发,是一个公开可用的视频数据集,旨在评估基于视觉的驾驶员睡意检测系统。它包括 36 个对象在各种真实驾驶条件下的记录,包括不同的照明环境(白天、有和没有机舱照明的夜晚)和各种外观,例如戴眼镜和太阳镜的受试者。这种多样性增强了数据集对实际场景的适用性。
每个视频序列都标注了与睡意检测相关的六种预定义状态之一:正常、打哈欠、说话、慢速眨眼、闭眼和睡眠。这些注释支持二进制分类 (alert vs. drowsy) 和多类检测框架。视频以 640 × 480 像素的分辨率和每秒 30 帧的帧速率录制,提供 RGB 和灰度版本。
该数据集因其全面的标注、主题可变性和对真实驾驶员行为的模拟而在学术界得到广泛应用。它是在驾驶员状态监控领域开发和验证机器学习和深度学习模型的强大基准。
3.2. 数据预处理和增强
3.2.1. 用于嗜睡和非嗜睡的面部特征点检测
在我们的研究中,我们采用了 Dlib 基于定向梯度直方图 (HOG) 的人脸检测和 68 点面部特征点预测模型来分析来自 SUST-DDD 和 YawDD 数据集的视频帧。选择 Dlib 基于 HOG 的检测器是基于其在不同照明条件和面部方向下的稳健性能,这对于这些数据集中的不同环境设置至关重要。该检测器在受控和动态场景中都表现出色,使其非常适合我们的分析。
此外,我们利用 68 点面部特征预测器精确检测计算眼睛纵横比 (EAR) 和嘴部纵横比 (MAR) 所需的关键面部点。这些指标对于量化嗜睡指标(例如闭眼和嘴巴运动)至关重要。这种具有里程碑意义的检测精度对于我们的疲劳评估的准确性和可靠性至关重要,确保我们的方法符合严格的学术标准,并适用于增强现实世界的嗜睡检测系统,如图 2 所示。
图 2.使用 Dlib 识别面部标志。( a) 面部特征点。( b) 面部 68 个点的位置和顺序 [ 47]。
3.2.2. 纵横比计算
我们计算了有助于检测关键疲劳相关行为的特定指标:
  • 眼睛纵横比 (EAR)
计算 EAR 以确定眼睛是睁开还是闭着。这对于检测嗜睡至关重要。计算眼睛纵横比 (EAR) 以量化垂直眼睛闭合,这是驾驶员嗜睡的重要指标。EAR 使用公式 (1) 计算如下 [ 48]:

同样,右眼 EAR 由公式 (2) 给出,如下所示:

 在这种方法中,根据每个视频的独特数据动态计算每个视频的眼睛纵横比 (EAR) 阈值,从而提高睡意检测的精度。如果 EAR 低于此自适应阈值,则表示闭眼,表明嗜睡;高于阈值的值表示睁开眼睛。此方法可确保检测适应单个视频中的变化,从而提高分析的可靠性。

  • 嘴部纵横比 (MAR)
嘴部纵横比 (MAR) 用于检测一个人是否打哈欠 [49]。EAR 使用公式 (3) 计算,如下所示:

与 EAR 类似,嘴部纵横比 (MAR) 是使用特定嘴部特征点之间的垂直和水平距离计算的。此比率是针对每个视频动态确定的,从而提高了检测准确性。如果 MAR 超过自适应阈值,则检测到打哈欠,表明可能存在嗜睡。低于阈值的值表示没有打哈欠。此方法适用于单个视频的变化,确保可靠和精确的哈欠检测。

3.2.3. 驾驶员睡意检测中的特征融合和特征点精度

由于 EffRes-DrowsyNet 采用混合方法,将手工制作的视觉特征(特别是 EAR 和 MAR)与 EfficientNetB0 和 ResNet50 提取的深度特征相结合,因此该模型受益于低级几何线索和高级语义表示,提高了其在不同照明和面部条件下检测睡意的可靠性。

EAR 和 MAR 的有效性取决于关键面部标志的准确定位。在这项工作中,由于 Dlib 68 点模型在正面面部分析中的可靠性而被采用。但是,在实际条件下,例如头部姿势变化、遮挡(例如眼镜、手势)和可变照明,特征点的准确性可能会降低。这些因素可能会扭曲 EAR 和 MAR 计算,从而导致错误的分类。

为了减轻此类风险,我们采用了以下策略:

  • 应用面部对齐以标准化方向和缩放。

  • 感兴趣区域 (ROI) 提取将注意力集中在眼睛和嘴巴区域。

  • 对连续帧的平均 EAR 和 MAR 值进行时间平滑处理,以减少瞬态噪声和自然闪烁的影响。

重要的是,该模型不会根据孤立的帧级变化对困倦进行分类。相反,它会随着时间的推移学习行为模式,例如持续闭眼或反复打哈欠。这些时间描述符与深度视觉特征融合,形成最终分类的统一表示。这种方法允许模型区分典型的闪烁和疲劳诱发状态。

虽然当前方法提高了稳健性,但持续的特征点不准确仍可能影响性能。作为未来工作的一部分,我们计划探索基于置信度的关键点过滤和完全端到端的架构,以减少对显式地标测量的依赖,同时保持行为可解释性。

3.2.4. 帧预处理

为了准备用于分析的人脸区域,视频帧经历了几个预处理步骤,如图 3 所示。

图 3.说明用于睡意检测的自动视频处理管道的工作流程图。
首先,边界框用于检测和裁剪人脸。然后,将提取的人脸大小调整为 224 × 224 像素,并转换为灰度,以确保照明条件一致。为了进一步提高能见度,应用了CLAHE(对比度受限自适应直方图均衡)[ 50],这有助于标准化照明变化。最后,像素值在 0 到 1 之间缩放,确保下一阶段处理的标准化输入。
3.2.5. 视频处理和事件检测
对视频进行了逐帧分析,并使用 EAR 和 MAR 来检测特定事件。
  • 嗜睡视频处理:
如果 EAR 低于定义的阈值,则认为眼睛是闭着的。在这个阶段,处理了 dsleepiness 数据集中的所有视频文件,检测了闭眼和打哈欠的事件。保存每个视频的目标帧。 图 4 说明了检测到的睡意帧的样本。

图 4.从视频数据集中提取的嗜睡输出帧样本。
  • 非嗜睡视频处理:
如果 EAR 超过阈值,则认为眼睛睁开,表明受试者没有困倦。对非嗜睡数据集进行处理以检测睁开眼睛和非打哈欠状态并保存相应的帧。图 5 说明了检测到的非睡意帧的样本。

图 5.从视频数据集中提取的非嗜睡输出帧样本。
      这两种互补的算法代表了预处理管道中基于面部线索检测困倦和警觉状态的初始步骤。这些算法可以有效地分析视频帧,以检测疲劳迹象,例如闭眼和打哈欠,以及警觉性指标,例如睁开眼睛和没有打哈欠。通过处理昏昏欲睡的视频和非昏昏欲睡的视频数据集,算法会提取突出这些行为的相关帧。此预处理阶段对于驾驶员睡意检测和实时安全监控系统等应用中的进一步分析至关重要。这项基础工作为更深入的分析和集成到更广泛的系统中奠定了基础,旨在加强安全和性能监控,如图 3 所示。
      视频流中的嗜睡和警觉性自动检测算法采用一系列计算步骤来评估视频输入的警觉性和嗜睡状态。图 4 说明了此过程的综合工作流程,利用先进的面部检测和图像处理技术来分析实时视频流。在此可视化概述之后,表 2 简洁地总结了算法的基本步骤,详细介绍了检测系统的初始化、检测指标的配置以及所涉及的处理例程。这种结构化方法可确保算法系统地识别和分类与用户状态相关的视觉线索,从而促进在不同环境中进行稳健可靠的评估。
表 2.自动检测嗜睡和警觉性算法步骤的摘要。
Algorithm 1: Frame Count Normalization For Video Datasets
Input:
Input directory containing video frame folders, output directory, and desired number of frames per video.
Initialize Categories: Check and create the output directory if it does not exist.
Process:
For Each Video Directory in the Input Directory:
  • Retrieve and Sort Frames:

    Collect all .jpg frames from the current video directory and sort them to maintain temporal order.

  • Check Frame Availability:

    If no frames are present, log the issue and proceed to the next video directory.

  • Adjust Frame Count:

    Excess Frames:

    If the number of frames exceeds the target, select frames evenly using linear interpolation.

    Insufficient Frames:

    If the number of frames is less than the target, replicate existing frames systematically until the target count is reached.

    Save Processed Frames:

    Store the selected or replicated frames in a new subdirectory within the output directory.

Output:
Indicate successful normalization of frame counts for all processed directories.
End Algorithm

图 6 显示了确保每个视频序列包含统一数量的帧以实现机器学习模型的一致输入的系统方法,包括帧评估、选择或复制以及系统存储。

图 6.描述在视频序列中标准化帧计数的过程的流程图。
将视频数据自动组织成不同的训练、验证和测试集是开发和评估机器学习模型的关键初始步骤。此过程首先验证指定源目录中是否存在分类目录,例如“Drowsiness”和“Not Drowsiness”。系统地处理每个类别,以枚举所有包含的目录,表示各个数据点。然后,这些目录被随机分配,以确保均衡分布——70%分配给训练集,其余30%在验证集和测试集之间平均分配[51]。这种细致的准备对于无偏见的模型训练至关重要,如图 7 所示。这种结构化方法不仅简化了数据设置,还提高了后续模型训练和验证任务的效率。

图 7.数据切分过程的流程图。
3.3. 模型架构和配置
在本节中,我们将讨论混合模型的架构,该模型利用两个最先进的预训练模型 EfficientNetB0 [ 52] 和 ResNet50 [ 53] 来提高性能。该架构侧重于从这些强大的模型中提取特征,将它们连接起来,并应用正则化以减少过度拟合。
3.3.1. 单个模型
组织框架由两个 CNN 组成,包括 EfficientNetB0 和 ResNet50。这两个网络都在 ImageNet 数据集上进行了预训练。这些网络是根据以前的图像分类文档选择的。
EfficientNet 是不同模型的名称,这些模型旨在以最少的计算量实现高精度。它是一个优化的轻量级模型,作为特征提取器具有出色的性能。模型的深度、厚度和分辨率尺度都是均匀缩放的,使其适用于在可接受的计算范围内的图片分类任务。
ResNet,又称残差网络(Residual Networks),其特点是包含残差连接的深度架构,经过专业化处理,消除了梯度消失问题,从而辅助了非常深的网络。ResNet50 是一个 50 层架构模型,在从图像中提取深层分层特征时特别高效。
混合模型利用了两个预训练架构(EfficientNetB0 和 ResNet50)的卷积基础,其中完全连接的顶层被排除在外(包括 top = False)。这些基础在 ImageNet 数据集上进行了预训练,基本上捕获了一般的视觉特征,例如边缘、纹理和图案。从两个模型中提取的特征被连接起来,从而能够融合互补表示以提高下游任务性能。
3.3.2. 特征连接和正则化
从两个模型中提取特征后,EfficientNetB0 和 ResNet50 的输出通过全局平均池化层以减小其空间维度。这个过程将高维特征图压缩为保留关键信息的低维特征向量。
然后将生成的向量连接起来,创建一个统一的表示,利用 EfficientNetB0 的计算效率和 ResNet50 的深度特征提取能力。为了提高训练稳定性并减轻内部协变量偏移,应用了批量归一化。随后是 dropout 层 (rate = 0.3) 以减少过拟合并提高泛化。
接下来,使用具有 256 个单元和 L2 正则化的密集层来优化组合特征,同时惩罚过大的权重。最后,sigmoid 激活的输出层执行二元分类,预测驾驶员是昏昏欲睡还是警觉。整体混合架构如图  8 所示。

图 8.统一的参考模型显示了在提议的 EffRes-DrowsyNet 框架中将手工制作的基于 EAR/MAR 的行为线索与双流 CNN 架构 (EfficientNetB0 + ResNet50) 的集成。
为了提高模型的可解释性和有效性,我们开发了一个混合渠道,将传统行为线索与基于深度学习的可视化分析相结合。如图  8 所示,我们的方法首先从使用 Dlib 检测到的面部标志中提取 EAR 和 MAR。这些功能用作驾驶员睡意的关键指标,例如闭眼和打哈欠,并用于根据预定义的阈值选择性地标记帧。然后将标记的图像传递给双流卷积模型 EfficientNetB0 和 ResNet50,每个模型都在 ImageNet 上进行预训练,以提取稳健的空间特征。全局平均池化应用于两个特征图,并将生成的向量连接起来以形成统一的表示。这种混合架构使模型能够从特定领域的手动特征和深度视觉模式中学习,最终提高各种真实场景中睡意检测的准确性和可靠性。
3.3.3. 模型架构
所提出的模型架构使用 EfficientNetB0 和 ResNet50 作为特征生成器,去除它们的分类层并仅保留特征提取组件。这些网络经过预先训练,对图像分类有效,其提取的特征在更广泛的系统中用于进一步处理。提取的特征随后被整合并经过额外的层,以进一步优化目标任务的浓度:
特征处理。在特征的串联过程中,执行了全局平均值的池化以最小化空间维度,并添加了批量归一化和 dropout 层以防止过度拟合并提高泛化能力。
密集层和正则化。通过 L2 密集层正则化将多个特征集中并压缩为所需的大小,从而实现二进制分类。
Output Layer (输出图层)。最后一层(即输出前面的层)是一个密集层,具有 sigmoid 激活函数,为目标类提供概率分数。
此架构旨在有效地利用预训练模型中捕获的一般图像表示,而添加的层使模型能够学习二元分类的特定任务详细信息。
3.3.4. 编译和训练
该模型使用 Adam 优化器进行编译,该优化器因其自适应学习率而被选中,该优化器通过动态调整每个参数的学习率来加速收敛。二元交叉熵用作损失函数,适用于二元分类任务,因为它测量预测概率与真实类标签之间的差异。在整个训练过程中,使用准确率、精度和召回率指标评估模型性能,从而提供其预测质量的全面视图。
为了增强训练过程,实现了四个回调函数。因此,EarlyStopping 监控验证损失,在改进停止时停止训练,并恢复最佳模型状态以避免过度拟合。此外,当验证损失趋于平稳时,ReduceLROnPlateau 会降低学习率,从而促进模型的持续细化。ModelCheckpoin 以最高的验证精度保存模型,确保保留最佳版本以供部署。TensorBoard 可视化训练进度,提供对损失和准确率指标演变的见解,帮助识别过度拟合或停滞。
3.3.5. 微调策略
训练的一个重要阶段是微调,因为它使模型能够正确使用预先训练的权重。最初,该模式是冻结 EfficientNetB0 和 ResNet50 的前一百层,这些分类器基于 ImageNet 特征构建,被确定为有用。使用这种方法,较低层会丢弃与任务无关的基本特征,而较高层则专门处理目标数据集的特征。在新的顶层上进行训练后,它们自己的层将逐步解冻,并且整个模型再次以较低的学习率进行训练,以确保仅对任务进行微小的更改,同时保留预训练模型中的有用特征。
3.3.6. 数据准备和扩充
数据预处理和增强是模型增强不可或缺的一部分。为了实现此目标,应用 ImageDataGenerator 类通过执行多种转换(例如旋转、剪切、移位、缩放、水平翻转和重新缩放像素值)来执行动态数据增强,从而提供变化。这些增强有助于改进训练数据,并使模型能够在新数据和未公开的数据上表现良好。
3.3.7. 训练执行和评估
对于一定数量的 epoch,使用为训练集和验证集指定的批量大小系统地训练模型。数据生成器简化了数据馈送过程,允许高效利用内存和计算资源。训练后,模型在单独的测试数据集上进行严格评估,以评估其实际适用性。这种训练后评估提供了对模型的有效性和潜在局限性的关键见解,确保它满足预期应用程序所需的性能标准。
3.3.8. 实现概述
TensorFlow 和 Keras 用于实现拟议的混合模型,Keras 作为高级 API 来支持模块化和灵活的模型构建。这种全面的训练、架构和实施策略集成了高效的特征提取、有针对性的正则化、自适应微调和详细评估,以开发能够解决计算机视觉中复杂图像分类挑战的高性能模型。以下伪代码(算法 2)系统地概述了整个过程,其中详细介绍了从数据准备到最终模型评估的每个阶段。
Algorithm 2: EffRes-DrowsyNet—Hybrid Drowsiness Detection Model 
Input:
  • Video stream V
  • EAR threshold 𝑻𝒆𝒚𝒆Teye
  • MAR threshold 𝑻𝒎𝒐𝒖𝒕𝒉Tmouth
  • Pretrained models: EfficientNetB0, ResNet50
  • Max_Epochs = N, Batch_Size = B
Output:
  • Predicted label: Drowsy/Not Drowsy
Process:

(1)

Preprocessing and Labeling:

For each frame F in video V:
  • Detect face using Dlib HOG detector
  • Predict 68 facial landmarks
  • Compute EAR and MAR
  • Label

    If EAR < 𝑻𝒆𝒚𝒆< Teye: Eyes = Closed

    Else: Eyes = Open

    If MAR > 𝑻𝒎𝒐𝒖𝒕𝒉> Tmouth: Mouth = Yawning

    Else: Mouth = Not Yawning
  • Assign final frame F label:

    If Eyes = Closed or Mouth = Yawning: Label = Drowsy

    Else: Label = Not Drowsy

(2)

Data Preparation

Convert all labeled frames to grayscale (224 × 224)

Apply data augmentation: brightness shift, rotation, flipping, etc.

Split dataset into training, validation, and test sets

(3)

Hybrid CNN Model Construction (EffRes-DrowsyNet) 

Input: Grayscale image I ∈ 𝑅224×224×1I ∈ R224×224×1

EfficientPath ← EfficientNetB0 (Replicated as 3 channels)

ResNetPath ← ResNet50 (Replicated as 3 channels)

FeatureEffNet ← GlobalAveragePooling(EfficientPath)   // Output: 1280-D

FeatureResNet ← GlobalAveragePooling(ResNetPath)    // Output: 2048-D

FeatureVector ← Concatenate(FeatureEffNet, FeatureResNet) // 3328-D

x ← BatchNormalization(FeatureVector)

x ← Dropout (x, rate = 0.3)

x ← Dense (x, units = 256, activation = ‘ReLU’, regularizer = L2)

Output ← Dense (x, units = 1, activation = ‘Sigmoid’)

(4)

Training Phase 

Compile model with Binary Cross-Entropy loss and Adam optimizer

Train model for max N epochs or until early stopping triggers

Monitor validation loss for learning rate reduction and overfitting

(5)

Inference 

For each test video:
  • Preprocess as above
  • Pass through the trained model
  • Predict label = Drowsy or Not Drowsy based on sigmoid threshold
End Algorithm

4. 结果与讨论

在本节中,我们将评估通过集成两个著名的 CNN 架构 EfficientNetB0 和 ResNet50 开发的新型混合深度学习模型的性能。这种方法背后的主要动机是利用两种架构的不同功能和优势来提高模型在二元分类设置中泛化和准确分类图像的能力。这些模型的组合旨在捕获从基本模式到复杂模式的广泛特征,从而提高模型在复杂数据集上的预测性能。
4.1. EFFRES-DrowsyNet 在 SUST-DDD 数据集上不同训练 epoch 的性能评估
本节详细分析了使用 SUST-DDD 数据集 [ 44] 在不同训练时期从模型配置中获得的实验结果。这些实验的目的是研究模型在不同时期数下的性能,同时在某些情况下纳入提前停止。使用四个主要指标评估性能:测试准确性、测试精度、测试召回率和测试损失。此分析的目标是比较不同训练持续时间对模型有效性的影响,并确定最稳健的实验设置以实现最佳性能。
表 3 说明了模型在不同实验设置下的性能,不同的训练 epoch 数量。显示的结果对应于模型的不同执行,每个执行都配置了唯一的停止标准或纪元总数。该表提供了有关训练持续时间如何影响关键性能指标的见解:测试准确性、测试精度、测试召回率和测试损失。
表 3.SUST-DDD 数据集上不同实验执行的不同训练时期的性能指标。
Experiment NumberEpochsTest AccuracyTest PrecisionTest RecallTest Loss
11093.67%96.87%90.25%0.2103
22095.42%96.66%94.08%0.1322
33096.96%97.47%96.52%0.0847
440 Early stopping at Epoch 2597.71%98.07%97.33%0.0881
55097.29%96.40%98.25%0.0876
66097.29%97.25%97.33%0.0850
770 Early stopping at Epoch 3697.46%97.03%97.92%0.0838
880 Early stopping at Epoch 3297.33%98.22%96.42%0.0901
99095.92%94.87%97.08%0.1255
10100 Early stopping at Epoch 2296.83%95.69%98.08%0.1347

图 9 描述了在 10 个不同的实验设置中,不同训练时期对关键性能指标(准确度、精密度、召回率和损失)的影响。

图 9.跨训练时期评估新型混合模型的性能。
此条形图精确量化了不同训练期对模型性能的影响,由测试准确率、精度、召回率和损失等指标表示。该数据集包含 10 个实验的结果,每个实验都采用特定数量的训练 epoch,范围从 10 到 100。这些实验中的许多实验都结合了早期停止标准,以优化训练过程并降低过拟合的风险。准确度、精密度和召回率等指标以百分比形式与主 y 轴作成关系图,而损失则在辅助 y 轴上测量,以保持量表完整性并提高可解释性。每个指标的条形正上方都标有垂直标签,确保可以轻松访问精确值以进行详细分析。这种图形表示对于突出训练持续时间和模型效能之间的关系非常重要,可以深入了解平衡模型准确性和计算效率的最佳训练策略。该图表支持对在实际部署场景中增强模型性能的有效训练方法的讨论。
4.1.1. 最优纪元和泛化
虽然深度学习模型通常会随着训练周期的增加而提高准确性,但我们的重点是确定最佳停止点,以平衡性能与计算效率。如 表 3 所示,实验 4 在 25 个时期应用提前停止,实现了最高的指标——97.71% 的准确率、98.07% 的准确率和 97.33% 的召回率——而测试损失最小 (0.0881)。这表明该模型在相对较短的训练窗口内有效地学习了睡意检测的相关特征,避免了不必要的计算成本。
这一结果对于实时应用(如车载驾驶员监控系统)尤为重要,在这些应用中,快速收敛和最小过拟合是必不可少的。超过 30 个时期的实验表明,泛化性仅略有改善甚至略有退化(反映在损失增加上),这加强了早期停止作为一种实际训练策略的有效性。
4.1.2. Early Stopping 的影响
事实证明,使用提前停止对于确定模型在不过度拟合的情况下最泛化的点至关重要。在所有实验中,实验 4 不仅产生了最高的准确性和精密度,而且与其他配置相比,它以更少的训练 epoch 实现了这一目标。其他提前停止情况(实验 7、8 和 10)也显示出较好的结果,但未超过实验 4 的平衡性能。
这表明,超过某个点后,额外的训练会提供递减的回报,并且可能会对模型性能产生负面影响。以更少的时期实现最佳准确性的能力证明了所提出的 EffRes-DrowsyNet 模型的实际效率,使其非常适合部署在速度和准确性都至关重要的实时睡意检测系统中。
4.1.3. 长时间训练的效果
探索了延长的训练持续时间(实验 5 到 9),以了解它们对模型泛化和保持精度和召回能力的影响。值得注意的是,虽然多达 60 个时期的实验保持了较低的损失率,但实验 9 和 10 的测试损失增加,同时精度和准确度也出现了波动。
实验 9(90 个 epoch)导致更高的损失 (0.1255),精度降低 (94.87%),这表明过多的 epoch 会导致模型过度拟合训练数据,从而对其在新的、看不见的数据上的性能产生不利影响。
4.1.4. 精度-召回率权衡
实时应用预测性能的一个关键方面是精确率和召回率之间的平衡,尤其是在驾驶员睡意检测等安全关键系统中,其中假阴性和假阳性都会产生严重影响。
实验 4 以最佳方式概括了训练数据,如其在准确率、精度、召回率和损失方面的平衡指标所示。这表明该模型既没有过拟合也没有欠拟合。实验 4 还展示了精确率和召回率之间的出色平衡,这对于最大限度地减少实时检测中的假阳性和假阴性至关重要。
相同的实验实现了最高的准确性,这对于决策必须准确和及时的可靠实时应用程序至关重要。与具有较高纪元的实验不同,实验 4 避免了过拟合的陷阱,正如其适度的测试损失所表明的那样,它不会牺牲精度或召回率。
综合分析,建议将实验 4 作为实时驾驶员睡意检测系统的最佳配置。该实验不仅提供了最高的准确度、精密度和召回率测量方法,还展示了在 25 个 epoch 处提前停止的有效使用,以最大限度地提高性能而不会过度拟合。早期停止策略可确保模型足够稳健,可以很好地概括看不见的数据,这是实时系统可靠性的关键要求。该实验有效地平衡了对快速、准确检测和计算效率的需求,使其成为在安全关键应用中部署的最佳选择。
4.1.5. SUST-DDD 数据集模型训练(40 个 epoch,提前停止在 epoch 25)的性能分析
在本节中,我们详细分析了模型在初始训练阶段(Epochs 1-25)的性能。这个阶段是必不可少的,因为它封装了模型的早期学习动态,包括其调整权重和优化其预测能力的能力。该分析分为关键的子阶段,以便对模型如何随时间演变和优化有细致的理解。
  • 训练动力学和模型优化
  • 初始学习阶段
训练以 4.5076 的显着初始损失开始,随着 epoch 的进行,该损失迅速下降。到第一个 epoch 结束时,该模型实现了 75.66% 的训练准确率,准确率为 74.68%,召回率为 77.63%。验证准确率大幅提高至 89.25%,表明该模型正在有效地学习可泛化特征。
  • 训练中期调整
到第 6 个 epoch 时,所有性能指标都有了显著的改进,验证准确率达到 93.12% 的峰值。此阶段标志着模型在训练过程中的最高泛化性能。尽管在随后的 epoch 中验证指标出现波动,但这个峰值展示了训练模型在最佳条件下的潜力。
  • 学习率降低
在第 20 个 epoch 之后,学习率从 0.0001 降低到 0.00001,作为改进模型在损失环境中收敛到更精确最小值的能力的策略的一部分。此调整旨在通过允许对模型权重进行更精细的更新来提高精度和召回率。
  • 收敛和提前停止
由于验证准确性没有提高,训练过程在第 25 个 epoch 自动停止,这调用了提前停止机制。该决定的指导是模型无法超过之前设定的 93.54% 的验证准确率阈值,从而防止不必要的计算和潜在的过拟合。
最终测试结果证明了模型的鲁棒性,准确率达到 97.71%,精密度达到 98.07%,召回率达到 97.33%。这些指标证实,该模型不仅在训练期间捕获了基本特征,而且还有效地推广到看不见的数据。
图 10 显示了模型训练过程的全面可视化,展示了损失、准确率、精度和召回率在训练时期的演变。子图 (a) 显示训练损失持续减少,验证损失普遍呈下降趋势,只有很小的波动,表明学习稳定和泛化良好。子图 (b) 说明了训练集和验证集的准确性呈上升趋势,突出了该模型随着时间的推移正确分类样本的能力不断增强。

图 10.SUST-DDD 数据集上 epoch 的训练和验证指标:( a) 损失,( b) 准确性,( c) 精度,( d) 召回率。
子图 (c) 和 (d) 分别显示训练和验证精度和召回率。这两个指标相辅相成:精度反映了模型减少误报的能力,而召回率则表示它成功识别了真阳性。它们同时改进和最终稳定意味着一个平衡良好的模型,具有最小的过拟合和很强的泛化。
4.1.6. 最终模型评估
结论性的测试评估为该模型的有效性提供了强有力的证据。为此,97.71% 的测试准确率证明了该模型在正确分类图像方面的高可靠性。98.07% 的精度值表示假阳性率非常低,这对于精度至关重要的应用至关重要。召回率为 97.33%,这表明该模型在识别几乎所有积极实例方面具有优势,这对于敏感应用程序至关重要。损失为 8.81%,反映了模型预测中的低错误率,证实了其整体预测质量。
这些指标突出了模型在对看不见的数据进行分类方面的精度和可靠性,具有非常高的真阳性率和较低的假阳性率。
4.1.7. 关键要点
学习效率。损失的初始快速降低和准确率的快速提高证明了该模型的有效学习能力,这可能是由于 EfficientNetB0 和 ResNet50 架构的有效集成。
泛化能力。始终如一的高验证和测试指标表明,该模型在类似任务中具有良好的泛化能力,使其适用于准确性和可靠性至关重要的实际应用程序。
优化和过拟合。使用 ReduceLROnPlateau 和提前停止等回调有助于微调学习过程并防止过拟合,后期 epoch 中验证指标的稳定证明了这一点。
总之,该模型在二元分类任务中表现出出色的性能,以详细和有条不紊的训练阶段为基础,优化了其很好地泛化到新数据的能力。该模型的稳健性通过高精度和召回率得到验证,使其成为在需要精确图像分类的领域中实际部署的有力工具。
4.2. EFFRES-DrowsyNet 在 YawDD 数据集上不同训练时期的性能评估
本节批判性地评估了 EFFRES-DrowsyNet 模型的性能,通过使用 YawDD 数据集 [ 45] 的一系列 10 个离散实验,采用结构化方法。每个标记为 EX1 到 EX10 的实验都经过精心进行,使用一组增量训练 epoch,范围从 10 到 100。这项分析工作的目的是分析不同训练持续时间对模型整体效能的影响,特别是检查关键指标,例如测试准确性、测试精度、测试召回率和测试损失。
4.2.1. 实验概述和方法
EFFRES-DrowsyNet 在 10 个独立实验中进行了严格的测试,每个实验都定制了特定数量的训练 epoch,以确定模型训练的最佳持续时间。这种系统化的方法允许全面记录性能指标,从而提供模型预测准确性和运营效率的精细视图。为了对抗潜在的过拟合,在几个实验中实施了提前停止,当没有检测到验证损失的显着改善时,有效地停止训练,从而保护模型免受泛化能力的削弱。
4.2.2. 详细结果和分析
表 4 和图 11 记录了每个实验的性能,其中突出了训练持续时间和各种性能指标之间的关系。结果描绘了随着训练时期的增加,模型行为的清晰轨迹,为模型训练和性能优化的动态提供了有价值的见解。
图 11.YawDD 数据集上 EFFRES-DrowsyNet 在不同训练时期的性能指标。
表 4.YawDD 数据集上 EFFRES-DrowsyNet 在不同训练时期的性能指标。
Experiment NumberEpochsTest AccuracyTest PrecisionTest RecallTest Loss
11088.75%95.64%74.6%1.2149
22090.39%86.32%89.6%0.3699
33092.5%93.72%86.6%0.3614
44090.39%92.17%0.824%0.452
550 (Early stopping at 42)89.06%88.63%0.826%0.4043
660 (Early stopping at 31)91.02%89.86%0.8685%0.4166
770 (Early stopping at 38)92.73%93.02%0.88%0.2905
880 (Early stopping at 42)90.7%90.45%0.852%0.3696
990 (Early stopping at 38)90.94%91.74%0.844%0.2543
10100 (Early stopping at 37)89.3%90.6%0.81%0.3671

实验 1 到实验 4 显示准确率和精密度的逐渐提高,这表明训练持续时间的初始增量大大增强了模型正确识别嗜睡的能力。

实验 5 到实验 7 受益于早期停止的应用,它保留了高性能指标,同时防止了过度拟合。值得注意的是,EX7 在 38 个时期停止训练,表现出模范性能,在所有评估指标之间取得了最佳平衡。

实验 8 到实验 10 在 EX7 中建立的早期停止点之后,性能指标表现出停滞或略微回归的迹象,这表明将训练扩展到此阈值之外会产生收益递减,并可能导致模型过度训练。

4.2.3. 最佳训练配置

分析结果明确表明,训练 EFFRES-DrowsyNet 大约 70 到 80 个时期,特别是提前停止,可以优化所有指标的性能,而不会导致过拟合。实验 7 是最有效的配置,在准确率、精密度和召回率方面获得了最高分,并且损失率较低。该实验提出了一个令人信服的案例,用于设置训练 epoch 数的上限,以最大限度地提高驾驶员睡意检测的实际应用的效率和效能。

这项全面的评估不仅证实了 EFFRES-DrowsyNet 的强大功能,还强调了明智的培训管理对于实现最佳运营绩效的重要性。这一系列实验的结果将指导模型的未来实施和优化,确保 EFFRES-DrowsyNet 仍然是驾驶员安全技术领域的尖端解决方案。

4.2.4. YawDD 数据集上的模型训练(70 个 epoch 和 epoch 38 提前停止)的性能分析

该模型被配置为训练总共 70 个时期,但由于验证性能停滞不前,因此在第 38 个时期应用了提前停止。以下是模型在训练过程中性能的详细分析,参考了准确度、精度、召回率和损失图。

  • Epoch 级性能概述

在第 1 个和第 3 个时期之间,模型显示出显著的改进,训练准确率从 62.47% 提高到 78.36%。这种快速的初始学习阶段在图 12b 中很明显,其中 accuracy 曲线急剧上升。相应地,在这些早期时期,精确率和召回率也有所提高,如图 12c,d 所示,这表明该模型很快就学会了分类所需的基本模式。在验证方面,准确率从 60.32% 显著提高到 89.60%,表明泛化能力较早。在第 4 到第 10 个时段期间,训练准确率不断提高,到第 10 个时段达到 90.79%。然而,验证准确率稳定在 89.60% 左右,如图 12b 所示,其中验证曲线在初始上升后趋于平坦。精确率仍然很高,召回率提高到 83.42%,表明模型的分类性能稳定。这些趋势在图 12c,d 中可以清楚地观察到。

图 12.YawDD 数据集上 epoch 的训练和验证指标:( a) 损失,( b) 准确性,( c) 精度和 ( d) 召回率。
从第 11 个纪元到第 17 个纪元,尽管训练准确率不断提高,但验证准确率稳定在 93.65% 左右。 图 12b 中突出显示的验证性能停滞不前,表明模型已达到其在验证集上的泛化能力。精确率和召回率也都稳定了下来,如图  12c,d 所示,强化了额外的训练对看不见的数据产生递减收益的概念。该模型的峰值性能发生在第 18 和第 28 个时段之间,验证准确率在第 28 个时段达到最高 94.92%。这在 图 12b 中很明显,其中验证曲线在趋于平稳之前达到最高点。在此期间,准确率和召回率也始终保持较高水平,如图  12c、d 所示,证明了该模型的稳健性和对这两个类别的平衡检测。
在最后的 epoch (29 到 38) 中,训练准确率进一步提高到 97.38%,但验证准确率没有超过第 28 个时期达到的峰值。 图 12b 中验证曲线的稳定性以及 图 12c、d 中的稳定精度和召回值表明性能饱和。尽管学习率在 Epoch 33 时有所降低,但没有观察到进一步的改进,这验证了在 Epoch 38 时做出的提前停止决定。 图 12a 中的损失曲线也显示出收敛性,支持模型已达到最佳训练的结论。
4.2.5. 性能指标
  • 训练精度:该模型在训练准确率方面稳步提高,最终在 Epoch 37 时达到 97.38%。然而,训练和验证准确性之间的差距越来越大( 如图 12b 中清楚地说明)表明过拟合的开始。虽然该模型继续从训练数据中学习,但它在看不见的数据上的性能并没有显示出相应的改进。
  • 验证精度:如图  12b 所示,该模型在第 28 纪元达到了 94.92% 的最高验证准确率。超过这一点,没有观察到进一步的改进,这表明该模型有效地捕获了数据中的基本模式。验证曲线的稳定强调了模型在持续训练下有限的泛化收益。
  • 精度和召回率:在整个训练过程中,准确率和召回率始终保持很高。准确率保持在 93% 以上,而召回率稳定在 88% 左右,这表明该模型在最大限度地减少假阳性和假阴性方面的有效性。这些趋势反映在 图 12c,d 中,这两个指标都表明在初始学习阶段之后是稳定的,只有很小的波动。
  • 训练和验证损失趋势:如图  12a 所示,训练损失从 5.0042 稳步下降到 0.0884,证实了有效的模型学习。验证损失在第 28 个时段达到最小值 0.2704,与峰值验证准确度一致。验证损失的后续波动表明过拟合的早期迹象,支持了在 Epoch 38 提前停止的基本原理。
  • 测试性能:最终模型评估得到测试损失 0.2905,测试准确率为 92.73%,精密率为 93.02%,召回率为 88.00%。这些结果肯定了该模型的稳健性和对以前未见过的数据的强烈泛化。
4.2.6. 提前停止的影响
由于验证准确性处于停滞状态,因此在 epoch 38 之后应用了提前停止。停止训练的决定得到了验证性能已经饱和的事实的支持,进一步的训练可能不会带来实质性的改进。这反映在 图 12b,d 中,验证曲线在以后的 epoch 中趋于平稳,确保模型不会过度拟合并保持强大的泛化。
4.2.7. 学习率调度
学习率由 10 降低−4到 10−5在纪元 33 处。这种调整有助于在模型接近最佳性能时微调模型的参数。虽然学习率的降低允许更精细的更新,但 图 12b 显示之后验证准确性没有显着提高。尽管如此,这种微调使模型能够稳定并避免了较大的波动。
4.2.8. 测试集性能
经最终评估,该模型达到 92.73% 的测试准确率,准确率为 93.02%,召回率为 88.00%。这些测试集结果与验证性能密切相关,表明模型的学习和泛化能力在可见和不可见的数据中是一致的。测试集性能反映了模型的稳健性,证实了其能够很好地泛化。
4.3. EFFRES-DrowsyNet 在 NTHU-DDD 数据集上 40 个时期的性能评估
本节全面分析了 EFFRES-DrowsyNet 模型在 NTHU-DDD 数据集上的 40 个时期训练过程中的性能。评估包括对准确率、精密度、召回率和损失等分类指标的详细纪元讨论,如图 13 所示。该模型在大多数指标上都表现出持续的改进,并且在后期有收敛和稳定的迹象。
图 13.NTHU-DDD 数据集上超过 40 个时期的训练和验证指标:( a) 损失、( b) 准确性、( c) 精度和 ( d) 召回率。
  • Epoch 级性能概述
在初始 epoch (1 到 3) 期间,该模型表现出快速学习阶段,训练准确率从 61.14% 提高到 76.70%,验证准确率从 57.58% 提高到 84.10%。这种急剧上升在 图 13b 中可见,表明该模型迅速内化了基本特征表示。精确率和召回率在此阶段也显示出显著的提高。如图  13c,d 所示,训练精度从 58.25% 提高到 77.57%,召回率从 53.75% 提高到 69.17%。同时,验证精度飙升至 95.11%,同时召回率从 99.58% 重新校准到 68.85%,表明从过度敏感到更平衡的分类行为的早期校正。
在第 4 个和第 10 个时期之间,训练准确率继续上升,达到 86.95%,而验证准确率稳步攀升至 89.26%。准确率和召回率也有所提高,训练召回率超过 82.80%,表明检测真阳性的一致性有所提高。尽管验证损失波动,但这一阶段的特点是验证性能稳定( 图 13a),反映了该模型日益增长的稳健性。
从第 11 个时期到第 17 个时期,验证准确率稳定在 94.28% 左右,而训练准确率提高到 90.06%。这些趋势表明,该模型在泛化能力方面达到了饱和点。训练精度和召回率仍然很高(高于 88%),而验证精度和召回率分别稳定在 93-94% 和 94% 左右。这种平衡反映了模型在这两个类别中的可靠分类性能。
第 18 到 28 个时段标志着最佳性能窗口。验证准确率达到 95.39% 的峰值(第 28 时期),精确率和召回率保持高且稳定的值。在此期间,训练指标不断提高——训练准确率上升到 92.65%,召回率达到 91.72%——但验证曲线( 图 13b-d)停滞不前,表明持续训练的额外好处有限。验证损失在第 28 个时段达到最低值 0.1157( 图 13a),进一步加强了模型的收敛性。
在最后阶段(第 29 到 40 个时期),训练准确率逐渐提高到 94.03%,准确率和召回率超过 93%。验证准确率保持稳定,从 94.91% 到 95.66% 不等,而准确率和召回率继续徘徊在 94-95% 左右。 如图 13 所示,这些指标的一致性证实了模型在最后一个 epoch 之前已经达到了其学习能力。尽管验证损失波动很小,但在 epoch 28 之后没有观察到显著的性能提升,这支持了模型的收敛。
性能指标摘要
所提出的模型在训练、验证和测试阶段表现出强大而一致的学习行为。如图  13b 所示,训练准确率呈稳步上升趋势,到第 40 个时段时最终达到 94.03%。值得注意的是,训练和验证准确性之间的差距在后期逐渐缩小,这表明模型在没有过度拟合的情况下进行了有效的学习。验证准确率在第 35 个时段达到 95.66% 的峰值,并在训练过程结束前保持稳定,进一步表明该模型能够很好地泛化到看不见的数据。在最终 epoch 中观察到的相对平坦的曲线证实了学习过程中的收敛性和稳定性。
在分类性能方面,在整个训练过程中,准确率和召回率都始终保持较高水平。如图  13c,d 所示,到第 28 个时期时,精确率超过 94%,而召回率也超过 94%,这表明该模型在最大限度地减少假阳性和假阴性方面的有效性。精确率和召回率之间的这种平衡强调了模型在准确检测目标类方面的可靠性。
训练损失从初始值 3.14 平滑而一致地下降到 0.14,如图  13a 所示,表明模型参数的逐步优化。验证损失在第 28 个时段达到最小值,之后保持在较窄的范围内,这表明该模型已成功捕获数据的基础模式,而没有明显的过拟合。
最后,对测试集的评估证实了模型的鲁棒性和泛化能力。测试结果的损失低至 0.1195,准确率为 95.14%,精密度为 94.09%,召回率为 95.39%。这些指标验证了模型在涉及以前未见过的输入的实际场景中的有效性和可靠性。
4.4. 所提出的混合深度学习模型与 SUST-DDD 和 NTHU-DDD 数据集上现有模型的比较
为了评估所提出的混合模型 EffRes-DrowsyNet 在检测驾驶员睡意方面的有效性,对几种已建立的模型进行了全面的比较分析,包括 VGG19 + LSTM、VGG16 + LSTM、AlexNet + LSTM、VGG-FaceNet + LSTM、MobileNetV2 + 3D CNN、PMLDB 和 CNN 集成方法。这些模型最初应用于 SUST-DDD 和 NTHU-DDD 数据集。使用三个关键指标(准确度、精密度和召回率)对性能进行评估,这些指标对于评估安全关键型应用的可靠性至关重要。如 表 5 所示,拟议的混合模型在这些指标上始终优于所有先前的模型。该算法在 SUST-DDD 数据集上达到 97.71% 的峰值准确率,在 NTHU-DDD 数据集上达到 95.14% 的峰值准确率,精度和召回率达到平衡,表现出卓越的检测能力。这些结果证实了该模型适用于实时驾驶员监控系统,其中检测准确性和稳健性都是必不可少的。
表 5.驾驶员睡意检测模型的比较分析。
ModelAccuracy (%)Precision (%)Recall (%)Dataset UsedAnalysis and Comparison with Proposed Hybrid Model
VGG19 + LSTM [44]90.5391.7491.28SUST-DDDThe VGG19 + LSTM model provides a solid baseline with high accuracy and balanced precision and recall. However, the proposed model achieves a very high accuracy of 97.71% with balanced precision and recall, while achieving a refined detection capability, expressed by precision at 98.07%. The recall also grew to 97.33%, meaning fewer misses.
VGG16 + LSTM [44]89.3991.8189.09SUST-DDDAlthough VGG16 + LSTM achieves strong precision, its overall accuracy and recall fall slightly short of VGG19 + LSTM. In all metrics, the proposed hybrid model outperforms VGG16 + LSTM, hence it can be more dependable for real-time drowsiness detection.
AlexNet + LSTM [44]63.9163.7897.91SUST-DDDAlexNet + LSTM achieves high recall, albeit with low accuracy and precision. In other words, it may produce too many false positives. The hybrid model we propose achieves much better accuracy and precision. Thus, it achieves a balance that looks more promising in being sensitive as well as specific when the sensitivity and specificity are particularly important to some real-world applications, which is suitable in scenarios where such characteristics are important.
VGGFaceNet + LSTM [44]84.9483.6594.92SUST-DDDVGGFaceNet + LSTM shows good recall and fair accuracy but has lower precision, indicating a tendency for false positives. The proposed hybrid model outperforms it in all metrics, giving better accuracy, precision, and more robust balance—an ideal system for applications where safety is a concern.
EffRes-DrowsyNet (Ours)97.7198.0797.33SUST-DDDThe proposed hybrid model, which integrates EfficientNetB0 and ResNet50, demonstrates superior performance across all key metrics—accuracy, precision, and recall—surpassing previous models. This improvement underscores the hybrid model’s unique advantages, combining EfficientNetB0’s scalable and efficient processing with ResNet50’s deep feature extraction capabilities. The model’s high accuracy and precision significantly reduce false positives, while its elevated recall minimizes missed detections, making it highly sensitive to subtle signs of drowsiness. This balanced performance across metrics highlights the hybrid model’s potential as an optimal solution for real-world driver safety monitoring, particularly suited for real-time deployment in-vehicle systems where reliability and responsiveness are critical.
MobileNetV2 + 3D CNN [33]73.90NotreportedNotreportedNTHU-DDDThe MobileNetV2-based 3D CNN model offers real-time deployment advantages for mobile platforms with reasonable accuracy (73.9%) and robustness under occlusion (e.g., sunglasses). However, it lacks the detection performance of the proposed hybrid model, which significantly exceeds it in accuracy and provides complete precision-recall metrics. While the MobileNetV2 model is lightweight and deployable on devices like the Galaxy S7 with ~1 s inference time, it trades off accuracy and detection depth. The hybrid model is thus more suitable where maximum detection performance is essential, while the MobileNetV2-based solution might be preferred in low-resource or budget-constrained applications.
PMLDB [35]79.84NotreportedNotreportedNTHU-DDDThe PML-based handcrafted model achieves competitive accuracy through multiscale texture descriptors (LBP, HOG, COV) with PCA and Fisher Score for feature selection. Although it lacks deep learning’s dynamic adaptability and reports no precision/recall values, its balanced fusion strategy performs well under varied conditions (e.g., night, glasses). Nevertheless, the hybrid EffRes-DrowsyNet model significantly surpasses it in accuracy (+15.30%) and offers detailed evaluation metrics, making it more robust for critical deployment scenarios. PMLDB remains suitable for resource-constrained settings but not optimal for high-accuracy demands.
CNN Ensemble [36]85.0086.3082.00NTHU-DDDThe CNN ensemble model integrates four specialized CNNs (AlexNet, VGG-FaceNet, FlowImageNet, and ResNet) and uses simple averaging for decision-making. It achieves balanced and respectable performance in accuracy and precision. Compared to the hybrid EffRes-DrowsyNet, it performs lower in all metrics, particularly accuracy and recall. While the ensemble architecture offers modularity and robustness under varied lighting and gesture conditions, the proposed hybrid model provides significantly higher accuracy (95.14%) and greater consistency across all detection metrics. Thus, the hybrid model is better suited for safety-critical, real-time deployment scenarios.
EffRes-DrowsyNet (Ours)95.1494.0995.39NTHU-DDDOn the NTHU-DDD dataset, the proposed hybrid model again demonstrates excellent generalization and robust detection performance. With an accuracy of 95.14%, precision of 94.09%, and a high recall of 95.39%, it clearly surpasses previous models tested on this dataset. The close balance between precision and recall reflects its capability to detect drowsiness accurately while minimizing both false positives and false negatives. This makes it a strong candidate for real-time embedded deployment in intelligent transport systems, ensuring both safety and responsiveness in practical conditions.

EffRes-DrowsyNet 性能的提高主要是由于其组件如何协同工作。通过结合 EfficientNetB0 和 ResNet50 两个强大的网络,该模型可以学习详细的面部模式和整体面部模式,这有助于处理面部位置、光线和表情的变化。另一个重要因素是在数据标记期间使用 EAR 和 MAR 计算。此步骤有助于仅选择有意义的帧,例如闭上眼睛或打哈欠时,使训练数据更加准确和相关。我们还应用了几种数据增强技术,使模型更加健壮并防止其过度拟合。最重要的是,dropout、批量归一化和学习率调度器的使用使模型能够更有效地训练模型。当我们把所有这些放在一起时,与其他模型相比,EffRes-DrowsyNet 始终显示出更好的准确度、精度和召回率。

具体实现代码:点击这里

附录代码[主页联系]

    def run(self):self.cap = cv2.VideoCapture(self.path)while self.running:ret, im_rd = self.cap.read()if ret:im_rd = imutils.resize(im_rd, height=480, width=640)original_img = im_rd.copy()# 灰度化图像img_gray = cv2.cvtColor(original_img, cv2.COLOR_BGR2GRAY)# 使用人脸检测器检测每一帧图像中的人脸faces = detector(img_gray, 0)# 准备信息字典用于UI更新info = {'alarm': self.alarm_flag,'driver_id': '未知','driving_time': 0,'pitch': 0,'yaw': 0,'roll': 0,'ear': 0,'mar': 0,'eyes_state': '睁开','nod_duration': 0,'yawn_duration': 0,'blinks': 0,'yawns': 0,'nods': 0,'percols': 0}if len(faces) == 1:for k, d in enumerate(faces):try:roi_gray = img_gray[d.top():d.bottom(), d.left():d.right()]roi_gray = cv2.resize(roi_gray, (92, 112))params = Eigen_Face_Model.predict(roi_gray)except:continue# 使用dlib预测器得到68点数据的坐标shape = predictor(original_img, d)shape_array = face_utils.shape_to_np(shape)if params[0] != self.last_params:# 驾驶员更换,重置计时self.driving_time = 0self.starttime = datetime.datetime.now()self.last_params = params[0]try:info['driver_id'] = names[params[0]]except:info['driver_id'] = '未识别'# 计算头部姿态reprojectdst, _, pitch, roll, yaw = HPE.get_head_pose(shape_array)info['pitch'] = round(pitch, 2)info['yaw'] = round(yaw, 2)info['roll'] = round(roll, 2)# 提取左眼、右眼和嘴巴的所有坐标leftEye = shape_array[lStart:lEnd]rightEye = shape_array[rStart:rEnd]mouth = shape_array[mStart:mEnd]# 计算EARleftEAR = ARE.eye_aspect_ratio(leftEye)rightEAR = ARE.eye_aspect_ratio(rightEye)EAR = (leftEAR + rightEAR) / 2.0info['ear'] = round(EAR, 2)# 记录EAR历史数据用于图表self.EAR_history.append(EAR)if len(self.EAR_history) > self.max_history_length:self.EAR_history.pop(0)# 眨眼检测 - 改进算法current_time = datetime.datetime.now()if EAR < self.EAR_threshold and not self.eyes_closed:# 眼睛刚闭上self.eyes_closed = Trueself.blink_start_time = current_timeself.blink_counter += 1elif EAR >= self.EAR_threshold and self.eyes_closed:# 眼睛刚睁开self.eyes_closed = Falseif self.blink_start_time and (current_time - self.blink_start_time).total_seconds() < 0.5:# 眨眼时间在合理范围内self.blinks += 1self.blink_start_time = None# 计算MARMAR = ARE.mouth_aspect_ratio(mouth)info['mar'] = round(MAR, 2)# 记录MAR历史数据self.MAR_history.append(MAR)if len(self.MAR_history) > self.max_history_length:self.MAR_history.pop(0)# 哈欠检测 - 改进算法if MAR > self.MAR_threshold and not self.mouth_open:# 嘴巴刚张开self.mouth_open = Trueself.yawn_start_time = current_timeself.yawn_counter += 1elif MAR <= self.MAR_threshold and self.mouth_open:# 嘴巴刚闭合self.mouth_open = Falseif self.yawn_start_time:yawn_duration = (current_time - self.yawn_start_time).total_seconds()if yawn_duration >= 1.0:  # 哈欠持续时间超过1秒self.yawns += 1info['yawn_duration'] = int(yawn_duration)self.yawn_start_time = None# 点头检测 - 改进算法if pitch > self.pitch_threshold and not self.head_nodding:# 头部刚开始点头self.head_nodding = Trueself.nod_start_time = current_timeself.nod_counter += 1elif pitch <= self.pitch_threshold and self.head_nodding:# 头部刚结束点头self.head_nodding = Falseif self.nod_start_time:nod_duration = (current_time - self.nod_start_time).total_seconds()if nod_duration >= 0.5:  # 点头持续时间超过0.5秒self.nods += 1info['nod_duration'] = int(nod_duration)self.nod_start_time = None# PERCOLS值计算 - 改进算法if params[0] in range(len(self.everybody_EAR_mean)):T1 = self.everybody_EAR_min[params[0]] + 0.2 * (self.everybody_EAR_mean[params[0]] - self.everybody_EAR_min[params[0]])T2 = self.everybody_EAR_min[params[0]] + 0.8 * (self.everybody_EAR_mean[params[0]] - self.everybody_EAR_min[params[0]])# 计算眼睛闭合程度if EAR < T1 and abs(pitch) < 15 and abs(yaw) < 25 and abs(roll) < 15:if self.P80_start_time1 is None:self.P80_start_time1 = current_timeelif self.P80_start_time1 is not None:duration = (current_time - self.P80_start_time1).total_seconds()if duration > 0:self.P80_sum_time1.append(duration)self.P80_start_time1 = Noneif EAR < T2 and abs(pitch) < 15 and abs(yaw) < 25 and abs(roll) < 15:if self.P80_start_time2 is None:self.P80_start_time2 = current_timeelif self.P80_start_time2 is not None:duration = (current_time - self.P80_start_time2).total_seconds()if duration > 0:self.P80_sum_time2.append(duration)self.P80_start_time2 = None# 计算PERCOLS值sum_t1 = sum(self.P80_sum_time1)sum_t2 = sum(self.P80_sum_time2)if sum_t2 > 0:self.f = min(round(sum_t1 / sum_t2, 2), 1.0)  # 限制在0-1之间else:self.f = 0# 每60秒重置PERCOLS计算if int(self.driving_time) % 60 == 0:self.P80_sum_time1 = []self.P80_sum_time2 = []self.f = 0# 设置眼睛状态info['eyes_state'] = '闭合' if EAR < self.EAR_threshold else '睁开'info['blinks'] = self.blinksinfo['yawns'] = self.yawnsinfo['nods'] = self.nodsinfo['percols'] = self.f# 疲劳状态判断 - 改进算法# 每60秒检查一次疲劳状态if int(self.driving_time) % 60 == 0:if self.blinks >= 30:self.alarm_flag = '眨眼频率警告'elif self.yawns >= 5:self.alarm_flag = '哈欠频率警告'elif self.nods >= 3:self.alarm_flag = '点头频率警告'elif self.f > 0.6:self.alarm_flag = 'PERCOLS值警告'elif self.driving_time > self.Driving_Time_Threshold:self.alarm_flag = '长时间驾驶警告'else:self.alarm_flag = '正常'# 重置计数器self.blinks = 0self.yawns = 0self.nods = 0info['alarm'] = self.alarm_flaginfo['driving_time'] = int(self.driving_time)# 绘制特征点和姿态for i in range(68):cv2.circle(im_rd, (shape.part(i).x, shape.part(i).y), 2, (0, 255, 0), -1, 8)for start, end in self.line_pairs:cv2.line(im_rd, (int(reprojectdst[start][0]), int(reprojectdst[start][1])),(int(reprojectdst[end][0]), int(reprojectdst[end][1])), (0, 0, 255))# 绘制眼睛和嘴巴轮廓leftEyeHull = cv2.convexHull(leftEye)rightEyeHull = cv2.convexHull(rightEye)cv2.drawContours(im_rd, [leftEyeHull], -1, (0, 255, 0), 1)cv2.drawContours(im_rd, [rightEyeHull], -1, (0, 255, 0), 1)mouthHull = cv2.convexHull(mouth)cv2.drawContours(im_rd, [mouthHull], -1, (0, 255, 0), 1)# 添加疲劳状态文字提示 - 使用支持中文的字体status_color = (0, 255, 0) if self.alarm_flag == '正常' else (0, 0, 255)cv2.putText(im_rd, f"状态: {self.alarm_flag}", (10, 50),cv2.FONT_HERSHEY_SIMPLEX, 0.7, status_color, 2)elif len(faces) == 0:# 使用支持中文的字体cv2.putText(im_rd, "未检测到人脸", (10, 30), cv2.FONT_HERSHEY_SIMPLEX, 0.7, (0, 0, 255), 2)else:cv2.putText(im_rd, "检测到多个人脸", (10, 30), cv2.FONT_HERSHEY_SIMPLEX, 0.7, (255, 0, 0), 2)# 更新驾驶时间endtime = datetime.datetime.now()self.driving_time = (endtime - self.starttime).total_seconds()# 转换图像用于Qt显示rgb_image = cv2.cvtColor(im_rd, cv2.COLOR_BGR2RGB)h, w, ch = rgb_image.shapebytes_per_line = ch * wqt_image = QImage(rgb_image.data, w, h, bytes_per_line, QImage.Format_RGB888)self.change_pixmap_signal.emit(qt_image)# 发送信息更新UIself.update_info_signal.emit(info)else:# 视频结束或摄像头断开,重新打开self.reset_counters()self.cap = cv2.VideoCapture(self.path)def reset_counters(self):"""重置所有计数器"""self.driving_time = 0self.starttime = datetime.datetime.now()self.blink_counter = 0self.blinks = 0self.yawn_counter = 0self.yawns = 0self.nod_counter = 0self.nods = 0self.P80_sum_time1 = []self.P80_sum_time2 = []self.f = 0self.alarm_flag = '正常'self.eyes_closed = Falseself.mouth_open = Falseself.head_nodding = Falseself.blink_start_time = Noneself.yawn_start_time = Noneself.nod_start_time = Noneself.P80_start_time1 = Noneself.P80_start_time2 = Nonedef stop(self):self.running = Falseself.wait()if hasattr(self, 'cap') and self.cap.isOpened():self.cap.release()class FatigueDetectionApp(QMainWindow):def __init__(self):super().__init__()self.setWindowTitle('疲劳驾驶检测系统')self.setMinimumSize(1200, 700)  # 增大窗口尺寸# 优化颜色方案,提高对比度self.setStyleSheet("""QMainWindow {background-color: #121212;}QLabel {color: #e0e0e0;font-size: 14px;}QPushButton {background-color: #3b82f6;color: white;border-radius: 5px;padding: 8px 15px;font-size: 14px;}QPushButton:hover {background-color: #2563eb;}QPushButton:pressed {background-color: #1d4ed8;}QGroupBox {border: 2px solid #3b82f6;border-radius: 8px;margin-top: 10px;padding-top: 15px;}QGroupBox::title {subcontrol-origin: margin;subcontrol-position: top center;padding: 0 10px;color: #3b82f6;font-weight: bold;font-size: 15px;}""")# 创建中央部件和主布局central_widget = QWidget()main_layout = QHBoxLayout(central_widget)main_layout.setSpacing(15)  # 增加间距# 左侧视频显示区域video_group = QGroupBox("实时视频")video_group.setFont(title_font)video_layout = QVBoxLayout()self.video_label = QLabel("等待视频输入...")self.video_label.setAlignment(Qt.AlignCenter)self.video_label.setMinimumSize(700, 500)self.video_label.setStyleSheet("border: 2px solid #3b82f6; border-radius: 5px;")video_layout.addWidget(self.video_label)video_group.setLayout(video_layout)# 右侧信息显示区域info_group = QGroupBox("驾驶状态监测")info_group.setFont(title_font)info_layout = QVBoxLayout()info_layout.setSpacing(10)  # 增加间距# 驾驶人信息driver_info_layout = QHBoxLayout()self.driver_id_label = QLabel("驾驶人: 未识别")self.driver_id_label.setFont(font)self.driving_time_label = QLabel("驾驶时间: 0 秒")self.driving_time_label.setFont(font)driver_info_layout.addWidget(self.driver_id_label)driver_info_layout.addWidget(self.driving_time_label)info_layout.addLayout(driver_info_layout)# 警告信息 - 增大尺寸和对比度self.alarm_label = QLabel("状态: 正常")self.alarm_label.setFont(alarm_font)self.alarm_label.setStyleSheet("color: #4caf50; font-size: 18px; font-weight: bold;")self.alarm_label.setAlignment(Qt.AlignCenter)self.alarm_label.setMinimumHeight(40)info_layout.addWidget(self.alarm_label)# 头部姿态pose_group = QGroupBox("头部姿态")pose_group.setFont(font)pose_layout = QHBoxLayout()self.pitch_label = QLabel("俯仰角(Pitch): 0.00°")self.pitch_label.setFont(font)self.yaw_label = QLabel("偏航角(Yaw): 0.00°")self.yaw_label.setFont(font)self.roll_label = QLabel("滚转角(Roll): 0.00°")self.roll_label.setFont(font)pose_layout.addWidget(self.pitch_label)pose_layout.addWidget(self.yaw_label)pose_layout.addWidget(self.roll_label)pose_group.setLayout(pose_layout)info_layout.addWidget(pose_group)# 面部特征face_group = QGroupBox("面部特征")face_group.setFont(font)face_layout = QHBoxLayout()self.ear_label = QLabel("眼睛纵横比(EAR): 0.00")self.ear_label.setFont(font)self.mar_label = QLabel("嘴巴纵横比(MAR): 0.00")self.mar_label.setFont(font)self.eyes_state_label = QLabel("眼睛状态: 睁开")self.eyes_state_label.setFont(font)face_layout.addWidget(self.ear_label)face_layout.addWidget(self.mar_label)face_layout.addWidget(self.eyes_state_label)face_group.setLayout(face_layout)info_layout.addWidget(face_group)# 疲劳指标fatigue_group = QGroupBox("疲劳指标")fatigue_group.setFont(font)fatigue_layout = QGridLayout()fatigue_layout.setSpacing(10)  # 增加间距# 使用更清晰的标签self.blinks_label = QLabel("0 次")self.yawns_label = QLabel("0 次")self.nods_label = QLabel("0 次")self.percols_label = QLabel("0.00")self.nod_duration_label = QLabel("0 秒")self.yawn_duration_label = QLabel("0 秒")# 设置标签字体labels = [self.blinks_label, self.yawns_label, self.nods_label,self.percols_label, self.nod_duration_label, self.yawn_duration_label]for label in labels:label.setFont(font)# 优化布局fatigue_layout.addWidget(QLabel("眨眼次数:", font=font), 0, 0)fatigue_layout.addWidget(self.blinks_label, 0, 1)fatigue_layout.addWidget(QLabel("哈欠次数:", font=font), 1, 0)fatigue_layout.addWidget(self.yawns_label, 1, 1)fatigue_layout.addWidget(QLabel("点头次数:", font=font), 2, 0)fatigue_layout.addWidget(self.nods_label, 2, 1)fatigue_layout.addWidget(QLabel("PERCOLS值:", font=font), 3, 0)fatigue_layout.addWidget(self.percols_label, 3, 1)fatigue_layout.addWidget(QLabel("点头持续时间:", font=font), 0, 2)fatigue_layout.addWidget(self.nod_duration_label, 0, 3)fatigue_layout.addWidget(QLabel("哈欠持续时间:", font=font), 1, 2)fatigue_layout.addWidget(self.yawn_duration_label, 1, 3)fatigue_group.setLayout(fatigue_layout)info_layout.addWidget(fatigue_group)# 控制按钮control_layout = QGridLayout()self.start_button = QPushButton("开始检测(摄像头)")self.start_button.setFont(font)self.start_button.setMinimumHeight(40)self.stop_button = QPushButton("停止检测")self.stop_button.setFont(font)self.stop_button.setMinimumHeight(40)self.stop_button.setEnabled(False)self.local_video_button = QPushButton("选择本地视频")self.local_video_button.setFont(font)self.local_video_button.setMinimumHeight(40)self.exit_button = QPushButton("安全退出系统")self.exit_button.setFont(font)self.exit_button.setMinimumHeight(40)self.exit_button.setStyleSheet("background-color: #ef4444;")control_layout.addWidget(self.start_button, 0, 0)control_layout.addWidget(self.local_video_button, 0, 1)control_layout.addWidget(self.stop_button, 1, 0)control_layout.addWidget(self.exit_button, 1, 1)info_layout.addLayout(control_layout)info_group.setLayout(info_layout)# 将视频和信息区域添加到主布局main_layout.addWidget(video_group)main_layout.addWidget(info_group)main_layout.setStretch(0, 3)  # 视频区域占3份main_layout.setStretch(1, 2)  # 信息区域占2份self.setCentralWidget(central_widget)# 创建视频线程self.video_thread = VideoThread()self.video_thread.change_pixmap_signal.connect(self.update_video_frame)self.video_thread.update_info_signal.connect(self.update_info_display)# 连接信号和槽self.start_button.clicked.connect(self.start_camera_detection)self.stop_button.clicked.connect(self.stop_detection)self.local_video_button.clicked.connect(self.select_local_video)self.exit_button.clicked.connect(self.safe_exit)def start_camera_detection(self):"""开始摄像头检测"""self.start_button.setEnabled(False)self.stop_button.setEnabled(True)self.video_thread.set_video_source(0)  # 0表示默认摄像头self.video_thread.running = Trueself.video_thread.start()def select_local_video(self):"""选择本地视频文件"""options = QFileDialog.Options()video_file, _ = QFileDialog.getOpenFileName(self, "选择视频文件", "","视频文件 (*.mp4 *.avi *.mov *.mkv);;所有文件 (*)",options=options)if video_file:self.start_button.setEnabled(False)self.stop_button.setEnabled(True)self.video_thread.set_video_source(video_file)self.video_thread.running = Trueself.video_thread.start()def stop_detection(self):"""停止检测"""self.start_button.setEnabled(True)self.stop_button.setEnabled(False)self.video_thread.stop()# 重置UI显示self.update_info_display({'alarm': '正常','driver_id': '未识别','driving_time': 0,'pitch': 0,'yaw': 0,'roll': 0,'ear': 0,'mar': 0,'eyes_state': '睁开','nod_duration': 0,'yawn_duration': 0,'blinks': 0,'yawns': 0,'nods': 0,'percols': 0})def safe_exit(self):"""安全退出系统"""reply = QMessageBox.question(self, '确认退出', '确定要退出系统吗?',QMessageBox.Yes | QMessageBox.No, QMessageBox.No)if reply == QMessageBox.Yes:if self.video_thread.isRunning():self.video_thread.stop()QApplication.quit()def update_video_frame(self, qt_image):"""更新视频帧"""pixmap = QPixmap.fromImage(qt_image)self.video_label.setPixmap(pixmap.scaled(self.video_label.width(), self.video_label.height(),Qt.KeepAspectRatio, Qt.SmoothTransformation))def update_info_display(self, info):"""更新信息显示"""self.driver_id_label.setText(f"驾驶人: {info['driver_id']}")self.driving_time_label.setText(f"驾驶时间: {info['driving_time']} 秒")# 根据警告类型设置不同颜色if info['alarm'] == '正常':self.alarm_label.setText(f"状态: {info['alarm']}")self.alarm_label.setStyleSheet("color: #4caf50; font-size: 18px; font-weight: bold;")else:self.alarm_label.setText(f"警告: {info['alarm']}")self.alarm_label.setStyleSheet("color: #ff5252; font-size: 18px; font-weight: bold;")self.pitch_label.setText(f"俯仰角(Pitch): {info['pitch']}°")self.yaw_label.setText(f"偏航角(Yaw): {info['yaw']}°")self.roll_label.setText(f"滚转角(Roll): {info['roll']}°")self.ear_label.setText(f"眼睛纵横比(EAR): {info['ear']}")self.mar_label.setText(f"嘴巴纵横比(MAR): {info['mar']}")self.eyes_state_label.setText(f"眼睛状态: {info['eyes_state']}")self.blinks_label.setText(f"{info['blinks']} 次")self.yawns_label.setText(f"{info['yawns']} 次")self.nods_label.setText(f"{info['nods']} 次")self.percols_label.setText(f"{info['percols']}")self.nod_duration_label.setText(f"{info['nod_duration']} 秒")self.yawn_duration_label.setText(f"{info['yawn_duration']} 秒")def closeEvent(self, event):"""关闭事件处理"""if self.video_thread.isRunning():self.video_thread.stop()event.accept()

http://www.xdnf.cn/news/1040365.html

相关文章:

  • 网络安全防护:Session攻击
  • Java大模型开发入门 (12/15):Agent实战 - 打造能调用外部API的智能助手
  • 更新! Windows 10 32位 专业版 [版本号19045.5912]
  • 2025-06-14[避坑]解决不支持中文路径读取图像的方法
  • 2025.06.11-华子第三题-300分
  • Python 继承的优缺点(处理多重继承)
  • 25年股票交易半年小结~~
  • K8S 专栏 —— Pod 篇
  • visual studio学习250614(编译错误)
  • 速度与精度的结合:Faster R-CNN模型的性能剖析
  • 清晰了解序列化的来龙去脉
  • etcd基本数据库操作
  • 基于Python学习《Head First设计模式》第十三章 现实世界中的模式
  • c++中vector的使用
  • 前端开发中,实现多线程
  • 轮转数组题解
  • App跨平台技术2025年深度解析:核心原理与最佳实践
  • C语言环形数组(循环队列)详解:原理、实现与应用
  • BeckHoff <--> Festo Cmmt AS驱动器 EtherCat通讯
  • 1.16 Cookie 和 Session
  • 多商户商城+直播电商系统融合开发方案:一套源码搞定双场景应用
  • 解决vue3标签中引用动态图片失效问题
  • Python无限弹窗
  • CSS Margin纵向重叠(Margin Collapse)问题详解
  • springAI 大模型应用开发
  • 操作系统多级存储模型
  • 【AS32系列MCU调试教程】调试工具:Eclipse调试工具栏与窗口的深入分析
  • 《高等数学》(同济大学·第7版)第五章第一节定积分的概念与性质
  • 【多线程初阶】详解线程池(上)
  • 探险之物资储备c++