📜  使用 OpenCV、 Python和 dlib 进行眨眼检测(1)

📅  最后修改于: 2023-12-03 15:22:15.289000             🧑  作者: Mango

使用 OpenCV、 Python 和 dlib 进行眨眼检测

眨眼检测是计算机视觉领域中的一个应用场景,通过对眨眼进行检测,可以实现许多应用,例如疲劳驾驶检测、情绪识别等。本文将介绍如何使用 OpenCV、 Python 和 dlib 进行眨眼检测。

安装依赖库

在开始之前,我们需要安装以下依赖库:

  • OpenCV:用于图像处理;
  • dlib:用于人脸检测和特征提取。

可以通过 pip 进行安装,命令如下:

pip install opencv-python dlib
运行程序

以下是完整的 Python 代码,用于检测摄像头捕捉到的视频中是否有眨眼现象:

import cv2
import dlib

# 初始化视频捕捉
cap = cv2.VideoCapture(0)

# 初始化人脸检测器和眼睛检测器
detector = dlib.get_frontal_face_detector()
predictor = dlib.shape_predictor('shape_predictor_68_face_landmarks.dat')

# 初始化计数器和阈值
blink_counter = 0
blink_threshold = 5

# 读取视频流
while True:
    ret, frame = cap.read()

    # 灰度化
    gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)

    # 人脸检测
    faces = detector(gray)

    # 遍历每张人脸
    for face in faces:
        # 特征提取
        landmarks = predictor(gray, face)

        # 左眼特征点序号
        left_eye_points = [36, 37, 38, 39, 40, 41]

        # 右眼特征点序号
        right_eye_points = [42, 43, 44, 45, 46, 47]

        # 左眼和右眼的特征点坐标
        left_eye = []
        right_eye = []

        # 将左眼和右眼的特征点坐标添加到对应的数组中
        for n in left_eye_points:
            x = landmarks.part(n).x
            y = landmarks.part(n).y
            left_eye.append((x, y))

        for n in right_eye_points:
            x = landmarks.part(n).x
            y = landmarks.part(n).y
            right_eye.append((x, y))

        # 计算左眼和右眼的长宽比
        left_eye_aspect_ratio = (left_eye[4][0] - left_eye[0][0]) / (left_eye[4][1] - left_eye[0][1])
        right_eye_aspect_ratio = (right_eye[4][0] - right_eye[0][0]) / (right_eye[4][1] - right_eye[0][1])

        # 计算左眼和右眼长宽比的平均值
        eye_aspect_ratio = (left_eye_aspect_ratio + right_eye_aspect_ratio) / 2

        # 眨眼检测
        if eye_aspect_ratio < 0.2:
            blink_counter += 1
        else:
            if blink_counter >= blink_threshold:
                print('Blink detected.')
            blink_counter = 0

        # 绘制眼睛边界框和特征点
        cv2.rectangle(frame, (face.left(), face.top()), (face.right(), face.bottom()), (0, 255, 0), 2)

        for n in range(0, 6):
            cv2.line(frame, left_eye[n], left_eye[(n + 1) % 6], (0, 0, 255), 1)
            cv2.line(frame, right_eye[n], right_eye[(n + 1) % 6], (0, 0, 255), 1)

    # 显示视频流
    cv2.imshow('frame', frame)

    # 退出程序
    if cv2.waitKey(1) & 0xFF == ord('q'):
        break

# 释放资源和关闭窗口
cap.release()
cv2.destroyAllWindows()
代码说明

程序的主要流程如下:

  • 初始化视频捕捉对象;
  • 初始化人脸检测器和眼睛检测器;
  • 从视频流中读取每一帧图像,进行灰度化、人脸检测、特征提取和眨眼检测;
  • 如果检测到眨眼现象,输出日志信息;
  • 显示视频流,同时监听退出程序的事件。

下面我们对程序的几个重点部分进行解释:

人脸检测
detector = dlib.get_frontal_face_detector()
faces = detector(gray)

在进行眼睛检测之前,我们首先需要检测出人脸。这里使用 dlib 库提供的默认人脸检测器,调用 get_frontal_face_detector 函数获取到检测器对象,然后利用该对象进行人脸检测,返回所有检测到的人脸区域。

特征提取
predictor = dlib.shape_predictor('shape_predictor_68_face_landmarks.dat')
landmarks = predictor(gray, face)

在进行眼睛检测之前,我们还需要获取到人脸的特征点,用于确定眼睛的位置。这里同样使用 dlib 库提供的特征点提取器,需要提前下载和训练好人脸特征点提取模型。在这里,我们使用由 dlib 官方提供的 68 个特征点的模型。

眼睛检测
left_eye_aspect_ratio = (left_eye[4][0] - left_eye[0][0]) / (left_eye[4][1] - left_eye[0][1])
right_eye_aspect_ratio = (right_eye[4][0] - right_eye[0][0]) / (right_eye[4][1] - right_eye[0][1])
eye_aspect_ratio = (left_eye_aspect_ratio + right_eye_aspect_ratio) / 2

在获取到眼睛的特征点之后,我们需要根据这些点的位置计算出眼睛的长宽比,以确定眼睛的状态。眨眼的过程实际上是眼睛长宽比快速变化的过程。

眨眼检测
if eye_aspect_ratio < 0.2:
    blink_counter += 1
else:
    if blink_counter >= blink_threshold:
        print('Blink detected.')
    blink_counter = 0

我们通过阈值的设置来确定何时该认为眼睛已经眨眼了,同时也需要记录连续多少帧的眼睛状态发生了变化,以防止噪音引起的误报。在本例中,我们将阈值设置为 5,即当连续 5 帧中眼睛都处于闭合状态时,就认为眨眼事件发生了。

总结

本文介绍了如何使用 OpenCV、 Python 和 dlib 进行眨眼检测,主要涉及到人脸检测、特征提取以及眼睛长宽比的计算等方面。这个技术可以应用于许多实际场景中,例如疲劳驾驶检测、眼部疾病诊断等。