OpenCV中的疲劳检测

一、介绍

这是一个基于 dlib 人脸 68 关键点 和 眼睛纵横比 EAR 的实时疲劳检测程序。整体思路是:用摄像头读取视频帧,检测人脸,定位眼睛关键点,计算眼睛睁开程度;如果连续多帧眼睛闭合,就认为可能疲劳并给出警告。

二、核心代码讲解

2.1导入库

numpy:数组运算,保存关键的坐标。

dlib:人脸检测和人脸68关键点预测。

cv2:OpenCV,读取摄像头、显示图像、画图。

eucliden_distances:计算两个点之间的欧式距离。

PIL:因为OpenCV的putText不支持中文,所以用PIL在图像上绘制中文。

2.2计算眼睛纵横比:eye_aspect_ratio

眼睛的6个关键点通常顺序为:

eye0:左眼角或外眼角;

eye1:上眼脸外侧

eye2:上眼脸内测

eye3:右眼角或内眼角

eye4:下眼脸内测

eye5:下眼脸外侧

计算逻辑:

A=distance(eye1,eye5):上眼脸外侧到下眼脸外侧的垂直距离。

B=distance(eye2,eye4):上眼脸内侧到下眼脸内侧的垂直距离。

C=distance(eye0,eye3):眼睛水平宽度。

EAR = ((A+B)/2)/C

当眼睛睁开时,垂直距离较大,EAR较大。

当眼睛闭合时,垂直距离变小,EAR变小。

因此EAR可以作为判断闭眼的指标。

euclidean_distances返回的是二维数组,所以最终ear不是普通浮点数,而是形如\[0.31的数组。后面代码用ear00取出数值。

2.3在OpenCV图像上绘制中文:cv2AddChineseText

OpenCV默认的cv2.putText不能直接显示中文,所以这里借助PIL:

1.如果传入的OpenCV的numpy.ndarray,先转成PIL图像。

OpenCV默认颜色顺序是BGR。

PIL默认颜色顺序是RGB。

所以用cv2.cvtColor(img, cv2.COLOR_BGR2RGB)转换。

2.创建ImageDraw.Draw对象,用于在图像上画文字。

3.加载中文字体simhei.ttf,字号由textSize指定。

4.使用draw.text在position位置绘制文字。

5.最后把PIL图像再转回OpenCV的BGR格式并返回。

2.4绘制眼睛凸包:drawEye

cv2.convexHull(eye):根据眼睛的6个点计算凸包,方便画出一个包围眼睛的轮廓。

cv2.drawContours:在frame上画出轮廓。

frame是全局变量,在后面在主循环中定义。

eyeHull:轮廓列表。

-1:画所有轮廓。

(0,255,0):绿色。

1:线宽

2.5初始化变量和模型

COUNTER = 0:记录连续闭眼的帧数。

detector = dlib.get_frontal_face_detector():构造dlib的正脸检测器。

predictor = dlib.shape_predictor:加载68点人脸关键点模型。

cap=cv2.VideoCaputer(0):打开默认摄像头,索引0通常表示第一个摄像头。

2.6主循环:读取摄像头并检测

ret,frame = cap.read():ret表示是否成功读取一帧。frame是当前视频帧。

faces = detector(frame,0):用dlib检测人脸。第二个参数0表示不进行上采样,速度较快,但小脸可能漏检。faces是检测到的人脸矩形列表。

2.7遍历每一张人脸

predictor(frame,face):根据人脸区域预测68个关键点。

shape.parts():返回68个关机点对象。

\[p.x,p.yfor p in shape.parts()]:把每个关键点转成x,y坐标。

np.array():转成NumPy数组,方便切片和计算。

2.8提取左右眼关键点

dlib的68点模型中:

索引36到41:右眼:共6个点。

索引42到47:左眼,共6个点。

2.9计算EAR

分别计算右眼和左眼的纵横比;

取平均值作为当前帧的眼睛睁开程度。

因为eye_aspect_ratio返回的是二维数组,所以ear也是数组。

2.10疲劳判断

逻辑:

如果ear<0.3,认为当前帧眼睛闭合或接近闭合。

COUNTER += 1:连续闭眼帧数加一。

如果连续闭眼达到50帧,就认为可能疲劳,在图像上显示"!!!!危险!!!!"。

如果ear>=0.3,说明眼睛睁开,COUNTER清零。

三、总结

整体流程为:

  1. 打开摄像头。

  2. 读取一帧图像。

  3. 用 dlib 检测人脸。

  4. 对每张人脸预测 68 个关键点。

  5. 提取左右眼各 6 个点。

  6. 计算眼睛纵横比 EAR。

  7. 如果 EAR 小于 0.3,连续闭眼计数加一。

  8. 连续闭眼超过 50 帧,显示"!!!!危险!!!!"。

  9. 绘制眼睛轮廓,显示 EAR 数值。

  10. 循环执行,直到按 ESC 退出。

  11. 释放摄像头和窗口。

相关推荐
小豆庄6 小时前
视频遮罩追踪退场后ID撞号的排查—多目标场景下的失效
opencv·算法·bug·视频·python3.11
zwc321043205513 小时前
Day 2:图像内存、数据类型与stride
c++·人工智能·opencv·算法·计算机视觉
誰能久伴不乏14 小时前
OpenCV 入门(二):像素访问、ROI 与深浅拷贝
人工智能·opencv·计算机视觉
zwc321043205515 小时前
第四周第五天——重构成类
c++·人工智能·opencv·算法·计算机视觉
zwc321043205517 小时前
Day 5:threshold与inRange阈值分割
c++·图像处理·人工智能·opencv·算法·计算机视觉
AI的探索之旅2 天前
97 个 OpenCV 实例(三十七):二维码识别,一张图四个码的陷阱
c++·opencv·计算机视觉
≮傷£≯√4 天前
OpenCV 边缘检测 Canny
人工智能·opencv·计算机视觉
≮傷£≯√5 天前
opencv 图像处理(一)
图像处理·人工智能·opencv
sali-tec5 天前
C# 基于OpenCv的视觉工作流-章114-视觉与http通讯
图像处理·人工智能·opencv·计算机视觉·c#
ahccqw5 天前
Opencv 基础常用API
人工智能·opencv·计算机视觉