因为某些原因需要眨眼识别,看到这个第一个想到的就是python,但是没接触过这个语言,所以我先看的java的写法,发现挺少。于是开始下载python开始了下载各种软件的道路。。。

原网址

虽然开始是在CSDN上花45积分下载的,但是发现这只是国外大佬写的。在这里给出国外大佬的原网址,就不给CSDN的了(明明人家免费,还在CSDN上卖45积分(小声BB))。

https://www.pyimagesearch.com/2017/04/24/eye-blink-detection-opencv-python-dlib/

问题

原网址上相关配置已经很详细了。在这里我就写我自己碰到的坑。。。

主要是这些opencvnumpy,以及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)的效果图(滑稽图)。


成功は、他人は諦めても、自分は頑張り続ける、というところにある