1. 摄像头采集到照片,把照片变成gray图像,减少内存读取。
2. 利用人脸检测器,在灰度图像上找到人脸,把图像放大1倍,可以注重图像细节。(这个人脸肯能是多张头像。但是我们通常只是处理一张头像)
detector = dlib.get_frontal_face_detector() # 人脸检测器
3. 利用人脸关键点预测器,找到68个特征点。
predictor = dlib.shape_predictor(r'libs/shape_predictor_68_face_landmarks.dat')
points = face_utils.shape_to_np(shape)
4. 从上述的特征点中,找到左眼和右眼相应的点。
5. 利用 scipy.spatial.distance ,计算欧式距离。
两点之间距离公式
6.利用欧式距离,来计算眼睛的宽高比。宽高比小于一定的阈值 0.3 ,我们认为是眨了一下眼睛了。
7. cv2 有个画轮廓的方法:
cv2.drawContours(frame, [leftEyeHull], -1, (0, 255, 0), 1)
#!/usr/bin/env python # !_*_ coding:utf-8 _*_ from scipy.spatial import distance import dlib import cv2 from imutils import face_utils import numpy as np def eye_aspect_ratio(eye): """ 计算 EAR, 欧式距离。 euclidean:欧式距离 :param eye: 眼部特征点数组 :return: EAR值 """ A = distance.euclidean(eye[1], eye[5]) B = distance.euclidean(eye[2], eye[4]) C = distance.euclidean(eye[0], eye[3]) return (A + B) / (2.0 * C) detector = dlib.get_frontal_face_detector() # 人脸检测器 predictor = dlib.shape_predictor(r'libs/shape_predictor_68_face_landmarks.dat') # 人脸关键点预测器 # 设置眼睛纵横比的阈值 EAR_THRESH = 0.3 # 我们假定连续3帧以上EAR的值都小于阈值,才认为产生了眨眼动作。 EAR_CONSEC_FRAMES = 3 # 人脸特征点中对应眼睛的特征点的序号(36~41;42~47);是从0开始计算的 RIGHT_EYE_START = 36 RIGHT_EYE_END = 41 LEFT_EYE_START = 42 LEFT_EYE_END = 47 frame_counter = 0 # 连续帧的计数 blink_counter = 0 # 眨眼的计数 cap = cv2.VideoCapture(0, cv2.CAP_DSHOW) while True: ret, frame = cap.read() gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY) rects = detector(gray, 1) # 图像放大1倍,注意图像细节 # print(rects) if len(rects) > 0: shape = predictor(gray, rects[0]) # 检测特征点 # 把特征点转换成点的坐标信息 points = face_utils.shape_to_np(shape) leftEye = points[LEFT_EYE_START:LEFT_EYE_END + 1] # 取出左眼的特征点 rightEye = points[RIGHT_EYE_START:RIGHT_EYE_END + 1] leftEAR = eye_aspect_ratio(leftEye) rightEAR = eye_aspect_ratio(rightEye) # 求EAR得平局值 ear = (leftEAR + rightEAR) / 2.0 print(ear) # 找出左眼,右眼的轮廓 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) # 如果ear小于阈值,开始计算连续帧,眨眼次数 if ear < EAR_THRESH: frame_counter += 1 else: if frame_counter >= EAR_CONSEC_FRAMES: print("眨眼检测成功,请进入") blink_counter += 1 break frame_counter = 0 # cv2.putText(frame,"blink:{}".format(blink_counter)) cv2.imshow("window", frame) key = cv2.waitKey(1) if key & 0xFF == ord('q'): break cap.release() cv2.destroyAllWindows()
#!/usr/bin/env python # !_*_ coding:utf-8 _*_ import cv2 import face_recognition from imutils import face_utils from scipy.spatial import distance import numpy as np EAR_THRESH = 0.28 CONTINUE_FRAME = 3 blink_count = 0 def eye_aspect_ratio(eye): A = distance.euclidean(eye[1], eye[5]) B = distance.euclidean(eye[2], eye[4]) C = distance.euclidean(eye[0], eye[3]) return (A + B) / (2.0 * C) cap = cv2.VideoCapture(0, cv2.CAP_DSHOW) while True: ret, frame = cap.read() face_marks = face_recognition.face_landmarks(frame) # print(face_marks) if len(face_marks) > 0: left_eye = face_marks[0]['left_eye'] # print(left_eye) left_eye_np = np.array(left_eye) # print(left_eye_np) right_eye = face_marks[0]['right_eye'] right_eye_np = np.array(right_eye) left_EAR = eye_aspect_ratio(left_eye) right_EAR = eye_aspect_ratio(right_eye) eye_EAR_mean = (left_EAR + right_EAR) / 2.0 print(eye_EAR_mean) leftEyeHull = cv2.convexHull(left_eye_np) rightEyeHull = cv2.convexHull(right_eye_np) cv2.drawContours(frame, [leftEyeHull], -1, (0, 255, 0), 1) cv2.drawContours(frame, [rightEyeHull], -1, (0, 255, 0), 1) if eye_EAR_mean < EAR_THRESH: blink_count += 1 if blink_count > CONTINUE_FRAME: print("眨眼测试成功") blink_count = 0 break cv2.imshow("video", frame) key = cv2.waitKey(5) if key & 0xFF == ord('q'): break cap.release() cv2.destroyAllWindows()