引言

(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

# -*- coding: UTF-8 -*-
import dlib
from skimage import io
from scipy.spatial import distance as dist
import matplotlib.pyplot as plt
import numpy as np
import cv2

流程设计

  1. 68 点提取:

借助 Dlib 官方的 Demo: face_landmark_detection.py,可以得到脸部 68 个特征点的坐标;

  1. OpenCv 绘图:

使用 opencv 中 画圆函数 cv2.circle() 和 画字符函数 cv2.putText() ;
静态图片的检测
在这里插入图片描述

张嘴和闭眼的检测

参考:Eye blink detection with OpenCV, Python, and dlib
公式很简单,就是欧式距离公式,设定好纵横比(EAR)。

def eye_aspect_ratio(eye):
    # 垂直眼标志(X,Y)坐标
    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:
    #cap.read()
    #返回两个值:
    #一个布尔值 true/false,用来判断读取视频是否成功/是否到视频末尾
    #图像对象,图像的三维矩阵
    flag,im_rd = cap.read()
    # 每帧数据延时 1ms,延时为 0 读取的是静态帧
    k = cv2.waitKey(1)
    img_gray = cv2.cvtColor(im_rd, cv2.COLOR_RGB2GRAY)
    faces = detector(img_gray, 0)
    font = cv2.FONT_HERSHEY_SIMPLEX
    # 标点
    if len(faces) != 0:
        # 检测到人脸
        for i in range(len(faces)):
            landmarks  = np.matrix([[p.x, p.y] for p in landmark_predictor(im_rd, faces[i]).parts()])
            left_eye = landmarks[42:48]
            right_eye = landmarks[36:41]
            mouth_points = landmarks[48:68]
            #print(left_eye)
            l_eye_ear = eye_aspect_ratio(left_eye)
            r_eye_ear = eye_aspect_ratio(left_eye)
            t_ear = (l_eye_ear +r_eye_ear) / 2.0
            mouth_ear = mouth_aspect_ratio(mouth_points)
            if t_ear < 0.2:
                COUNT += 1
            else:
                if COUNT >= EYE_AR_CONSEC_FRAMES:
                    TOTAL += 1
                COUNT = 0
            if mouth_ear > MAR_THRESH:
                mCOUNT += 1
            else:
                if mCOUNT >= MOUTH_AR_CONSEC_FRAMES:
                    mTOTAL += 1
                mCOUNT = 0
            for idx,point in enumerate(landmarks):
                # 68点打印
                pos = (point[0, 0], point[0, 1])
                #利用 cv2.circle 给每个特征点画一个圈,共 68 个
                cv2.circle(im_rd, pos, 2, color=(139, 0, 0))
                # 利用 cv2.putText 输出 1-68
                #cv2.putText(im_rd, str(idx + 1), pos, font, 0.2, (187, 255, 255), 1, cv2.LINE_AA)
        cv2.putText(im_rd, "faces: " + str(len(faces)), (20, 20), font, 1, (255,20,147), 1, cv2.LINE_AA)
        #cv2.putText(im_rd, "L_Eye_Ear: " + str(l_eye_ear), (20, 60), font, 1, (0, 0, 0), 1, cv2.LINE_AA)
        #cv2.putText(im_rd, "R_Eye_Ear: " + str(r_eye_ear), (20, 90), font, 1, (0, 0, 0), 1, cv2.LINE_AA)
        cv2.putText(im_rd, "T_Ear: " + str(t_ear), (20, 40), font, 1, (255,20,147), 1, cv2.LINE_AA)
        cv2.putText(im_rd, "BlinkNum: " + str(TOTAL), (20, 80), font, 1, (255,20,147), 1, cv2.LINE_AA)
        cv2.putText(im_rd, "openMouth: " + 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 'q': 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 == ord('q'):
        break
cap.release()
cv2.destroyAllWindows()
点击阅读全文
Logo

腾讯云面向开发者汇聚海量精品云计算使用和开发经验,营造开放的云计算技术生态圈。

更多推荐