首页 > 其他分享 >使用Dlib库实现疲劳检测

使用Dlib库实现疲劳检测

时间:2024-10-20 20:46:16浏览次数:9  
标签:eye img 疲劳 检测 frame cv2 shape reshape Dlib

目录

前言

一、完整代码

二、代码步骤解析

1.计算眼睛纵横比

2.向图片中添加中文

3.绘制凸包 

4.打开摄像头读取每一帧画面进行处理


前言

        使用dlib库进行疲劳检测通常涉及人脸特征点检测和分析眼部特征(如眨眼率、眼睛开合程度等)。通过观察这些特征,可以推测一个人是否处于疲劳状态。

 

一、完整代码

import numpy as np
import dlib
import cv2
from sklearn.metrics.pairwise import euclidean_distances
from PIL import Image, ImageDraw, ImageFont


def eye_aspect_ration(eye):  # 计算眼睛纵横比
    x = eye[1]
    y = eye[1].reshape(1, 2)

    A = euclidean_distances(eye[1].reshape(1, 2), eye[5].reshape(1, 2))
    # euclidean_distances 函数的输入要求是两个二维数组 计算两点之间的欧氏距离
    B = euclidean_distances(eye[2].reshape(1, 2), eye[4].reshape(1, 2))
    C = euclidean_distances(eye[0].reshape(1, 2), eye[3].reshape(1, 2))
    return ((A + B) / 2.0) / C


def drawEye(eye):
    eyeHull = cv2.convexHull(eye)
    cv2.drawContours(frame, [eyeHull], -1, (0, 0, 255), -1)


def cv2AddChineseText(img, text, position, textColor=(255, 0, 0), textSize=30):
    # 向图片中添加中文
    if (isinstance(img, np.ndarray)):  # 判断图片是否是opencv的图片类型
        img = Image.fromarray(cv2.cvtColor(img, cv2.COLOR_BGR2RGB))  # 实现array到image的转换
    draw = ImageDraw.Draw(img)  # 在img图片上创建一个绘图的对象
    # 字体的格式
    fontStyle = ImageFont.truetype('simsun.ttc', textSize, encoding='utf-8')
    draw.text(position, text, textColor, font=fontStyle)  # 绘制文本
    return cv2.cvtColor(np.asarray(img), cv2.COLOR_RGB2BGR)  # 转换回opencv格式


detector = dlib.get_frontal_face_detector()  # 人脸检测器
predictor = dlib.shape_predictor('shape_predictor_68_face_landmarks.dat')  # 关键点检测器
counter = 0  # 记录闭眼帧数

cap = cv2.VideoCapture(0)
while True:
    ret, frame = cap.read()
    if not ret:
        break
    faces = detector(frame, 0)
    for face in faces:
        shape = predictor(frame, face)  # 检测关键点
        shape = np.array([[p.x, p.y] for p in shape.parts()])  # 获取关键点坐标
        rightEye = shape[36:42]
        leftEye = shape[42:48]
        rightEAR = eye_aspect_ration(rightEye)
        leftEAR = eye_aspect_ration(leftEye)
        ear = (leftEAR + rightEAR) / 2.0  # 平均值
        if ear < 0.3:
            counter += 1
            if counter >= 50:  # 闭眼时长大于50帧判断为疲劳
                frame = cv2AddChineseText(frame, "!!!疲劳危险!!!", (250, 250))
        else:
            counter = 0
        drawEye(leftEye)
        drawEye(rightEye)
        info = f"EAR:{ear[0][0]:.2f}"   # 二维数组访问元素  ear[0,0]
        frame = cv2AddChineseText(frame, info, (0, 30))
    cv2.imshow('Frame', frame)
    if cv2.waitKey(1) == 27:
        break
cv2.destroyAllWindows()
cap.release()

 

二、代码步骤解析

1.计算眼睛纵横比

获取眼睛关键点的坐标,计算眼睛的纵横比

def eye_aspect_ration(eye):  # 计算眼睛纵横比
    x = eye[1]
    y = eye[1].reshape(1, 2)

    A = euclidean_distances(eye[1].reshape(1, 2), eye[5].reshape(1, 2))
    # euclidean_distances 函数的输入要求是两个二维数组 计算两点之间的欧氏距离
    B = euclidean_distances(eye[2].reshape(1, 2), eye[4].reshape(1, 2))
    C = euclidean_distances(eye[0].reshape(1, 2), eye[3].reshape(1, 2))
    return ((A + B) / 2.0) / C

 

2.向图片中添加中文

开源代码,网上搜索即可

def cv2AddChineseText(img, text, position, textColor=(255, 0, 0), textSize=30):
    # 向图片中添加中文
    if (isinstance(img, np.ndarray)):  # 判断图片是否是opencv的图片类型
        img = Image.fromarray(cv2.cvtColor(img, cv2.COLOR_BGR2RGB))  # 实现array到image的转换
    draw = ImageDraw.Draw(img)  # 在img图片上创建一个绘图的对象
    # 字体的格式
    fontStyle = ImageFont.truetype('simsun.ttc', textSize, encoding='utf-8')
    draw.text(position, text, textColor, font=fontStyle)  # 绘制文本
    return cv2.cvtColor(np.asarray(img), cv2.COLOR_RGB2BGR)  # 转换回opencv格式

 

3.绘制凸包 

def drawEye(eye):
    eyeHull = cv2.convexHull(eye)
    cv2.drawContours(frame, [eyeHull], -1, (0, 0, 255), -1)

 

4.打开摄像头读取每一帧画面进行处理

  1. 创建人脸检测器和关键点检测器
  2. 获取每一帧的左右眼纵横比的平均值
  3. 若小于0.3就判断为闭眼
  4. 闭眼帧数大于50帧时判断为疲劳
  5. 在屏幕中央显示疲劳危险
detector = dlib.get_frontal_face_detector()  # 人脸检测器
predictor = dlib.shape_predictor('shape_predictor_68_face_landmarks.dat')  # 关键点检测器
counter = 0  # 记录闭眼帧数

cap = cv2.VideoCapture(0)
while True:
    ret, frame = cap.read()
    if not ret:
        break
    faces = detector(frame, 0)
    for face in faces:
        shape = predictor(frame, face)  # 检测关键点
        shape = np.array([[p.x, p.y] for p in shape.parts()])  # 获取关键点坐标
        rightEye = shape[36:42]
        leftEye = shape[42:48]
        rightEAR = eye_aspect_ration(rightEye)
        leftEAR = eye_aspect_ration(leftEye)
        ear = (leftEAR + rightEAR) / 2.0  # 平均值
        if ear < 0.3:
            counter += 1
            if counter >= 50:  # 闭眼时长大于50帧判断为疲劳
                frame = cv2AddChineseText(frame, "!!!疲劳危险!!!", (250, 250))
        else:
            counter = 0
        drawEye(leftEye)
        drawEye(rightEye)
        info = f"EAR:{ear[0][0]:.2f}"   # 二维数组访问元素  ear[0,0]
        frame = cv2AddChineseText(frame, info, (0, 30))
    cv2.imshow('Frame', frame)
    if cv2.waitKey(1) == 27:
        break
cv2.destroyAllWindows()
cap.release()

标签:eye,img,疲劳,检测,frame,cv2,shape,reshape,Dlib
From: https://blog.csdn.net/weixin_65047977/article/details/143098370

相关文章