面部区域的面部标志索引
在dlib内部安装有一个面部标志性检测器,可以产生映射到特定面部结构。是一个 68 (x,y)坐标 。通过在标记的iBUG 300-W数据集上训练一个形状预测器获得68点映射。
通过图像,我们可以看到可以通过简单的Python索引来访问面部区域(因为上面的图像是单索引的,所以假设使用Python进行零索引):
右眼用 [36,42],左眼 用 [42,48]
为了实现眨眼检测,需要一个称为眼睛纵横比 (EAR) 的指标,该指标由 Soukupová 和 Čech 在2016 年的论文《使用面部标记的实时眨眼检测》中提出。
三个部分
第一部分,我们将讨论眼睛纵横比以及如何使用它来确定一个人在给定的视频帧中是否在眨眼。
第二部分,编写代码来执行面部标志检测和检测视频流中的眨眼的功能。
第三部分,应用来检测示例网络摄像头流中的眨眼。
眼睛纵横比
每只眼睛由 6 个 (x, y) 坐标表示,从眼睛的左角开始,然后围绕该区域的其余部分顺时针旋转。这些坐标的宽度和高度之间存在关系。反映这种关系的方程,称为眼睛纵横比 (EAR):
其中 p1, ..., p6 是 2D 面部标志位置。该方程的分子计算垂直眼睛界标之间的距离,而分母计算水平眼睛界标之间的距离。眼睛睁开时眼睛的纵横比大致恒定,但在眨眼时会迅速降至零。
使用面部标志和 OpenCV 检测眨眼
首先,打开一个新文件,导入必要的库。
接下来,定义函数,此函数接受单个必需参数,即给定眼睛的面部标志的 (x, y) 坐标。计算两组垂直眼睛界标之间的距离,然后计算水平眼睛界标之间的距离。 最后,结合了分子和分母以得出最终的眼睛纵横比。然后将眼睛纵横比返回给调用函数。脚本需要一个命令行参数:
--shape-predictor :这是 dlib 的预训练面部标志检测器的路径。
在确定视频流中是否发生眨眼时,需要计算眼睛纵横比。如果眼睛纵横比低于某个阈值,然后又高于阈值,那么将注册一个“眨眼”——EYE_AR_THRESH 就是这个阈值。默认它的值为 0.26。然后有一个重要的常量,EYE_AR_CONSEC_FRAME——这个为 3 以指示眼睛纵横比小于3的三个连续帧发生,以便注册眨眼。初始化两个计数器,COUNTER是眼睛纵横比小于 EYE_AR_THRESH 的连续帧的总数,而 TOTAL 是脚本运行时发生的眨眼总数。
然后可以初始化 dlib 的人脸检测器和面部标记检测器:确定开始和结束数组切片索引值,为左眼和右眼提取 (x, y) 坐标。
然后遍历视频流中的帧。如果我们正在访问一个视频文件流并且视频中没有更多的帧,我们就会中断循环。从视频流中读取下一帧,然后调整其大小并将其转换为灰度。然后我们通过 dlib 的内置人脸检测器检测灰度帧中的人脸。我们现在需要遍历帧中的人脸,然后应用面部标志检测:确定面部区域的面部标志,将这些 (x, y) 坐标转换为 NumPy 数组。使用本脚本前面的数组切片技术,我们可以分别提取左眼和右眼的 (x, y) 坐标。然后计算每只眼睛的眼睛纵横比,并将两只眼睛的纵横比平均在一起。
下一步,检查眼睛纵横比是否低于眨眼阈值——如果是增加指示正在发生眨眼的连续帧的数量。 否则,处理眼睛纵横比不低于眨眼阈值的情况。在这种情况下,再次检查以查看是否有足够数量的连续帧包含低于预定义阈值的眨眼率。如果检查通过,增加闪烁的总次数。 然后重置连续闪烁的次数 COUNTER。 最终代码块只是处理在我们的输出帧上绘制眨眼次数,以及显示当前眼睛纵横比。
检测眨眼结果
20211218_220322