【进阶OpenCV】 (20) --疲劳检测

文章目录

疲劳检测

使用OpenCV实现疲劳检测 通常依赖于面部特征分析,特别是眼睛的状态(如眼睛开合程度)以及闭眼的时间。

一、面部识别

通过Dlib库构造人脸检测器 ,用于检测人脸,然后通过shape_predictor()加载模型用于定位检测到的人脸的关键点:

python 复制代码
detector = dlib.get_frontal_face_detector() # 构造人脸检测器
predictor = dlib.shape_predictor("shape_predictor_68_face_landmarks.dat") # 定位关键点模型
cap = cv2.VideoCapture(0)

二、主循环

1. 计算眼睛纵横比

通过euclidean_distances()函数计算两点间的距离:

python 复制代码
def eye_aspect_ratio(eye):
    """-----计算眼睛纵横比-----"""
    A = euclidean_distances(eye[1].reshape(1,2),eye[5].reshape(1,2))
    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))
    ear = ((A+B)/2.0) / C # 纵横比
    return ear
python 复制代码
COUNTER = 0 # 闭眼持续帧数统计
while True:
    ret,frame = cap.read()
    faces = detector(frame,0)
    for face in faces:
        shape = predictor(frame,face)# 获取关键点
        # 将关键点转换为坐标(x,y)的形式
        shape = np.array([[p.x,p.y] for p in shape.parts()])
        rightEye = shape[36:42] # 右眼,关键点索引从36到41
        leftEye = shape[42:48] # 左眼,关键点索引从42到47
        rightEAR = eye_aspect_ratio(rightEye) # 计算右眼纵横比
        leftEAR = eye_aspect_ratio(leftEye) # 计算左眼纵横比
        ear = (leftEAR + rightEAR) / 2.0 # 均值处理

2. 判断疲劳状态

当宽高比小于0.3,且连续50帧保持这个状态,则认定他处于疲劳状态:

python 复制代码
def cv2ADDChineseText(img,text,position,textColor=(0,255,0),textSize=30):
    """像图片中添加中文"""
    if (isinstance(img,np.ndarray)):
        img = Image.fromarray(cv2.cvtColor(img,cv2.COLOR_BGR2RGB))
    draw = ImageDraw.Draw(img)

    fontStyle = ImageFont.truetype("simfang.ttf",textSize,encoding="Utf-8")
    draw.text(position,text,textColor,font=fontStyle)
    return cv2.cvtColor(np.asarray(img),cv2.COLOR_BGR2RGB)

if ear < 0.3: # 小于0.3认为闭眼,也可能是眨眼
    COUNTER += 1
    if COUNTER >= 50:
        frame = cv2ADDChineseText(frame,"!!!危险!!!",(250,250))
# 宽高比 > 0.3,则计数器清零,解除疲劳标志
else:
    COUNTER = 0 # 闭眼次数清零

3. 绘制双眼凸包

将双眼绘制出来:

python 复制代码
def drawEye(eye): # 绘制眼眶凸包
    eyeHull = cv2.convexHull(eye)
    cv2.drawContours(frame,[eyeHull],-1,(0,255,0),1)

drawEye(leftEye) # 绘制左眼凸包
drawEye(rightEye) # 绘制右眼凸包

4. 显示眼睛闭合程度值

python 复制代码
info = "EAR:{:.2f}".format(ear[0][0])
frame = cv2ADDChineseText(frame,info,(0,30)) # 显示眼睛闭合程度值

5. 显示图像

python 复制代码
    cv2.imshow("Frame",frame)
    if cv2.waitKey(1) == 27:
        break

三、释放资源

python 复制代码
cv2.destroyAllWindows()
cap.release()

四、完整代码展示

python 复制代码
import numpy as np
import dlib
import cv2
from sklearn.metrics.pairwise import euclidean_distances
from PIL import Image,ImageDraw,ImageFont

def eye_aspect_ratio(eye):
    """-----计算眼睛纵横比-----"""
    A = euclidean_distances(eye[1].reshape(1,2),eye[5].reshape(1,2))
    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))
    ear = ((A+B)/2.0) / C # 纵横比
    return ear

def cv2ADDChineseText(img,text,position,textColor=(0,255,0),textSize=30):
    """像图片中添加中文"""
    if (isinstance(img,np.ndarray)):
        img = Image.fromarray(cv2.cvtColor(img,cv2.COLOR_BGR2RGB))
    draw = ImageDraw.Draw(img)

    fontStyle = ImageFont.truetype("simfang.ttf",textSize,encoding="Utf-8")
    draw.text(position,text,textColor,font=fontStyle)
    return cv2.cvtColor(np.asarray(img),cv2.COLOR_BGR2RGB)

def drawEye(eye): # 绘制眼眶凸包
    eyeHull = cv2.convexHull(eye)
    cv2.drawContours(frame,[eyeHull],-1,(0,255,0),1)

COUNTER = 0 # 闭眼持续帧数统计
detector = dlib.get_frontal_face_detector() # 构造人脸检测器
predictor = dlib.shape_predictor("shape_predictor_68_face_landmarks.dat") # 定位关键点模型
cap = cv2.VideoCapture(0)

while True:
    ret,frame = cap.read()
    faces = detector(frame,0)
    for face in faces:
        shape = predictor(frame,face)# 获取关键点
        # 将关键点转换为坐标(x,y)的形式
        shape = np.array([[p.x,p.y] for p in shape.parts()])
        rightEye = shape[36:42] # 右眼,关键点索引从36到41
        leftEye = shape[42:48] # 左眼,关键点索引从42到47
        rightEAR = eye_aspect_ratio(rightEye) # 计算右眼纵横比
        leftEAR = eye_aspect_ratio(leftEye) # 计算左眼纵横比
        ear = (leftEAR + rightEAR) / 2.0 # 均值处理

        if ear < 0.3: # 小于0.3认为闭眼,也可能是眨眼
            COUNTER += 1
            if COUNTER >= 50:
                frame = cv2ADDChineseText(frame,"!!!危险!!!",(250,250))
        # 宽高比 > 0.3,则计数器清零,解除疲劳标志
        else:
            COUNTER = 0 # 闭眼次数清零
        drawEye(leftEye) # 绘制左眼凸包
        drawEye(rightEye) # 绘制右眼凸包
        info = "EAR:{:.2f}".format(ear[0][0])
        frame = cv2ADDChineseText(frame,info,(0,30)) # 显示眼睛闭合程度值
    cv2.imshow("Frame",frame)
    if cv2.waitKey(1) == 27:
        break
cv2.destroyAllWindows()
cap.release()

总结

本篇介绍了,如何通过人脸部眼睛的变化来简单的进行疲劳检测。

相关推荐
CoovallyAIHub几秒前
超越YOLOv8/v11!自研RKM-YOLO为输电线路巡检精度、速度双提升
深度学习·算法·计算机视觉
paperxie_xiexuo2 分钟前
面向多场景演示需求的AI辅助生成工具体系研究:十类平台的功能分型、技术实现与合规应用分析
大数据·人工智能·powerpoint·ppt
aneasystone本尊20 分钟前
学习 LiteLLM 的缓存系统
人工智能
CNRio40 分钟前
人工智能基础架构与算力之2 异构算力合池技术:打破资源壁垒的分布式 AI 部署方案
人工智能·分布式
Zlssszls42 分钟前
全运会展现科技魅力,数字孪生打造智慧场馆新标杆
人工智能·科技·数字孪生·智慧场馆·全运会
qinyia1 小时前
WisdomSSH如何高效检查服务器状态并生成运维报告
linux·运维·服务器·数据库·人工智能·后端·ssh
BagMM1 小时前
FC-CLIP 论文阅读 开放词汇的检测与分割的统一
人工智能·深度学习·计算机视觉
IT_陈寒1 小时前
Python开发者必知的5个高效技巧,让你的代码性能提升50%
前端·人工智能·后端
张较瘦_1 小时前
[论文阅读] AI + 软件工程 | LLM救场Serverless开发!SlsReuse框架让函数复用率飙升至91%,还快了44%
论文阅读·人工智能·软件工程
极限实验室1 小时前
INFINI Labs 产品更新 - Coco AI v0.9 与 Easysearch v2.0 全新功能上线,全面支持 GitLab 合并请求(MR)自动
数据库·人工智能·产品