Dlib库 人脸应用实例 疲劳监测
目录
一、项目原理与流程
1. 核心原理:眼睛纵横比(EAR)
2. 实现流程
二、完整代码实现
三、代码解析与优化说明
1. 核心函数解析
2. 关键优化点
3. 使用说明
四、运行效果与扩展方向
扩展方向:
一、项目原理与流程
1. 核心原理:眼睛纵横比(EAR)
眼睛纵横比(Eye Aspect Ratio)是判断眼睛开合状态的关键指标,其计算基于眼睛的 6 个特征点(每只眼睛有 6 个关键点):
- 上下眼睑之间的垂直距离(A 和 B)
- 内外眼角之间的水平距离(C)
计算公式:EAR = (A + B) / (2 * C)
- 当眼睛睁开时,EAR 值通常大于 0.3
- 当眼睛闭合时,EAR 值会显著下降(通常小于 0.3)
- 通过连续监测 EAR 值的变化,可判断眼睛闭合的持续时间
2. 实现流程
整个疲劳检测系统的工作流程分为初始化和视频处理两个阶段:
初始化阶段:
- 导入必要的库(numpy、dlib、cv2 等)
- 定义核心功能函数:
eye_aspect_ratio
:计算眼睛纵横比cv2AddChineseText
:在图像上添加中文文本drawEye
:绘制眼睛轮廓
- 初始化变量和模型:
- 计数器
COUNTER
:统计闭眼持续帧数 - 人脸检测器和关键点定位器
- 视频捕获设备
- 计数器
视频处理阶段:
- 逐帧读取视频画面
- 检测人脸并定位 68 个面部关键点
- 提取左右眼的关键点坐标
- 计算眼睛纵横比(EAR)
- 根据 EAR 值判断眼睛状态:
- EAR < 0.3:判定为闭眼,计数器累加
- 连续闭眼超过 50 帧:判定为疲劳状态,显示警示信息
- 眼睛睁开时:重置计数器
- 绘制眼睛轮廓和相关信息
- 实时显示处理结果并响应退出指令
二、完整代码实现
以下是可直接运行的疲劳检测系统代码,包含详细注释:
import numpy as np
import dlib
import cv2
from sklearn.metrics.pairwise import euclidean_distances
from PIL import Image, ImageDraw, ImageFontdef eye_aspect_ratio(eye):"""计算眼睛纵横比(EAR)"""# 计算垂直方向关键点的距离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值ear = ((A + B) / 2.0) / Creturn eardef cv2AddChineseText(img, text, position, textColor=(0, 255, 0), textSize=30):"""在OpenCV图像上添加中文文本"""if isinstance(img, np.ndarray):# 转换OpenCV的BGR格式为PIL的RGB格式img = Image.fromarray(cv2.cvtColor(img, cv2.COLOR_BGR2RGB))# 创建绘图对象draw = ImageDraw.Draw(img)# 加载中文字体try:# 尝试加载宋体字体,可替换为系统中存在的其他中文字体fontStyle = ImageFont.truetype("simsun.ttc", textSize, encoding="utf-8")except IOError:# 加载失败时使用默认字体fontStyle = ImageFont.load_default()print("警告:未找到中文字体,可能导致显示异常")# 绘制文本draw.text(position, text, textColor, font=fontStyle)# 转换回OpenCV格式return cv2.cvtColor(np.asarray(img), cv2.COLOR_RGB2BGR)def drawEye(frame, eye):"""绘制眼睛的凸包轮廓"""# 计算眼睛关键点的凸包eyeHull = cv2.convexHull(eye)# 绘制凸包轮廓cv2.drawContours(frame, [eyeHull], -1, (0, 255, 0), 2)# 初始化计数器
COUNTER = 0 # 用于统计连续闭眼的帧数# 初始化人脸检测器和关键点预测器
detector = dlib.get_frontal_face_detector()
# 加载68个关键点模型(确保模型文件在当前目录)
try:predictor = dlib.shape_predictor("shape_predictor_68_face_landmarks.dat")
except Exception as e:print(f"模型加载失败: {e}")print("请从https://github.com/davisking/dlib-models下载模型文件")exit()# 初始化视频捕获(可以是摄像头或视频文件)
# cap = cv2.VideoCapture(0) # 使用摄像头
cap = cv2.VideoCapture('test_video.mp4') # 使用视频文件# 检查视频是否成功打开
if not cap.isOpened():print("无法打开视频源,请检查路径或设备")exit()# 视频处理主循环
while True:# 读取一帧视频ret, frame = cap.read()# 检查是否成功读取帧if not ret:print("视频已结束或无法读取帧")break# 检测人脸faces = detector(frame, 0)# 处理每个检测到的人脸for face in faces:# 获取面部关键点shape = predictor(frame, face)# 将关键点转换为numpy数组shape = np.array([[p.x, p.y] for p in shape.parts()])# 提取左右眼的关键点(右眼36-41,左眼42-47)rightEye = shape[36:42]leftEye = shape[42:48]# 计算左右眼的EAR值rightEAR = eye_aspect_ratio(rightEye)leftEAR = eye_aspect_ratio(leftEye)# 计算平均EAR值ear = (leftEAR + rightEAR) / 2.0# 判断眼睛状态if ear < 0.3:COUNTER += 1# 如果连续闭眼超过50帧,判定为疲劳if COUNTER >= 50:frame = cv2AddChineseText(frame, "警告:疲劳状态!", (50, 50), (0, 0, 255), 40)else:# 眼睛睁开,重置计数器COUNTER = 0# 绘制眼睛轮廓drawEye(frame, leftEye)drawEye(frame, rightEye)# 显示当前EAR值info = f"EAR: {ear[0][0]:.2f}"frame = cv2AddChineseText(frame, info, (10, 30), (255, 0, 0), 20)# 显示处理后的帧cv2.imshow("疲劳检测系统", frame)# 按ESC键退出if cv2.waitKey(1) == 27:break# 释放资源
cap.release()
cv2.destroyAllWindows()
三、代码解析与优化说明
1. 核心函数解析
eye_aspect_ratio
:通过计算眼睛关键点的欧氏距离来确定 EAR 值,是疲劳判断的核心算法cv2AddChineseText
:解决 OpenCV 不支持中文显示的问题,通过 PIL 库实现中文绘制drawEye
:使用凸包算法绘制眼睛轮廓,使眼睛区域更直观地显示
2. 关键优化点
- 添加了模型加载错误处理,避免因模型文件缺失导致程序崩溃
- 优化了中文字体加载逻辑,增加了字体加载失败的容错处理
- 添加了视频源打开状态检查,提高程序健壮性
- 调整了绘制参数,使眼睛轮廓和文字信息显示更清晰
- 优化了疲劳判断阈值,使检测更准确
3. 使用说明
- 确保已安装所需库:
pip install dlib opencv-python numpy scikit-learn pillow
- 下载
shape_predictor_68_face_landmarks.dat
模型文件并放在代码同一目录 - 如需使用摄像头,将视频捕获部分改为
cap = cv2.VideoCapture(0)
- 运行程序,按 ESC 键退出
四、运行效果与扩展方向
程序运行时,会实时显示视频画面,并在画面中:
- 用绿色线条绘制眼睛轮廓
- 显示当前的 EAR 值(越小表示眼睛越接近闭合状态)
- 当检测到连续闭眼超过 50 帧时,显示红色 "警告:疲劳状态!" 提示
扩展方向:
- 增加声音报警功能,在检测到疲劳时发出提示音
- 记录疲劳发生的时间和频率,生成统计报告
- 结合嘴巴状态(如打哈欠检测)提高疲劳判断的准确性
- 优化算法,提高在不同光照条件下的检测稳定性
通过这个系统,可以实现基本的疲劳检测功能,适用于驾驶安全监控、课堂注意力监测等场景。