作者:萝莉控的小潴_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 dlibfrom skimage import iofrom scipy. spatial import distance as distimport matplotlib. pyplot as pltimport numpy as npimport 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 &#61; cv2. VideoCapture( 0 ) cap. set ( 3 , 720 ) isOpen &#61; 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.0 mouth_ear &#61; mouth_aspect_ratio( mouth_points) if t_ear < 0.2 : COUNT &#43;&#61; 1 else : if COUNT >&#61; EYE_AR_CONSEC_FRAMES: TOTAL &#43;&#61; 1 COUNT &#61; 0 if mouth_ear > MAR_THRESH: mCOUNT &#43;&#61; 1 else : if mCOUNT >&#61; MOUTH_AR_CONSEC_FRAMES: mTOTAL &#43;&#61; 1 mCOUNT &#61; 0 for 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( )