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


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 += 1COUNTER = 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

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/455024.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Python 实现 excel 数据过滤

一、场景分析 假设有如下一份 excel 数据 shop.xlsx, 写一段 python 程序&#xff0c;实现对于车牌的分组数据过滤。 并以车牌为文件名&#xff0c;把店名输出到 车牌.txt 文件中。 比如 闽A.txt 文件内容为&#xff1a; 小林书店福州店1 小林书店福州店2 二、依赖安装 程序依…

【C++】拆分详解 - 模板

文章目录 一、泛型编程二、函数模板1. 概念2. 语法3. 函数模板的原理4. 函数模板的实例化5. 模板参数的匹配原则 三、类模板1. 语法2. 实例化 四、模板的特化1. 概念2. 函数模板特化3. 类模板特化3.1 全特化3.2 偏特化 / 半特化3.3 应用示例 4. 小结 五、模板的分离编译1. 分离…

Java:抽象类和接口

一.抽象类 1.抽象类概念和语法 ⨀概念&#xff1a; 在面向对象的概念中&#xff0c;所有的对象都是通过类来描绘的&#xff0c;但是并不是所有的类都是用来描绘对象的&#xff0c;如果一个类中没有包含足够的信息来描绘一个具体的对象&#xff0c;这样的类就是抽象类。 ⨀语…

JMeter使用不同方式传递接口参数

1、使用 HTTP 请求中的参数&#xff1a; 在 JMeter 的测试计划中&#xff0c;添加一个 "HTTP 请求" 元件。 在 "HTTP 请求" 元件的参数化选项中&#xff0c;可以添加参数的名称和值。可以手动输入参数&#xff0c;也可以使用变量来传递参数值。 如果要使…

Golang | Leetcode Golang题解之第497题非重叠矩形中的随机点

题目&#xff1a; 题解&#xff1a; type Solution struct {rects [][]intsum []int }func Constructor(rects [][]int) Solution {sum : make([]int, len(rects)1)for i, r : range rects {a, b, x, y : r[0], r[1], r[2], r[3]sum[i1] sum[i] (x-a1)*(y-b1)}return Sol…

自定义多级联动选择器指南(uni-app)

多端支持&#xff1a;可以运行在H5、APP、微信小程序还是支付宝小程序&#xff0c;都可以轻松使用改组件。自定义配置&#xff1a;您可以根据需要配置选择器的级数&#xff0c;使其适应不同的数据结构和用例。无限级联&#xff1a;此组件支持无限级联选择&#xff0c;使您能够创…

最好的ppt模板网站是哪个?做PPT不可错过的18个网站!

现在有很多PPT模板网站&#xff0c;但真正免费且高质量的不多&#xff0c;今天我就分享主流的国内外PPT模板下载网站&#xff0c;并且会详细分析这些网站的优缺点&#xff0c;这些网站都是基于个人实际使用经验的&#xff0c;免费站点会特别标注&#xff0c;让你可以放心下载&a…

信息安全工程师(64)其他恶意代码分析与防护

前言 恶意代码是指那些能够损害系统用户和系统所有者利益的软件&#xff0c;是故意在计算机系统上执行恶意任务的恶意代码的集合。 一、恶意代码分析 病毒&#xff08;Virus&#xff09; 定义&#xff1a;病毒是一种人为制造的、能够进行自我复制的、具有对计算机资源的破坏作用…

国家信息安全水平考试(NISP一级)最新题库-第十七章

目录 另外免费为大家准备了刷题小程序和docx文档&#xff0c;有需要的可以私信获取 1 受到了ARP欺骗的计算机&#xff0c;发出的数据包&#xff0c;     地址是错误的&#xff08;&#xff09; A.源IP&#xff1b;B.目的IP&#xff1b;C.源MAC&#xff1b;D.目的MAC 正…

rust入门基础总结

文章目录 前言1、输出格式规范一、占位符相关&#xff08;一&#xff09;{}与{:?} 二、参数替换方式&#xff08;一&#xff09;位置参数&#xff08;二&#xff09;具名参数 三、格式化参数&#xff08;一&#xff09;宽度&#xff08;二&#xff09;对齐&#xff08;三&…

基于K8S的StatefulSet部署mysql主从

StatefulSet特性 StatefulSet的网络状态 拓扑状态&#xff1a;应用的多个实例必须按照某种顺序启动&#xff0c;并且必须成组存在&#xff0c;例如一个应用中必须存在一个A Pod和两个B Pod&#xff0c;且A Pod必须先于B Pod启动的场景 存储状态&#xff1a;应用存在多个实例&…

Golang | Leetcode Golang题解之第500题键盘行

题目&#xff1a; 题解&#xff1a; func findWords(words []string) (ans []string) {const rowIdx "12210111011122000010020202" next:for _, word : range words {idx : rowIdx[unicode.ToLower(rune(word[0]))-a]for _, ch : range word[1:] {if rowIdx[unico…

【Redis】数据结构(下)

文章目录 QuickList概念QuickList结构QuickList的特点控制ZipList的大小对节点的ZipList进行压缩 总结 SkipList概念源码中结构分析总结 QuickList 概念 问题1:ZipList虽然节省内存,但是申请的内存必须是连续空间,如果内存占用过多,申请内存效率低,怎么办? 为了缓解这个问题,…

可编辑38页PPT | 柔性制造企业数字化转型与智能工厂建设方案

荐言分享&#xff1a;在数字化技术快速发展的今天&#xff0c;传统的大规模生产模式已难以满足市场对个性化、定制化产品的需求。柔性制造以其灵活多变、快速响应的特点&#xff0c;成为制造业转型升级的关键。通过数字化转型与智能工厂建设&#xff0c;企业可以构建高效、灵活…

Llama Tutor:开源 AI 个性化学习平台,根据主题自动制定学习计划

❤️ 如果你也关注大模型与 AI 的发展现状&#xff0c;且对大模型应用开发非常感兴趣&#xff0c;我会快速跟你分享最新的感兴趣的 AI 应用和热点信息&#xff0c;也会不定期分享自己的想法和开源实例&#xff0c;欢迎关注我哦&#xff01; &#x1f966; 微信公众号&#xff…

Centos7 将man手册内容转换为txt,pdf访问,并汉化

转换为txt格式 直接将man的输出导入到txt文档即可&#xff0c;使用col -b 删除掉特殊字符方便阅读 # man ps | col -b > ps.txt转换为pdf格式 使用 groff 将 man 页转换为 PostScript 格式&#xff0c;然后使用 ps2pdf 转换为 PDF&#xff1a; 下载ps2pdf 命令工具包&am…

8阻塞队列

阻塞队列能是⼀种 线程安全的数据结构 , 并且具有以下特性: • 当队列满的时候, 继续⼊队列就会阻塞, 直到有其他线程从队列中 取⾛ 元素. • 当队列空的时候, 继续出队列也会阻塞, 直到有其他线程往队列中 插⼊ 元素 标准库中的阻塞队列 在 Java 标准库中内置了阻塞队列. …

与ai一起作诗(《校园清廉韵》)

与ai对话犹如拷问自己的灵魂&#xff0c;与其说ai助力还不如说在和自己对话。 (笔记模板由python脚本于2024年10月19日 19:18:33创建&#xff0c;本篇笔记适合喜欢python和诗歌的coder翻阅) 【学习的细节是欢悦的历程】 Python 官网&#xff1a;https://www.python.org/ Free&…

NGINX 保护 Web 应用安全之基于 IP 地址的访问

根据客户端的 IP 地址控制访问 使用 HTTP 或 stream 访问模块控制对受保护资源的访问&#xff1a; location /admin/ { deny 10.0.0.1; allow 10.0.0.0/20; allow 2001:0db8::/32; deny all; } } 给定的 location 代码块允许来自 10.0.0.0/20 中的任何 IPv4 地址访问&#xf…