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. 释放摄像头和窗口。

相关推荐
宿州派大星1 小时前
【Python实战】:基于 OpenCV + dlib 的传统换脸术原理与实战
opencv·python3.11·dlib
陈年老古董1 小时前
MediaPipe 姿态检测与脸部关键点检测
笔记·python·opencv·学习·dlib
a3535413823 小时前
DFT到FFT的推导
opencv
别动我齐刘海3 小时前
ROS2 Jazzy + C++ 实战路线——ros2_control
c++·人工智能·python·opencv·机器学习·机器人·github
浔溺4 小时前
al+大数据每日学习笔记41
opencv·计算机视觉
江畔柳前堤20 小时前
字节跳动·大模型应用知识手册
前端·人工智能·深度学习·opencv·目标检测·重构·transformer
棣廷1 天前
初识OpenCV——Dlib CNN人脸检测
人工智能·深度学习·opencv
zx_741484811 天前
【计算机视觉入门】基于 dlib 与 OpenCV 的三大案例:人脸检测、年龄性别预测与疲劳检测
opencv·计算机视觉·dnn
yyk333241 天前
OpenCV中的表情识别
opencv