返回

睁眼、闭眼,眨眼就在一瞬间——利用OpenCV、Python和dlib构建眨眼检测器

人工智能

我们经常说“一眨眼”,用来形容时间短暂。眼睛的闭合和睁开,只是一个眨眼之间的事情。我们的大脑常常是通过眼睛来对世界进行观察,眼睛是心灵的窗口。与此同时,神经系统会对眼睛进行监测和控制,所以闭眼和睁眼也代表着不同的神经信息。
在人机交互领域,眨眼是一个重要的非语言沟通信号,也是一种人机交互方式。例如,我们可以在人机交互系统中通过眨眼来进行一些简单的操作。
那么问题来了,要如何进行眨眼检测呢?我们需要对眼睛进行建模,确定眼睛模型。这样我们就可以对摄像头画面中的眼睛进行检测,然后就可以进行眨眼检测了。我们常见的眨眼检测方法有两种:

  • 基于眼睑检测的眨眼检测
  • 基于眼睛纵横比的眨眼检测
    我们重点介绍第二种方法,基于眼睛纵横比的眨眼检测 。为了进一步确定眨眼,我们在文章的后半部分中进一步融合了相关性判断和阈值判断

接下来,让我们开启眨眼检测实战之旅。我们将使用OpenCV、Python和dlib三个强大的工具,带领你一步步构建一个眨眼检测器。

  1. 导入必要的库
import cv2
import dlib
import numpy as np
  1. 加载预训练的人脸检测模型和面部关键点检测模型
face_detector = dlib.get_frontal_face_detector()
landmark_predictor = dlib.shape_predictor("shape_predictor_68_face_landmarks.dat")
  1. 初始化一些变量
EAR_THRESH = 0.2
EYE_ASPECT_RATIO_COUNTER = 0
TOTAL = 0
  • EAR_THRESH:眼睛纵横比阈值,当眼睛纵横比小于该阈值时,我们认为眼睛是闭合的。
  • EYE_ASPECT_RATIO_COUNTER:眼睛纵横比计数器,用于计算连续闭合眼睛的帧数。
  • TOTAL:总眨眼次数。
  1. 打开摄像头
cap = cv2.VideoCapture(0)
  1. 开始视频流处理循环
while True:
    # 读取帧
    ret, frame = cap.read()

    # 将帧转换为灰度图像
    gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)

    # 检测人脸
    faces = face_detector(gray)

    # 遍历人脸
    for face in faces:
        # 检测面部关键点
        landmarks = landmark_predictor(gray, face)

        # 计算眼睛纵横比
        left_eye_start = landmarks.part(36)
        left_eye_end = landmarks.part(39)
        right_eye_start = landmarks.part(42)
        right_eye_end = landmarks.part(45)

        left_eye_width = np.linalg.norm(np.array([left_eye_start.x, left_eye_start.y]) - np.array([left_eye_end.x, left_eye_end.y]))
        right_eye_width = np.linalg.norm(np.array([right_eye_start.x, right_eye_start.y]) - np.array([right_eye_end.x, right_eye_end.y]))

        left_eye_height = np.linalg.norm(np.array([left_eye_start.x, left_eye_start.y]) - np.array([landmarks.part(37).x, landmarks.part(37).y]))
        right_eye_height = np.linalg.norm(np.array([right_eye_start.x, right_eye_start.y]) - np.array([landmarks.part(43).x, landmarks.part(43).y]))

        left_ear = left_eye_width / left_eye_height
        right_ear = right_eye_width / right_eye_height

        ear = (left_ear + right_ear) / 2.0

        # 检测眨眼
        if ear < EAR_THRESH:
            EYE_ASPECT_RATIO_COUNTER += 1

            # 检测到连续闭合眼睛的帧数超过阈值,则认为是一个眨眼
            if EYE_ASPECT_RATIO_COUNTER >= 3:
                TOTAL += 1
                EYE_ASPECT_RATIO_COUNTER = 0

        else:
            EYE_ASPECT_RATIO_COUNTER = 0

        # 在帧上绘制眼睛纵横比和眨眼次数
        cv2.putText(frame, "EAR: {:.2f}".format(ear), (300, 30), cv2.FONT_HERSHEY_SIMPLEX, 0.7, (0, 255, 0), 2)
        cv2.putText(frame, "Blinks: {}".format(TOTAL), (300, 60), cv2.FONT_HERSHEY_SIMPLEX, 0.7, (0, 255, 0), 2)

    # 显示帧
    cv2.imshow("Frame", frame)

    # 按下 ESC 键退出循环
    if cv2.waitKey(1) & 0xFF == 27:
        break

# 释放摄像头
cap.release()

# 销毁所有窗口
cv2.destroyAllWindows()

这个眨眼检测器将帮助你检测和计算视频流或网络摄像头馈送中的眨眼次数。