用Python的face_recognition库快速实现人脸关键点提取与疲劳检测
人脸识别技术正在从实验室走向日常生活,而face_recognition库让开发者能够轻松调用这项能力。今天我们就来探索如何用不到50行代码,构建一个实时疲劳检测系统。这个方案特别适合需要长时间盯着屏幕的程序员、司机等职业人群。
1. 环境准备与库安装
首先需要配置Python环境。推荐使用Python 3.7及以上版本,这个版本的兼容性最好。face_recognition库底层依赖dlib,而dlib的安装有时会遇到麻烦。以下是经过验证的安装方案:
pip install cmake # 必须先安装cmake pip install dlib==19.22.0 # 指定这个稳定版本 pip install face_recognition opencv-python注意:如果在Windows上安装dlib失败,可以尝试先安装Visual Studio Build Tools中的C++开发组件
验证安装是否成功:
import face_recognition print(face_recognition.__version__) # 应该输出类似1.3.0的版本号常见问题排查:
- 报错关于numpy版本:尝试
pip install numpy==1.21.0 - 报错关于CMake:确保安装了最新版CMake并添加到系统PATH
- Mac用户可能需要先运行
xcode-select --install
2. 人脸关键点提取实战
face_recognition库内置了68点人脸特征检测模型,我们先用静态图片演示:
import face_recognition import cv2 image = face_recognition.load_image_file("person.jpg") face_landmarks = face_recognition.face_landmarks(image) # 可视化关键点 image = cv2.cvtColor(image, cv2.COLOR_RGB2BGR) for landmark in face_landmarks: for feature, points in landmark.items(): for point in points: cv2.circle(image, point, 2, (0,255,0), -1) cv2.imshow("Landmarks", image) cv2.waitKey(0)关键点分布对应的人脸部位:
| 点范围 | 对应部位 | 应用场景 |
|---|---|---|
| 0-16 | 下巴轮廓 | 人脸对齐、姿态估计 |
| 17-21 | 右眉毛 | 表情识别 |
| 22-26 | 左眉毛 | 表情识别 |
| 27-35 | 鼻梁和鼻尖 | 3D建模、活体检测 |
| 36-41 | 右眼 | 疲劳检测、视线追踪 |
| 42-47 | 左眼 | 疲劳检测、视线追踪 |
| 48-67 | 嘴唇轮廓 | 唇语识别、表情分析 |
3. 疲劳检测算法实现
基于眼睛纵横比(Eye Aspect Ratio, EAR)的算法是疲劳检测的经典方法。原理很简单:当人疲劳时眨眼频率会变化,眼睛闭合时间变长。
计算EAR的公式:
def eye_aspect_ratio(eye_points): # 计算两组垂直距离 A = np.linalg.norm(eye_points[1] - eye_points[5]) B = np.linalg.norm(eye_points[2] - eye_points[4]) # 计算水平距离 C = np.linalg.norm(eye_points[0] - eye_points[3]) return (A + B) / (2.0 * C)完整疲劳检测流程:
- 获取视频流(摄像头或视频文件)
- 逐帧检测人脸和关键点
- 计算双眼EAR值
- 设定阈值判断眼睛闭合
- 统计连续闭合帧数判断疲劳
实现代码核心部分:
# 初始化参数 EAR_THRESHOLD = 0.25 # 需根据实际调整 CONSEC_FRAMES = 15 # 连续多少帧低于阈值算疲劳 frame_counter = 0 alarm_on = False while True: _, frame = video_capture.read() rgb_frame = frame[:, :, ::-1] # BGR转RGB face_landmarks = face_recognition.face_landmarks(rgb_frame) for landmarks in face_landmarks: left_eye = landmarks["left_eye"] right_eye = landmarks["right_eye"] left_ear = eye_aspect_ratio(left_eye) right_ear = eye_aspect_ratio(right_eye) ear = (left_ear + right_ear) / 2.0 if ear < EAR_THRESHOLD: frame_counter += 1 if frame_counter >= CONSEC_FRAMES: if not alarm_on: print("疲劳警告!") alarm_on = True else: frame_counter = 0 alarm_on = False4. 性能优化与实用技巧
在实际部署时,我们需要考虑性能和用户体验。以下是几个关键优化点:
多尺度检测优化
# 调整检测参数提高速度 face_locations = face_recognition.face_locations( rgb_frame, number_of_times_to_upsample=0, model="cnn")参数调优经验值
| 场景 | EAR阈值 | 连续帧数 | 检测间隔 |
|---|---|---|---|
| 驾驶员监测 | 0.22 | 20 | 每帧检测 |
| 电脑前疲劳提醒 | 0.25 | 15 | 隔帧检测 |
| 移动端应用 | 0.28 | 10 | 降分辨率 |
实用增强功能
- 添加声音报警:使用
winsound(Windows)或pygame.mixer - 保存疲劳片段:检测到疲劳时自动保存前后10秒视频
- 多线程处理:将视频采集和检测分离到不同线程
# 简单的多线程实现 import threading def detection_thread(): while True: # 检测逻辑 pass capture_thread = threading.Thread(target=detection_thread) capture_thread.daemon = True capture_thread.start()5. 扩展应用与进阶方向
这个基础框架可以扩展出许多实用功能:
眨眼计数实现
blink_counter = 0 eye_closed = False if ear < EAR_THRESHOLD and not eye_closed: blink_counter += 1 eye_closed = True elif ear >= EAR_THRESHOLD: eye_closed = False头部姿态估计
利用solvePnP算法和3D模型点,可以估计头部旋转角度:
# 3D模型参考点 model_points = np.array([ (0.0, 0.0, 0.0), # 鼻尖 (0.0, -330.0, -65.0), # 下巴 # 其他关键点... ], dtype=np.float64) # 2D图像点 image_points = np.array([ landmarks["nose_tip"][0], landmarks["chin"][8], # 其他对应点... ], dtype=np.float64) # 计算旋转向量和平移向量 _, rotation_vec, translation_vec = cv2.solvePnP( model_points, image_points, camera_matrix, dist_coeffs)结合其他生理指标
- 打哈欠检测:通过嘴巴纵横比(MAR)
- 头部倾斜检测:利用眉毛和下巴关键点
- 心率估计:通过面部微小颜色变化
在实际项目中,我发现将EAR值与头部姿态结合能显著提高检测准确率。当系统检测到头部持续前倾(可能是打瞌睡)同时伴随EAR值降低时,触发警报的可靠性更高。