利用OpenCV和Dlib实现疲劳检测:守护安全与专注
在当今快节奏的生活中,疲劳和注意力不集中是许多人面临的常见问题,尤其是在驾驶、学习等需要高度集中精力的场景中。疲劳不仅影响个人的健康和安全,还可能导致严重的事故。为了应对这一挑战,计算机视觉技术提供了一种有效的解决方案,通过实时监测人的生理状态,及时发现疲劳迹象并发出警报。本文将介绍如何利用OpenCV和Dlib库实现疲劳检测功能,尤其是通过监测眼睛的闭合程度来判断疲劳状态。
一、项目背景与目标
疲劳检测技术在多个领域具有重要的应用价值。例如,在驾驶场景中,通过实时监测驾驶员的眼睛状态,可以及时发现疲劳驾驶行为,提醒驾驶员休息,从而提高行车安全。在教育领域,通过监测学员上课时的状态,可以判断学员是否专注听讲或处于疲劳状态,为教学管理提供参考。
本文的目标是实现一个基于OpenCV和Dlib的疲劳检测系统,能够实时监测眼睛的闭合程度,并通过中文提示信息反馈检测结果。
二、技术栈
- OpenCV:用于图像处理和视频流操作。
- Dlib:用于人脸检测和关键点检测。
- Sklearn:用于计算欧几里得距离。
- PIL:用于在图像上绘制中文文本。
三、疲劳检测:眼睛状态监测
疲劳检测的核心是通过监测眼睛的闭合程度来判断一个人是否处于疲劳状态。眼睛的闭合程度可以通过计算眼睛的纵横比(Eye Aspect Ratio, EAR)来量化。
(一)眼睛纵横比的计算
眼睛的六个关键点分布如下:
1 2
0 3
5 4
通过计算这些关键点之间的欧几里得距离,可以得到眼睛的纵横比。具体公式如下:
[ \text{EAR} = \frac{A + B}{2C} ]
其中:
- (A) 是关键点1和5之间的距离
- (B) 是关键点2和4之间的距离
- (C) 是关键点0和3之间的距离
以下是计算EAR的代码实现:
from sklearn.metrics.pairwise import euclidean_distances
def eyes_aspect_ratio(eye):
A = euclidean_distances(eye[1].reshape(1, 2), eye[5].reshape(1, 2))[0][0]
B = euclidean_distances(eye[2].reshape(1, 2), eye[4].reshape(1, 2))[0][0]
C = euclidean_distances(eye[0].reshape(1, 2), eye[3].reshape(1, 2))[0][0]
ear = (A + B) / (2.0 * C)
return ear
(二)实时监测与警告
在实时视频流中,我们通过Dlib的人脸检测器和关键点检测器获取人脸和眼睛的关键点,然后计算EAR值。如果连续多帧(如50帧)检测到EAR值低于阈值(如0.6),则认为用户处于疲劳状态,并在屏幕上显示警告信息。
以下代码实现了一个疲劳驾驶检测系统,通过检测眼睛的闭合程度来判断驾驶员是否疲劳。代码主要分为以下几个部分:
1. 导入必要的库
import cv2 # OpenCV 库,用于图像处理和视频流操作
import dlib # Dlib 库,用于人脸检测和关键点检测
from sklearn.metrics.pairwise import euclidean_distances # 用于计算两点之间的欧几里得距离
from PIL import Image, ImageDraw, ImageFont # PIL 库,用于处理图像
import numpy as np # NumPy 库,用于数值计算
2. 定义眼睛纵横比计算函数
def eyes_aspect_ratio(eye):
# 计算眼睛的纵横比(EAR),用于判断眼睛是否闭合
A = euclidean_distances(eye[1].reshape(1, 2), eye[5].reshape(1, 2))[0][0] # 计算垂直距离 A
B = euclidean_distances(eye[2].reshape(1, 2), eye[4].reshape(1, 2))[0][0] # 计算垂直距离 B
C = euclidean_distances(eye[0].reshape(1, 2), eye[3].reshape(1, 2))[0][0] # 计算水平距离 C
ear = (A + B) / (2.0 * C) # 计算眼睛的纵横比
return ear
3. 定义添加中文文本的函数
def cv2AddChineseText(img, text, position, textColor=(0, 255, 0), textSize=50):
# 在 OpenCV 的图像上添加中文文本
if isinstance(img, np.ndarray): # 检查输入是否为 NumPy 数组
img = Image.fromarray(cv2.cvtColor(img, cv2.COLOR_BGR2RGB)) # 将 OpenCV 图像转换为 PIL 图像
draw = ImageDraw.Draw(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) # 将 PIL 图像转换回 OpenCV 图像
4. 定义绘制眼睛轮廓的函数
def drawEye(eye, frame):
# 绘制眼睛的轮廓
eyeHull = cv2.convexHull(eye) # 计算眼睛的凸包
cv2.drawContours(frame, [eyeHull], -1, (0, 255, 0), -1) # 绘制眼睛的轮廓
5. 初始化人脸检测器和关键点检测器
detector = dlib.get_frontal_face_detector() # 初始化人脸检测器
predictor = dlib.shape_predictor("shape_predictor_68_face_landmarks.dat") # 初始化关键点检测器
6. 初始化摄像头
cap = cv2.VideoCapture(0) # 打开默认摄像头
7. 初始化闭眼持续次数统计
COUNTER = 0 # 闭眼持续次数统计
8. 主循环
while True:
ret, frame = cap.read() # 从摄像头读取一帧
if not ret: # 如果读取失败
break # 退出循环
9. 检测人脸和关键点
faces = detector(frame, 0) # 检测图像中的人脸
for face in faces: # 遍历每个检测到的人脸
shape = predictor(frame, face) # 提取人脸的关键点
shape = np.array([[p.x, p.y] for p in shape.parts()]) # 将关键点转换为 NumPy 数组
10. 计算眼睛的纵横比
rightEye = shape[36:42] # 提取右眼的关键点
leftEye = shape[42:48] # 提取左眼的关键点
rightEAR = eyes_aspect_ratio(rightEye) # 计算右眼的纵横比
leftEAR = eyes_aspect_ratio(leftEye) # 计算左眼的纵横比
ear = (leftEAR + rightEAR) / 2.0 # 计算平均纵横比
11. 判断是否闭眼
if ear < 0.6: # 如果眼睛的纵横比小于 0.6,认为眼睛闭合
COUNTER += 1 # 增加闭眼持续次数统计
if COUNTER >= 50: # 如果闭眼持续次数达到 50 帧
frame = cv2AddChineseText(frame, "!!!!危险!!!!", (250, 250)) # 显示警告信息
else:
COUNTER = 0 # 如果眼睛睁开,重置闭眼持续次数统计
12. 绘制眼睛轮廓
drawEye(rightEye, frame) # 绘制右眼的轮廓
drawEye(leftEye, frame) # 绘制左眼的轮廓
info = "EAR: {:.2f}".format(ear) # 格式化眼睛的纵横比信息
frame = cv2AddChineseText(frame, info, (0, 30)) # 在图像上显示眼睛的纵横比信息
13. 显示结果
cv2.imshow("Frame", frame) # 显示处理后的图像
if cv2.waitKey(1) == 27: # 按下 ESC 键退出
break # 退出循环
14. 释放资源
cv2.destroyAllWindows() # 关闭所有 OpenCV 窗口
cap.release() # 释放摄像头资源
四、应用场景
(一)驾驶员疲劳检测
通过实时监测驾驶员的眼睛状态,可以及时发现疲劳驾驶行为,提醒驾驶员休息,从而提高行车安全。
(二)学员上课状态监测
通过监测学员上课时的状态,可以判断学员是否专注听讲或处于疲劳状态,为教学管理提供参考。
五、总结
本文详细介绍了如何利用OpenCV和Dlib实现疲劳检测。通过计算眼睛的纵横比,可以实时监测用户的疲劳状态。这一技术在驾驶安全和教学管理等领域具有广泛的应用前景。未来,我们还可以进一步优化算法,提高检测的准确性和实时性,为人们的生活和工作提供更多的便利和安全保障。