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

相关推荐
JMchen11 小时前
集成第三方 C/C++ 库到 Android NDK 项目:OpenCV 与 FFmpeg 实战指南
android·opencv·cmake
richard_yuu1 天前
OpenCV 实战第 9 篇:Template Matching vs 特征匹配,ROI 定位该选哪个
opencv
研來如此1 天前
OpenCV官方下载界面下载opencv库
人工智能·opencv·计算机视觉
程序人生8881 天前
PDF 转 Word 版式错乱、表格丢失?DocConverter Web 格式互转引擎的保真实践
前端·人工智能·opencv·机器学习·pdf·word
HUANGZHENXUAN1231 天前
代码解析(一):从 `opencv_basics/` 说起
opencv
词却2 天前
OpenCV学习:MediaPipe 人脸网格检测
opencv·学习
richard_yuu2 天前
OpenCV 实战第 8 篇:几何测量算子族,从 boundingRect 到亚像素定位
人工智能·opencv·计算机视觉
程序人生8883 天前
从“把隐私文件上传到别人云端“到本地可控:DocConverter Web 立项初心与架构选型
前端·图像处理·人工智能·opencv·架构·ocr·文心一言
ab1237683 天前
OpenCV 学习笔记
笔记·opencv·学习
咯哦哦哦哦3 天前
opencv复现 Halcon 双相机拼接
人工智能·数码相机·opencv