因为某些原因需要眨眼识别,看到这个第一个想到的就是python,但是没接触过这个语言,所以我先看的java的写法,发现挺少。于是开始下载python开始了下载各种软件的道路。。。
原网址
虽然开始是在CSDN上花45积分下载的,但是发现这只是国外大佬写的。在这里给出国外大佬的原网址,就不给CSDN的了(明明人家免费,还在CSDN上卖45积分(小声BB))。
https://www.pyimagesearch.com/2017/04/24/eye-blink-detection-opencv-python-dlib/
问题
原网址上相关配置已经很详细了。在这里我就写我自己碰到的坑。。。
主要是这些opencv ,numpy,以及dlib库,scipy库。
除了dlib库其他都是直接按照网上教程直接成功的。
在这就说一下这个安装吧,找了无数的方法。最后成功了,而且还是个超级简单的。。。
首先下载dlib-19.17.0-cp37-cp37m-win_amd64.whl我已经把这个文件放在了蓝奏云。
然后直接安装,在解压好的文件夹的cmd窗口输入下面的就可以了。
pip install 文件名.whl
这里就不配安装好的图了。
wink.py的代码贴出来(原文并没有中文,中文是我机翻的)
# Command line parameters
# python Wink.py --shape-predictor shape_predictor_68_face_landmarks.dat --video your videoname.mp4
# python Wink.py --shape-predictor shape_predictor_68_face_landmarks.dat
# 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
import winsound
def eye_aspect_ratio(eye):
# compute the euclidean distances between the two sets of vertical eye landmarks (x, y)-coordinates
# 计算两组垂直眼界标(x,y)坐标之间的欧几里得距离
A = dist.euclidean(eye[1], eye[5])
B = dist.euclidean(eye[2], eye[4])
# compute the euclidean distance between the horizontal eye landmark (x, y)-coordinates
# 计算水平眼界标(x,y)坐标之间的欧几里得距离
C = dist.euclidean(eye[0], eye[3])
# compute the eye aspect ratio 计算眼睛长宽比
ear = (A + B) / (2.0 * C)
# return the eye aspect ratio 返回眼睛长宽比
return ear
# construct the argument parse and parse the arguments 构造参数解析并解析参数
ap = argparse.ArgumentParser()
ap.add_argument("-p", "--shape-predictor", required=True,
help="path to facial landmark predictor")
ap.add_argument("-v", "--video", type=str, default="",
help="path to input video file")
args = vars(ap.parse_args())
# define two constants, one for the eye aspect ratio to indicate
# blink and then a second constant for the number of consecutive frames the eye must be below the threshold
# 定义两个常数,一个常数表示眼睛的纵横比以指示眨眼,然后定义第二个常数表示眼睛的连续帧数必须低于阈值
EYE_AR_THRESH = 0.25
EYE_AR_CONSEC_FRAMES = 2
# initialize the frame counters and the total number of blinks 初始化帧计数器和闪烁总数
COUNTER = 0
TOTAL = 0
# initialize dlib's face detector (HOG-based) and then create the facial landmark predictor
# 初始化dlib的面部检测器(基于HOG),然后创建面部界标预测器
print("[INFO] loading facial landmark predictor...")
detector = dlib.get_frontal_face_detector()
predictor = dlib.shape_predictor(args["shape_predictor"])
# grab the indexes of the facial landmarks for the left and right eye, respectively
# 分别获取左眼和右眼的面部标志的索引
(lStart, lEnd) = face_utils.FACIAL_LANDMARKS_IDXS["left_eye"]
(rStart, rEnd) = face_utils.FACIAL_LANDMARKS_IDXS["right_eye"]
# start the video stream thread 启动视频流线程
print("[INFO] starting video stream thread...")
# vs = FileVideoStream(args["video"]).start()
fileStream = True
vs = VideoStream(src=0).start()
fileStream = False
time.sleep(1.0)
# loop over frames from the video stream 循环播放视频流中的帧
while True:
# if this is a file video stream, then we need to check if there any more frames left in the buffer to process
# 如果这是文件视频流,那么我们需要检查缓冲区中是否还有剩余的帧要处理
if fileStream and not vs.more():
break
# grab the frame from the threaded video file stream, resize it, and convert it
# to grayscale channels)
# 从线程视频文件流中抓取帧,调整其大小,然后将其转换为灰度通道)
frame = vs.read()
frame = imutils.resize(frame, width=450)
gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
# detect faces in the grayscale frame 在灰度框中检测人脸
rects = detector(gray, 0)
# loop over the face detections 循环人脸检测
for rect in rects:
# determine the facial landmarks for the face region, then convert
# the facial landmark (x, y)-coordinates to a NumPy array
# 确定面部区域的面部界标,然后将面部界标(x,y)坐标转换为NumPy数组
shape = predictor(gray, rect)
shape = face_utils.shape_to_np(shape)
# extract the left and right eye coordinates, then use the coordinates to compute the eye aspect ratio for both eyes
# 提取左眼和右眼坐标,然后使用坐标计算两只眼睛的眼睛纵横比
leftEye = shape[lStart:lEnd]
rightEye = shape[rStart:rEnd]
leftEAR = eye_aspect_ratio(leftEye)
rightEAR = eye_aspect_ratio(rightEye)
# average the eye aspect ratio together for both eyes 将两只眼睛的眼睛纵横比平均在一起
ear = (leftEAR + rightEAR) / 2.0
# compute the convex hull for the left and right eye, then visualize each of the eyes
# 计算左眼和右眼的凸包,然后可视化每只眼睛
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)
# check to see if the eye aspect ratio is below the blink threshold, and if so, increment the blink frame counter
# 检查眼睛宽高比是否低于眨眼阈值,如果是,则增加眨眼帧计数器
if ear < EYE_AR_THRESH:
COUNTER += 1
# otherwise, the eye aspect ratio is not below the blink threshold
# 否则,眼睛纵横比不低于眨眼阈值
else:
# if the eyes were closed for a sufficient number of then increment the total number of blinks
# 如果闭上眼睛的次数足够多,则增加眨眼的总数
if COUNTER >= EYE_AR_CONSEC_FRAMES:
TOTAL += 1
# reset the eye frame counter 重置眼框计数器
COUNTER = 0
# draw the total number of blinks on the frame along with the computed eye aspect ratio for the frame
# 绘制帧上眨眼的总数以及计算出的帧的眼睛纵横比
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.putText(frame, "COUNTER: {}".format(COUNTER), (140, 30),
cv2.FONT_HERSHEY_SIMPLEX, 0.7, (0, 0, 255), 2)
# show the frame show the frame
cv2.imshow("Frame", frame)
key = cv2.waitKey(1) & 0xFF
# if the `q` key was pressed, break from the loop
if key == ord("q"):
break
# do a bit of cleanup
cv2.destroyAllWindows()
vs.stop()
使用
python Wink.py --shape-predictor shape_predictor_68_face_landmarks.dat --video your videoname.mp4
python Wink.py --shape-predictor shape_predictor_68_face_landmarks.dat
效果图
这个可以检测摄像头也可以检测视频里的,我都试过了可以,下面来个视频(周董的说好不哭的MV)的效果图(滑稽图)。