基于opencv的人脸闭眼识别疲劳监测

时间:2024-10-10 10:26:18

关于深度实战社区

我们是一个深度学习领域的独立工作室。团队成员有:中科大硕士、纽约大学硕士、浙江大学硕士、华东理工博士等,曾在腾讯、百度、德勤等担任算法工程师/产品经理。全网20多万+粉丝,拥有2篇*人工智能发明专利。

社区特色:深度实战算法创新

获取全部完整项目数据集、代码、视频教程,请进入官网:zzgcz.com。竞赛/论文/毕设项目辅导答疑,v:zzgcz_com


1. 项目简介

本项目旨在实现基于眼部特征的眨眼检测,通过监测眼睛开闭状态来计算眨眼次数,从而应用于疲劳监测、注意力检测等场景。使用了面部特征点检测算法,以及眼部特征比率(EAR, Eye Aspect Ratio)来判断眼睛的闭合状态。当EAR值低于设定的阈值时,系统判定为眨眼。整个项目采用了Dlib库进行面部特征点定位,并使用OpenCV进行视频流的实时处理和可视化。通过设定合适的阈值和连续帧数参数,该模型能够准确判断并统计眨眼次数。该项目适用于基于视频流的实时眨眼检测场景,并可进一步扩展到疲劳驾驶检测、医疗健康监测以及基于表情的交互应用中。

在这里插入图片描述

2.技术创新点摘要

  1. 基于面部特征点的眼部状态检测: 代码使用Dlib库进行面部特征点检测,并通过预测68个关键点来定位眼部区域。该方法能够精确定位每个关键点的位置,确保眼部区域的检测具有较高的准确性。相比于传统的基于像素的眼部检测方法,这种基于特征点的方式更加鲁棒,能够在不同光照、角度和面部姿态下保持稳定的检测效果。
  2. 提出眼部特征比率(EAR)的判定机制: 项目中定义了眼部特征比率(EAR, Eye Aspect Ratio),通过计算眼部竖直方向的两个特征点距离与水平方向的距离比值,动态反映眼睛的开闭状态。这一比率的设计能够在眨眼时有效地捕捉眼部变化,并且与传统的基于面积或形状的检测方法相比,受噪声干扰较小。同时,EAR的阈值判定法具有较强的普适性,不同用户仅需微调参数即可适应多种应用场景。
  3. 实时眨眼检测与连续帧闭合判定: 在项目中,通过实时视频流获取用户眼部图像并进行处理,利用EAR值与预设阈值进行实时判定。创新地引入了“连续帧闭合判定”机制,即只有当眼部EAR值连续多帧低于设定阈值时,才计为一次有效的眨眼行为。该机制避免了因瞬时噪声或轻微眼部动作(如快速眨眼或眼球移动)引起的误判,提升了检测的精度和可靠性。
  4. 可视化与交互设计: 该项目在实时检测过程中提供了可视化展示,包括眨眼次数统计、EAR值的动态变化以及眼部轮廓的实时标注。通过这种可视化方式,用户能够直观地了解系统的检测状态,从而提升了模型的可解释性与交互体验。

3. 数据集与预处理

本项目的眨眼检测主要依赖于视频流数据和面部特征点检测模型进行实时处理,因此数据集以动态视频帧为主,并通过Dlib提供的预训练面部特征点模型来提取特征。视频源可以是实时摄像头输入或预录制的视频文件,通过OpenCV进行逐帧处理。该项目不直接使用大规模的图像数据集,而是通过Dlib模型的shape_predictor_68_face_landmarks.dat权重文件来对面部进行特征点定位。特征点数据能够精准定位眼睛、嘴巴、鼻子等关键面部区域,因此,项目中没有传统数据集的标注步骤,而是基于特征点模型的输出进行二次处理。

在数据预处理方面,该项目采取了以下步骤:

  1. 图像尺寸调整: 每帧图像在输入时会被统一调整到指定大小(宽度1200像素),保证所有帧的尺度一致,从而避免因不同视频分辨率带来的计算误差。此外,项目通过OpenCV对帧数据进行灰度化处理,减少色彩冗余,提升检测速度和准确性。
  2. 面部特征点提取: 使用Dlib的面部检测器(detector = dlib.get_frontal_face_detector())来检测每一帧中的人脸区域,并通过68个面部特征点预测模型(shape_predictor)提取关键点坐标,主要关注眼部区域的特征点。然后将提取的特征点转换为Numpy数组格式,便于后续计算和处理。
  3. 眼部区域特征工程: 项目中定义了眼部特征比率(EAR)作为核心判定特征。通过计算左眼和右眼的竖直与水平距离比率,并进一步结合两眼的平均值来判断眼部状态。EAR特征能够有效区分眨眼和非眨眼状态,是项目的重要特征工程步骤。

4. 模型架构

  1. 模型结构的逻辑

本项目主要使用传统的计算机视觉方法,而非典型的深度学习神经网络模型。其核心检测部分依赖于基于Dlib库的面部特征点检测算法,并未使用典型的卷积神经网络(CNN)或循环神经网络(RNN)模型。项目的关键算法部分包括以下结构逻辑:

  • 面部特征点检测模型: 使用Dlib的shape_predictor来检测面部的68个关键点,该模型是基于监督学习的回归树(Regression Trees)算法实现的。它通过逐步调整面部区域的坐标,最终确定68个特征点的精确位置。模型输入为图像的灰度值矩阵,输出为面部68个关键点的二维坐标。
  • 眼部特征比率(Eye Aspect Ratio, EAR)计算: 通过面部特征点定位获取眼部区域(左眼和右眼各6个点),定义竖直方向上的点对距离为 A 和 B,水平方向的点对距离为 C。具体公式如下:

A = ( x 2 − x 6 ) 2 + ( y 2 − y 6 ) 2 A = \sqrt{(x_2 - x_6)^2 + (y_2 - y_6)^2} A=(x2x6)2+(y2y6)2

B = ( x 3 − x 5 ) 2 + ( y 3 − y 5 ) 2 B = \sqrt{(x_3 - x_5)^2 + (y_3 - y_5)^2} B=(x3x5)2+(y3y5)2

C = ( x 1 − x 4 ) 2 + ( y 1 − y 4 ) 2 C = \sqrt{(x_1 - x_4)^2 + (y_1 - y_4)^2} C=(x1x4)2+(y1y4)2

其中,(x1,y1) 到 (x6,y6) 表示眼睛周围的6个关键点。眼部特征比率(EAR)的定义如下:

E A R = A + B 2 × C EAR = \frac{A + B}{2 \times C} EAR=2×CA+B

EAR值反映了眼睛的开合状态,当EAR值低于某个设定的阈值时,即判断为眨眼状态。

  • 阈值判定与计数机制: 在模型中设定了两个关键参数:EAR阈值(EYE_AR_THRESH = 0.3)和连续帧计数阈值(EYE_AR_CONSEC_FRAMES = 3)。当EAR值低于0.3且连续低于3帧时,系统会判定为一次有效的眨眼行为,并在计数器中累加。

整体来看,本项目的结构较为简单,主要由图像预处理、面部特征点检测、EAR值计算、阈值判定、以及可视化输出几个步骤组成。所有这些步骤在代码中被集成在同一个脚本中,以逐帧的方式处理视频流。

  1. 模型的整体训练流程与评估指标

由于本项目并非深度学习模型,因此没有典型的训练流程和神经网络的训练阶段。相反,它主要依赖于预训练的Dlib面部特征点检测模型(shape_predictor_68_face_landmarks.dat),该模型本身已经通过大规模的人脸关键点数据集进行训练。

项目的整体工作流程如下:

  1. 模型加载与参数初始化: 首先通过Dlib加载面部特征点检测模型,并初始化EAR阈值与连续帧检测参数。
  2. 视频流逐帧处理: 从输入视频或实时摄像头中逐帧读取图像,并转换为灰度图以提升检测速度。
  3. 面部特征点检测: 使用Dlib模型在每一帧中检测人脸,并定位眼部的6个关键点坐标。
  4. EAR值计算与判定: 基于提取的眼部特征点,逐帧计算EAR值,并与预设阈值进行比较,判断当前帧是否为眨眼状态。
  5. 眨眼次数统计与可视化: 当连续帧数低于阈值时,判定为一次眨眼,并在总次数上累加,同时在图像中实时显示眨眼次数。

评估指标:

该项目没有传统模型训练的评估指标,如损失函数或精确度,但可通过以下两个指标来评估其效果:

  • 眨眼检测准确率: 即检测到的眨眼次数与实际眨眼次数的比例。
  • 误报率(False Positive Rate, FPR): 系统误判为眨眼的帧数与总检测帧数的比例。

5. 核心代码详细讲解

1. 面部特征点定位与初始化
detector = dlib.get_frontal_face_detector()
predictor = dlib.shape_predictor(args["shape_predictor"])

详细解释:

  • detector = dlib.get_frontal_face_detector(): 这行代码使用 dlib 的内置函数 get_frontal_face_detector() 加载一个预训练的人脸检测器。该检测器采用基于方向梯度直方图(HOG, Histogram of Oriented Gradients)和线性分类器的方法来快速定位图像中的人脸位置,返回的是一个 detector 对象。这个对象用于检测输入图像中的人脸区域。
  • predictor = dlib.shape_predictor(args["shape_predictor"]): 该行代码加载了预训练的面部特征点模型 shape_predictor。这个模型通常是 shape_predictor_68_face_landmarks.dat 文件,用于检测人脸中的68个关键点(例如眼睛、鼻子、嘴巴、下巴等位置)。它将返回一个 predictor 对象,该对象可用于进一步获取每个面部特征点的坐标。
2. EAR(眼部特征比率)计算函数
def eye_aspect_ratio(eye):
        A = dist.euclidean(eye[1], eye[5])
        B = dist.euclidean(eye[2], eye[4])
        C = dist.euclidean(eye[0], eye[3])
        ear = (A + B) / (2.0 * C)return ear

详细解释:

  • def eye_aspect_ratio(eye): 定义了一个名为 eye_aspect_ratio 的函数,该函数用于计算眼睛的特征比率(EAR)。它的输入参数 eye 是一个包含6个面部关键点坐标的列表,表示当前帧中检测到的一个眼部区域。
  • A = dist.euclidean(eye[1], eye[5]): 使用 scipy.spatial.distance 模块中的 euclidean 函数计算眼部竖直方向上两个点(第2个点和第6个点)之间的欧氏距离。该值存储在变量 A 中。
  • B = dist.euclidean(eye[2], eye[4]): 计算竖直方向上另一对点(第3个点和第5个点)之间的距离,并存储在变量 B 中。
  • C = dist.euclidean(eye[0], eye[3]): 计算水平方向上两个端点(第1个点和第4个点)之间的距离,并存储在变量 C 中。
  • ear = (A + B) / (2.0 * C): 根据EAR公式 EAR=A+B2×C\text{EAR} = \frac{A + B}{2 \times C}EAR=2×CA+B 计算眼睛的特征比率。该比率反映了眼睛的开闭程度,EAR值越低表示眼睛越闭合。
  • return ear: 返回当前眼部区域的EAR值。
3. 逐帧处理与眼部状态判断
if ear < EYE_AR_THRESH:
        COUNTER += 1else:if COUNTER >= EYE_AR_CONSEC_FRAMES:
                TOTAL += 1
        COUNTER = 0

详细解释:

  • if ear < EYE_AR_THRESH: 检查计算得到的 ear 值是否小于设定的阈值 EYE_AR_THRESH(在代码中设定为0.3)。如果 ear 值小于该阈值,表示眼睛处于闭合状态。
  • COUNTER += 1: 当眼睛处于闭合状态时,累加闭眼计数器 COUNTER。这个计数器用于统计当前连续闭眼的帧数。
  • else: 如果 ear 值大于或等于阈值,表示眼睛处于睁开状态,进入 else 分支。
  • if COUNTER >= EYE_AR_CONSEC_FRAMES: 检查 COUNTER 是否大于等于设定的连续帧阈值 EYE_AR_CONSEC_FRAMES(设定为3)。这表示眼睛已经连续闭合了3帧,判定为一次有效的眨眼行为。
  • TOTAL += 1: 当满足连续闭眼帧数条件时,眨眼总数 TOTAL 加1。
  • COUNTER = 0: 重置 COUNTER 计数器,表示从当前帧开始重新统计。
4. 实时视频流处理与展示
cv2.putText(frame, "Blinks: {}".format(TOTAL), (10, 30),
        cv2.FONT_HERSHEY_SIMPLEX, 0.7, (0, 0, 255), 2)
cv2.putText(frame, "EAR: {:.2f}".format(ear), (300, 30),
        cv2.FONT_HERSHEY_SIMPLEX, 0.7, (0, 0, 255), 2)

详细解释:

  • cv2.putText(frame, "Blinks: {}".format(TOTAL), (10, 30), cv2.FONT_HERSHEY_SIMPLEX, 0.7, (0, 0, 255), 2): 使用 OpenCV 的 putText 函数在当前帧 frame 中显示文本信息。文本内容为当前检测到的眨眼总次数 TOTAL,显示位置为图像左上角(坐标 (10, 30)),字体类型为 FONT_HERSHEY_SIMPLEX,字体大小为 0.7,颜色为红色 (0, 0, 255),粗细为2。
  • cv2.putText(frame, "EAR: {:.2f}".format(ear), (300, 30), cv2.FONT_HERSHEY_SIMPLEX, 0.7, (0, 0, 255), 2): 显示当前帧中计算的 EAR 值(保留两位小数),显示位置为图像的 (300, 30),格式与上一行相同。这些实时信息有助于用户直观地看到当前检测状态。
5. 视频流结束与资源释放
vs.release()
cv2.destroyAllWindows()

详细解释:

  • vs.release(): 释放视频流对象 vs 占用的资源,确保程序退出时不会发生内存泄漏或资源占用。
  • cv2.destroyAllWindows(): 关闭所有由 OpenCV 创建的窗口。该行代码用于清理与视频流处理相关的可视化窗口,保证程序顺利退出。

6. 模型优缺点评价

优点:

  1. 轻量化与实时性: 本项目采用传统的计算机视觉方法(面部特征点检测与EAR值计算),而非复杂的深度学习模型,能够在普通CPU上实现实时的眨眼检测,具有较低的计算开销,适合于移动设备或嵌入式系统的应用。
  2. 特征工程稳定性: 通过EAR(眼部特征比率)这一简单而有效的几何特征来判断眼睛的开闭状态,避免了传统基于像素点或面积的特征易受光线和噪声干扰的问题。同时,EAR对不同用户的眼部形状具有较好的鲁棒性,适用范围广。
  3. 高可解释性: 使用几何比率来描述眼睛状态,模型输出的EAR值能够直接反映当前眼部状态的变化,使得模型的行为具有较高的可解释性。

缺点:

  1. 对人脸检测器依赖较高: 该项目依赖于Dlib的人脸检测与特征点定位模型,因此在实际应用中,人脸姿态变化、部分遮挡或光照变化会导致特征点定位不准,从而影响EAR的计算结果,导致检测精度下降。
  2. 缺乏深度学习特征表示: EAR值作为单一的几何特征,在处理复杂场景(如快速眨眼、疲劳检测)时可能存在误判,无法有效捕捉更多上下文信息或复杂表情。
  3. 缺乏适应性: EAR阈值与连续帧数阈值是通过人工设定的超参数,对不同用户或不同视频数据源的适应性差,可能需要频繁调整参数。

模型改进方向:

  1. 引入深度学习模型: 考虑使用卷积神经网络(CNN)或更复杂的模型(如LSTM、RNN)来捕捉视频中的时间序列特征,通过端到端训练来提升模型对复杂场景的鲁棒性。
  2. 改进人脸检测与特征点提取方法: 可以引入更先进的面部特征点检测模型(如OpenFace或MediaPipe),提升对不同姿态、光照和遮挡情况的检测效果。
  3. 参数自适应调整: 采用自适应参数调整策略,或通过深度学习模型自动学习不同用户的特征,使系统能够在不同应用场景下自我优化。

↓↓↓更多热门推荐:
transformers和bert实现微博情感分类模型提升
基于ResNet50模型的船型识别与分类系统研究

全部项目数据集、代码、教程进入官网zzgcz.com