作者:萝莉控的小潴_515 | 来源:互联网 | 2023-12-12 13:27
文章目录引言开发环境和库流程设计张嘴和闭眼的检测引言(1)利用Dlib官方训练好的模型“shape_predictor_68_face_landmarks.dat”进行68个点标定
引言
(1) 利用 Dlib 官方训练好的模型 “shape_predictor_68_face_landmarks.dat” 进行 68 个点标定;
(2)利用 OpenCv 进行图像化处理,在人脸上画出 68 个特征点,并标明特征点的序号实现的 68 个特征点;
(3)根据得到的点位进行简单的活体检测
开发环境和库
1.Window10
2.Anaconda3
3.Python 3.6
4.dlib 19.8.1
5.opencv-python 4.2.0.32 (openCV只是用来画图)
PS:dlib 的pip install 可能需要加上版本号才能成功下载安装
pip install dlib==19.8.1
import dlib
from skimage import io
from scipy.spatial import distance as dist
import matplotlib.pyplot as plt
import numpy as np
import cv2
流程设计
- 68 点提取:
借助 Dlib 官方的 Demo: face_landmark_detection.py,可以得到脸部 68 个特征点的坐标;
- OpenCv 绘图:
使用 opencv 中 画圆函数 cv2.circle() 和 画字符函数 cv2.putText() ;
静态图片的检测
张嘴和闭眼的检测
参考:Eye blink detection with OpenCV, Python, and dlib
公式很简单,就是欧式距离公式,设定好纵横比(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 mouth_aspect_ratio(mouth):A = np.linalg.norm(mouth[2] - mouth[9])B = np.linalg.norm(mouth[4] - mouth[7])C = np.linalg.norm(mouth[0] - mouth[6])mar = (A + B) / (2.0 * C)return mar
还有可调试的常量
EYE_AR_THRESH = 0.2
EYE_AR_CONSEC_FRAMES = 2
MAR_THRESH = 0.5
MOUTH_AR_CONSEC_FRAMES = 3
COUNT = 0
TOTAL = 0
mCOUNT = 0
mTOTAL = 0
r_eye_ear = 0
l_eye_ear = 0
然后我们就可以把视频流的定帧数据输入到我们的函数里面解析,算出各个指标来判断是否触发张嘴闭眼。
cap = cv2.VideoCapture(0)
cap.set(3,720)
isOpen = cap.isOpened()
while isOpen:flag,im_rd &#61; cap.read()k &#61; cv2.waitKey(1)img_gray &#61; cv2.cvtColor(im_rd, cv2.COLOR_RGB2GRAY)faces &#61; detector(img_gray, 0)font &#61; cv2.FONT_HERSHEY_SIMPLEXif len(faces) !&#61; 0:for i in range(len(faces)):landmarks &#61; np.matrix([[p.x, p.y] for p in landmark_predictor(im_rd, faces[i]).parts()])left_eye &#61; landmarks[42:48]right_eye &#61; landmarks[36:41]mouth_points &#61; landmarks[48:68]l_eye_ear &#61; eye_aspect_ratio(left_eye)r_eye_ear &#61; eye_aspect_ratio(left_eye)t_ear &#61; (l_eye_ear &#43;r_eye_ear) / 2.0mouth_ear &#61; mouth_aspect_ratio(mouth_points)if t_ear < 0.2:COUNT &#43;&#61; 1else:if COUNT >&#61; EYE_AR_CONSEC_FRAMES:TOTAL &#43;&#61; 1COUNT &#61; 0if mouth_ear > MAR_THRESH:mCOUNT &#43;&#61; 1else:if mCOUNT >&#61; MOUTH_AR_CONSEC_FRAMES:mTOTAL &#43;&#61; 1mCOUNT &#61; 0for idx,point in enumerate(landmarks):pos &#61; (point[0, 0], point[0, 1])cv2.circle(im_rd, pos, 2, color&#61;(139, 0, 0))cv2.putText(im_rd, "faces: " &#43; str(len(faces)), (20, 20), font, 1, (255,20,147), 1, cv2.LINE_AA)cv2.putText(im_rd, "T_Ear: " &#43; str(t_ear), (20, 40), font, 1, (255,20,147), 1, cv2.LINE_AA)cv2.putText(im_rd, "BlinkNum: " &#43; str(TOTAL), (20, 80), font, 1, (255,20,147), 1, cv2.LINE_AA)cv2.putText(im_rd, "openMouth: " &#43; str(mTOTAL), (20, 100), font, 1, (255,20,147), 1, cv2.LINE_AA)else:cv2.putText(im_rd, "no face", (20, 50), font, 1, (0, 0, 0), 1, cv2.LINE_AA)cv2.putText(im_rd, "Press &#39;q&#39;: Quit", (20, 450),cv2.FONT_HERSHEY_SIMPLEX, 0.7, (0,0,255),)cv2.namedWindow("camera", 0)cv2.imshow("camera", im_rd)if cv2.waitKey(1) & 0xFF &#61;&#61; ord(&#39;q&#39;):break
cap.release()
cv2.destroyAllWindows()