眼睛纵横比(EAR)

在讨论EAR之前,先看看68个人脸特征点: 


人脸特征点检测本身的算法是很复杂的,dlib中给出了相关的实现。

每只眼睛由6个(x,y)坐标表示,从眼睛的左角开始,然后围绕该区域的其余部分顺时针显示:

基于这个描述,我们应该抓住重点:这些坐标的宽度高度之间有一个关系。

Soukupová和Čech在其2016年的论文“使用面部标志实时眼睛眨眼检测”的工作,我们可以推导出反映这种关系的方程,称为眼睛纵横比(EAR):

其中p1,...,p6是2D面部地标位置。

这个方程的分子是计算垂直眼睛标志之间的距离,而分母是计算水平眼睛标志之间的距离,因为只有组水平点,但是两组垂直点,所以进行加权分母。

为什么这个方程如此有趣?

我们将会发现,眼睛的长宽比在眼睛张开的时候大致是恒定的,但是在发生眨眼时会迅速下降到零。

使用这个简单的方程,我们可以避免使用图像处理技术简单地依靠眼睛地标距比例来确定一个人是否眨眼。

为了更清楚地说明,看下面的图:

底部图中绘出了眼纵横比随时间的视频剪辑的曲线图。正如我们所看到的,眼睛纵横比是恒定的,然后迅速下降到接近零,然后再增加,表明一个单一的眨眼已经发生。

代码实现

# -*- coding: utf-8 -*-
# import the necessary packages
from scipy.spatial import distance as dist
from imutils.video import FileVideoStream
from imutils.video import VideoStream
from imutils import face_utils
import numpy as np
import argparse
import imutils
import time
import dlib
import cv2 def eye_aspect_ratio(eye):
# 计算两个集合之间的欧几里得距离
# 垂直眼标志(X,Y)坐标
A = dist.euclidean(eye[1], eye[5])
B = dist.euclidean(eye[2], eye[4])
# 计算水平之间的欧几里得距离
# 水平眼标志(X,Y)坐标
C = dist.euclidean(eye[0], eye[3])
# 眼睛长宽比的计算
ear = (A + B) / (2.0 * C)
# 返回眼镜的长宽比
return ear # 定义两个常数
# 眼睛长宽比
# 闪烁阈值
EYE_AR_THRESH = 0.2
EYE_AR_CONSEC_FRAMES = 3
# 初始化帧计数器和眨眼总数
COUNTER = 0
TOTAL = 0 # 初始化DLIB的人脸检测器(HOG),然后创建面部标志物预测
print("[INFO] loading facial landmark predictor...")
detector = dlib.get_frontal_face_detector()
predictor = dlib.shape_predictor('shape_predictor_68_face_landmarks.dat') # 分别获取左右眼面部标志的索引
(lStart, lEnd) = face_utils.FACIAL_LANDMARKS_IDXS["left_eye"]
(rStart, rEnd) = face_utils.FACIAL_LANDMARKS_IDXS["right_eye"] cap = cv2.VideoCapture(1) # 从视频流循环帧
while True:
ret, frame = cap.read() gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
# 检测灰度帧中的人脸
rects = detector(gray, 0) # 人脸检测循环
for rect in rects:
# 确定脸部区域的面部标志,然后将面部标志(x,y)坐标转换为数字阵列
shape = predictor(gray, rect)
shape = face_utils.shape_to_np(shape)
# 提取左眼和右眼坐标,然后使用坐标计算双眼的眼睛长宽比
leftEye = shape[lStart:lEnd]
rightEye = shape[rStart:rEnd]
leftEAR = eye_aspect_ratio(leftEye)
rightEAR = eye_aspect_ratio(rightEye)
# 双眼平均长宽比
ear = (leftEAR + rightEAR) / 2.0 # 计算左眼和右眼的标志点并绘制
leftEyeHull = cv2.convexHull(leftEye)
rightEyeHull = cv2.convexHull(rightEye)
cv2.drawContours(frame, [leftEyeHull], -1, (0, 255, 0), 1)
cv2.drawContours(frame, [rightEyeHull], -1, (0, 255, 0), 1) # 在图片中标注人脸,并显示
left = rect.left()
top = rect.top()
right = rect.right()
bottom = rect.bottom()
cv2.rectangle(frame, (left, top), (right, bottom), (0, 255, 0), 3) '''
第一步检查眼睛纵横比是否低于我们的眨眼阈值,如果是,我们递增指示正在发生眨眼的连续帧数。否则,我们将处理眼高宽比不低于眨眼阈值的情况,我们对其进行检查,
看看是否有足够数量的连续帧包含低于我们预先定义的阈值的眨眼率。如果检查通过,我们增加总的闪烁次数。然后我们重新设置连续闪烁次数 COUNTER。
'''
if ear < EYE_AR_THRESH:
COUNTER += 1
else:
# 如果眼睛闭合足够数量,那么眨眼总数增加
if COUNTER >= EYE_AR_CONSEC_FRAMES:
TOTAL += 1
# 重置眼帧计数器
COUNTER = 0 for (x, y) in shape:
cv2.circle(frame, (x, y), 1, (0, 0, 255), -1) cv2.putText(frame, "COUNTER: {}".format(COUNTER), (150, 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)
cv2.putText(frame, "EAR: {:.2f}".format(ear), (300, 30),
cv2.FONT_HERSHEY_SIMPLEX, 0.7, (0, 0, 255), 2) cv2.imshow("Frame", frame)
print(len(rects))
# if the `q` key was pressed, break from the loop
if cv2.waitKey(1) & 0xFF == ord('q'):
break # do a bit of cleanup
cv2.destroyAllWindows()

效果

dlib 基于摄像流检测眨眼次数的更多相关文章

  1. 使用C#处理基于比特流的数据

    使用C#处理基于比特流的数据 0x00 起因 最近需要处理一些基于比特流的数据,计算机处理数据一般都是以byte(8bit)为单位的,使用BinaryReader读取的数据也是如此,即使读取bool型 ...

  2. python dlib 面部轮廓实时检测

    1.dlib 实现动态人脸检测及面部轮廓检测 模型下载连接 : http://dlib.net/files/ # coding:utf-8 import cv2 import os import dl ...

  3. 老猿学5G:融合计费基于QoS流计费QBC的触发器Triggers

    ☞ ░ 前往老猿Python博文目录 ░ 一.引言 SMF中的功能体CTF在用户上网时达到一定条件就会向CHF上报流量,而CTF什么时候触发流量上报是由CTF中的触发器来控制的.在<老猿学5G: ...

  4. 使用dlib基于CNN(卷积神经网络)的人脸检测器来检测人脸

    基于机器学习CNN方法来检测人脸比之前介绍的效率要慢很多 需要先下载一个训练好的模型数据: 地址点击下载 // dlib_cnn_facedetect.cpp: 定义控制台应用程序的入口点. // # ...

  5. HAAR与DLib的实时人脸检测之实现与对比

    人脸检测方法有许多,比如opencv自带的人脸Haar特征分类器和dlib人脸检测方法等. 对于opencv的人脸检测方法,优点是简单,快速:存在的问题是人脸检测效果不好.正面/垂直/光线较好的人脸, ...

  6. 思科恶意加密TLS流检测论文记录——由于样本不均衡,其实做得并不好,神马99.9的准确率都是浮云啊,之所以思科使用DNS和http一个重要假设是DGA和HTTP C&C(正常http会有图片等)。一开始思科使用的逻辑回归,后面17年文章是随机森林。

    论文记录:Identifying Encrypted Malware Traffic with Contextual Flow Data from:https://songcoming.github. ...

  7. https ddos攻击——由于有了认证和加解密 后果更严重 看绿盟的产品目前对于https的ddos cc攻击需要基于内容做检测

    如果web服务器支持HTTPS,那么进行HTTPS洪水攻击是更为有效的一种攻击方式,一方面,在进行HTTPS通信时,web服务器需要消耗更多的资源用来进行认证和加解密,另一方面,一部分的防护设备无法对 ...

  8. 利用ML&AI判定未知恶意程序——里面提到ssl恶意加密流检测使用N个payload CNN + 字节分布包长等特征综合判定

    利用ML&AI判定未知恶意程序 导语:0x01.前言 在上一篇ML&AI如何在云态势感知产品中落地中介绍了,为什么我们要预测未知恶意程序,传统的安全产品已经无法满足现有的安全态势.那么 ...

  9. dlib VS2013 face关键点检测与对齐

    http://blog.csdn.net/hust_bochu_xuchao/article/details/53906223 http://blog.csdn.net/xiamentingtao/a ...

随机推荐

  1. java23种设计模式(五)--组合模式

    转载:https://www.cnblogs.com/V1haoge/p/6489827.html定义:所谓组合模式,其实说的是对象包含对象的问题,通过组合的方式(在对象内部引用对象)来进行布局,我认 ...

  2. loj2542 「PKUWC2018」随机游走 MinMax 容斥+树上高斯消元+状压 DP

    题目传送门 https://loj.ac/problem/2542 题解 肯定一眼 MinMax 容斥吧. 然后问题就转化为,给定一个集合 \(S\),问期望情况下多少步可以走到 \(S\) 中的点. ...

  3. nodejs部署配置pm2

    高大上先上部署node方式: 直接通过node app来启动,如果报错了可能直接停在整个运行, supervisor感觉只是拿来用作开发环境的. 目前似乎最常见的线上部署nodejs项目的有forev ...

  4. Vue学习笔记-插槽基本使用

    为了让我们的组件更加具有扩展性,可以使用插槽 <div id="app"> <cpn> <span>返回</span> <in ...

  5. 报错——userdel: user hhh is currently used by process 9218

    报错 userdel: user hhh is currently used by process 9218 [root@centos71 ~]# useradd hhh [root@centos71 ...

  6. 线程join方法demo-模拟叫号看病

    package cn.chapter4.test5; public class SicknessDemo { /** * 模拟叫号看病 * @param args * * 思路:把普通号看病写在主线程 ...

  7. (转载)虚拟机出现无法连接虚拟设备sata0:0,因为主机上没有相应设备

    虚拟主机需要镜像文件, 如果是拷贝的虚拟机,还需要桥接联网的话,更改mac地址,

  8. 北风设计模式课程---20、UML类图介绍

    北风设计模式课程---20.UML类图介绍 一.总结 一句话总结: 不仅要通过视频学,还要看别的博客里面的介绍,搜讲解,搜作用,搜实例 设计模式都是对生活的抽象,比如用户获得装备,我可以先装备工厂先生 ...

  9. 用.NET做圣诞节音乐盒

    用.NET做圣诞节音乐盒 我曾经用这个程序送给我女朋友(现老婆)

  10. 通过export方式导出,在导入时要加{ },export default则不需要

    怎么就是记不住呢?? 通过export方式导出,在导入时要加{ },export default则不需要