赞
踩
与用于计算眨眼的传统图像处理方法不同,该方法通常涉及以下几种组合:
1、眼睛定位。
2、阈值找到眼睛的白色。
3、确定眼睛的“白色”区域是否消失了一段时间(表示眨眼)。
相反,眼睛长宽比是一种更为优雅的解决方案,它涉及基于眼睛面部轮廓之间的距离之比的非常简单的计算。
这种眨眼检测方法快速,高效且易于实现。
我们可以应用脸部界标检测来定位脸部重要区域,包括眼睛,眉毛,鼻子,耳朵和嘴巴
这也意味着我们可以通过了解特定面部部分的索引来提取特定面部结构:
在眨眼检测方面,我们只对两套面部结构感兴趣:眼睛。
每只眼睛都由6 (x,y)坐标表示,从坐标的左角开始(就像您在看那个人一样),然后沿该区域的其余部分顺时针旋转:
基于此图像,我们应该取消关键点:
这些坐标的宽度和高度之间存在关系。
根据Soukupová和Čech在2016年的论文《使用面部地标进行实时眼睛眨眼检测》的工作,我们可以得出一个反映这种关系的方程,称为眼睛纵横比(EAR):
其中p1,…,p6是2D面部界标位置。
该方程的分子计算垂直眼界标之间的距离,而分母计算水平眼界标之间的距离,对分母进行适当加权,因为只有一组水平点,但有两组垂直点。
睁开眼睛时眼睛的纵横比大约是恒定的,但是当眨眼时眼睛的纵横比会迅速降至零。
使用这个简单的方程式,我们可以避免使用图像处理技术,而只需依靠眼睛界标距离的比率来确定一个人是否在眨眼。
为了更清楚地说明这一点,请看下图:
图: 左上:当眼睛睁开时,眼睛界标的可视化。右上:闭上眼睛时的眼睛地标。底部:绘制随时间变化的眼睛纵横比。眼睛纵横比的下降表示眨眼
在左上角,我们的眼睛完全张开-此处的眼睛长宽比会很大(r),并且随着时间的推移会相对保持恒定。
但是,一旦眨眼(右上角),眼睛的宽高比就会急剧下降,接近零。
在底部图中绘出了眼纵横比随时间的视频剪辑的曲线图。如我们所见,眼睛的纵横比是恒定的,然后迅速下降到接近零,然后再次增加,表明已经发生了一次眨眼。
我实在 基于英伟达定制的jetson nano ubuntu18.04系统上跑的,以下是我的版本信息,理论上ubuntu 和MacOS都跑的起来 关键opencv和dlib以及相关库安装好,相关安装自行解决。
要访问我们在磁盘上的视频文件(FileVideoStream )或内置的网络摄像头/ USB摄像头/ Raspberry Pi摄像头模块(视频流),我们需要使用我的imutils库(一组便捷函数)来简化OpenCV的使用。
如果没有安装imutils在系统上(或者如果您使用的是旧版本),请确保使用以下命令进行安装/升级:
pip3 install --upgrade imutils
首先,打开一个新文件并命名 detect_blinks.py。从那里,插入以下代码:
接下来,我们将定义 eye_aspect_ratio 功能
该函数接受单个必需参数,即给定脸部界标的(x,y)-坐标眼睛 。
第16和17行计算两组垂直眼界标之间的距离,而第21行计算水平眼界标之间的距离。
最后,第24行结合了分子和分母,以得出最终的眼睛长宽比,如上面的图4中所述。
然后,第27行将眼睛的宽高比返回给调用函数。
让我们继续分析我们的命令行参数:
我们的 detect_blinks。py 脚本需要一个命令行参数,然后是第二个可选参数:
–shape_predictor:这是dlib预先训练的面部标志检测器的路径。
–video:此可选开关控制驻留在磁盘上的输入视频文件的路径。如果您想使用实时视频流,只需在执行脚本时忽略此开关即可。
现在,我们需要设置两个重要的常量,您可能需要针对自己的实现进行调整,并初始化其他两个重要的变量
在确定视频流中是否发生眨眼时,我们需要计算眼睛的宽高比。
如果眼睛的宽高比下降到某个阈值以下,然后又上升到该阈值以上,那么我们将注册“眨眼”- EYE_AR_THRESH 是此阈值。我们将其默认设置为0. 3 因为这对我的应用程序最有效,但是您可能需要针对自己的应用程序进行调整。
然后我们有一个重要的常数, EYE_AR_CONSEC_FRAME —此值设置为 3 表示连续三个帧的眼睛长宽比小于EYE_AR_THRESH 必须进行眨眼才能注册眨眼。
同样,根据流水线的帧处理吞吐率,您可能需要为自己的实现提高或降低此数字。
第44和45行初始化两个计数器。柜台 是眼睛长宽比小于的连续帧的总数 EYE_AR_THRESH 尽管 全部的 是脚本运行期间发生的总闪烁次数。
现在我们已经处理了导入,命令行参数和常量,现在可以初始化dlib的人脸检测器和人脸界标检测器:
dlib库使用预训练的面部检测器,该检测器基于对“定向梯度直方图+线性SVM”方法的修改,用于对象检测。
然后,我们在第51行初始化实际的面部界标预测变量。
dlib生成的面部标志遵循一个可索引列表
因此,我们可以为下面的左眼和右眼确定用于提取(x,y)-坐标的开始和结束数组切片索引值:
使用这些索引,我们将能够轻松提取眼睛区域。
接下来,我们需要确定是否要使用基于文件的视频流或实时USB /网络摄像头/ Raspberry Pi摄像机视频流:
如果您使用的是文件视频流,则将代码保持原样。
否则,如果要使用内置网络摄像头或USB摄像头,请取消注释第62行。
对于Raspberry Pi相机模块,请取消注释第63行。
如果你有没有注释或者 行62或63号线,然后取消注释行64以及以表明你是不是从磁盘读取视频文件。
最后,我们到达了脚本的主循环:
在第68行,我们开始循环播放视频流中的帧。
如果我们正在访问视频文件流,并且视频中没有剩余的帧,那么我们将退出循环(第71和72行)。
第77行从视频流中读取下一帧,然后调整其大小并将其转换为灰度(第78和79行)。
然后,我们通过dlib的内置面部检测器在82行的灰度帧中检测面部。
现在,我们需要遍历框架中的每个面孔,然后对每个面孔应用脸部界标检测:
第89行确定了面部区域的面部界标,而第90行将这些(x,y)坐标转换为NumPy数组。
使用本脚本前面的数组切片技术,我们可以分别提取左眼和右眼的(x,y)坐标(第94和95行)。
从那里,我们在第96和97行上计算每只眼睛的眼睛纵横比。
根据Soukupová和Čech的建议,我们将两只眼睛的长宽比平均在一起,以获得更好的眨眼估计(当然,假设一个人同时眨眼了)。
我们的下一个代码块仅处理可视化眼睛区域本身的面部标志:
至此,我们已经计算了(平均)眼睛长宽比,但实际上还没有确定是否发生眨眼,这将在下一部分中解决:
第111行进行检查以查看眼睛长宽比是否低于眨眼阈值-如果是,则增加表示眨眼发生的连续帧数(第112行)。
否则,线116处理眼睛宽高比不低于眨眼阈值的情况。
在这种情况下,我们在119行进行另一次检查,以查看是否有足够数量的连续帧包含眨眼比率低于我们预先定义的阈值。
如果检查通过,我们将增加 全部的 眨眼次数(第120行)。
然后,我们重置连续闪烁的次数 柜台 (第123行)。
我们的最终代码块仅用于在输出帧上绘制眨眼次数,并显示当前的眼睛长宽比:
要查看我们的眨眼检测器的运行情况,请继续进行下一部分。
眨眼检测结果
要将眨眼检测器应用于示例视频,只需执行以下命令:
python detect_blinks.py \
--shape-predictor shape_predictor_68_face_landmarks.dat \
--video blink_detection_demo.mp4
要访问我的内置网络摄像头,我执行了以下命令(注意取消对正确注释的注释)。 视频流 类,如上所述):
python detect_blinks.py \
--shape-predictor shape_predictor_68_face_landmarks.dat
这里我们测试一段摄像头和一段网上下载的video:
后面未设置参数
参考
要将眨眼检测器应用于示例视频,只需执行以下命令:
python detect_blinks.py \
--shape-predictor shape_predictor_68_face_landmarks.dat \
--video blink_detection_demo.mp4
要访问我的内置网络摄像头,我执行了以下命令(注意取消对正确注释的注释)。 视频流 类,如上所述):
python detect_blinks.py \
--shape-predictor shape_predictor_68_face_landmarks.dat
检查文件路径、检查示例视频源是否能正常播放解析,尝试换一段示例视频。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。