当前位置: 首页 > article >正文

使用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()

http://www.kler.cn/news/358489.html

相关文章:

  • 1、HTML笔记
  • 使用 CDN 后 Apache 的日志记录客户真实 IP
  • 大模型效率优化的解决方案系统研究
  • 手动部署LNMP环境(Alibaba Cloud Linux 3/2、CentOS 7/8)
  • Matlab自学笔记三十九:日期时间型数据的算术运算:加减运算
  • 客户端与服务端通信的端口以及新增ARP缓存
  • 100. UE5 GAS RPG 显示范围魔法的攻击范围
  • Axure垂直菜单展开与折叠
  • upload-labs靶场Pass-03
  • Maven概述
  • 【电子通识】热敏打印头的结构类型和特点
  • 集创赛比赛细则了解
  • 一天认识一个硬件之路由器
  • 边界AIchat:智能办公与学习的全能助手
  • 【实战项目】——Boost搜索引擎(五万字)
  • 三菱PLC如何实现数据排序的分析?
  • Linux 累加计算递归算法汇编实现
  • js简单基础笔记
  • Pytorch Note
  • Java 多线程(四)—— 线程安全 与 volatile 与 单例模式