4、人脸关键点定位:掌握68点/106点/468点关键点检测原理,以及如何用于头部姿态估计和眼部状态分析
人脸关键点定位是座舱DMS(Driver Monitoring System)感知链路中的核心环节。它解决的是“驾驶员面部各部件在哪里”的问题——不仅要找到眼睛、鼻子、嘴巴的粗略位置,还要精确到眼睑轮廓、瞳孔中心、眉脊线等亚像素级坐标。在DMS应用中,关键点定位的精度直接决定了疲劳检测(如PERCLOS)、分心检测(如视线方向)和头部姿态估计(Head Pose Estimation)的可靠性。本章将系统讲解68点、106点和468点三种主流关键点模型的原理差异、工程选型依据,以及如何基于关键点坐标计算头部姿态和眼部开合度。
上图展示了三种关键点模型到下游DMS任务的完整链路。在实际工程中,选择哪种模型并非越密越好,而是取决于芯片算力、摄像头安装位置、实时性要求以及算法鲁棒性。下面我们逐一深入剖析。
4.1 三种关键点模型的原理与工程选型
68点模型源自经典的dlib库和iBUG 300-W数据集,它将人脸划分为眉毛(5点×2)、眼睛(6点×2)、鼻子(9点)、嘴巴(20点)和脸部轮廓(17点)。其检测原理通常基于级联回归树(Ensemble of Regression Trees)或深度卷积网络(如Heatmap回归)。在DMS场景中,68点模型的优势在于计算量小,在ARM Cortex-A53级别的CPU上即可达到30fps以上。但其对眼部细节的刻画不足——每只眼睛只有6个点,当驾驶员佩戴墨镜或眼睛眯缝时,眼睑上下沿的拟合误差会显著增大。
106点模型是近年来国内车规级DMS方案(如地平线、芯驰、爱芯元智等平台)的主流选择。它在68点的基础上,将每只眼睛的点数增加到12个,额外补充了眉弓下沿和眼袋区域的采样点。106点模型通常采用轻量级HRNet或MobileFaceNet结构,通过Heatmap回归输出关键点坐标。相比68点,106点对眼部开合度的测量精度提升了约30%,且对侧脸姿态(Yaw角超过45°)的鲁棒性更好。其代价是模型参数量约为68点模型的1.8倍,但仍在车规级芯片的NPU算力范围内。
468点模型来自Google MediaPipe Face Mesh,它采用BlazeFace进行人脸检测,然后通过回归模型直接输出468个3D关键点(含深度信息)。该模型最大的特点是包含眼球轮廓(每只眼睛约16个点)和唇部内沿,能够精细刻画微表情。在DMS中,468点模型主要用于视线估计(Gaze Estimation)和微睡眠检测(Microsleep)。但需要注意,MediaPipe Face Mesh在PC和手机端表现优异,在车规级嵌入式平台上直接部署时,若没有GPU或NPU加速,很难达到实时性要求。此外,其3D关键点的深度信息在单目摄像头下存在尺度模糊问题,需要额外的标定补偿。
| 对比维度 | 68点模型 | 106点模型 | 468点模型 |
|---|---|---|---|
| 关键点数量 | 68 | 106 | 468(含3D深度) |
| 眼部点数 | 6点/眼 | 12点/眼 | 约16点/眼+眼球轮廓 |
| 典型算法 | 级联回归/浅层CNN | HRNet/轻量Transformer | MediaPipe回归模型 |
| 计算量(MACs) | 约0.5G | 约1.2G | 约4.5G |
| 车规级部署 | 低端MCU即可 | 需NPU或中端SoC | 需独立GPU/NPU |
| DMS适用性 | 基础疲劳检测 | 主流方案,精度/算力平衡 | 高精度视线估计 |
4.2 基于关键点的头部姿态估计:PnP求解与工程实现
头部姿态估计的目标是计算驾驶员头部在三维空间中的旋转角度(Yaw偏航角、Pitch俯仰角、Roll滚转角)。其核心原理是透视n点投影(Perspective-n-Point, PnP):已知人脸关键点在图像中的2D坐标,以及对应的人脸标准3D模型坐标,通过求解相机外参(旋转矩阵R和平移向量t)来获得头部姿态。
具体操作流程如下:
- 建立3D人脸基准模型:选取鼻尖、下巴、左眼左角、右眼右角、嘴角左端、嘴角右端等6-8个关键点,赋予其在标准坐标系下的3D坐标(单位:毫米)。例如,鼻尖为(0,0,0),左眼左角为(-30,-20,10)等。
- 获取2D关键点坐标:从关键点检测网络输出中提取对应索引的2D像素坐标。
- 相机内参标定:使用座舱内摄像头的焦距(fx, fy)和主点(cx, cy)构建内参矩阵K。若无法精确标定,可使用近似值(如fx=fy=图像宽度,cx=宽度/2, cy=高度/2),但会引入约2-3°的姿态误差。
- 调用PnP求解器:使用OpenCV的
cv2.solvePnP或cv2.solvePnPRansac函数,输入3D点、2D点、内参矩阵和畸变系数,输出旋转向量rvec和平移向量tvec。 - 转换旋转向量为欧拉角:通过Rodrigues变换将rvec转换为旋转矩阵R,再分解为Yaw、Pitch、Roll。
import cv2
import numpy as np
# 3D人脸基准点(单位:mm)
object_pts = np.float32([
[0.0, 0.0, 0.0], # 鼻尖
[0.0, -30.0, -10.0], # 下巴
[-30.0, -20.0, 10.0], # 左眼左角
[30.0, -20.0, 10.0], # 右眼右角
[-25.0, 10.0, 5.0], # 嘴角左端
[25.0, 10.0, 5.0] # 嘴角右端
])
# 2D关键点(从检测网络获取)
image_pts = np.float32([
[nose_x, nose_y],
[chin_x, chin_y],
[left_eye_x, left_eye_y],
[right_eye_x, right_eye_y],
[mouth_left_x, mouth_left_y],
[mouth_right_x, mouth_right_y]
])
# 相机内参(需标定)
K = np.float64([[fx, 0, cx], [0, fy, cy], [0, 0, 1]])
dist_coeffs = np.float64([0, 0, 0, 0, 0]) # 假设无畸变
# 求解PnP
success, rvec, tvec = cv2.solvePnP(object_pts, image_pts, K, dist_coeffs)
# 旋转向量转旋转矩阵
R, _ = cv2.Rodrigues(rvec)
# 计算欧拉角(注意旋转顺序)
yaw = np.degrees(np.arctan2(R[1,0], R[0,0]))
pitch = np.degrees(np.arctan2(-R[2,0], np.sqrt(R[2,1]**2 + R[2,2]**2)))
roll = np.degrees(np.arctan2(R[2,1], R[2,2]))
在DMS工程中,头部姿态估计需要做时间序列平滑,因为单帧的PnP结果存在抖动。常用的方法包括卡尔曼滤波或滑动窗口平均。此外,当Yaw角值大于60°时,人脸关键点自遮挡严重,PnP求解会退化,此时应结合肩部检测或车辆转向信号进行综合判断。
4.3 眼部状态分析:从EAR到PERCLOS的完整链路
眼部状态分析是疲劳驾驶告警的核心依据。最常用的指标是眼纵横比(Eye Aspect Ratio, EAR),它利用眼睛周围关键点的欧氏距离比值来量化眼睛的开合程度。对于106点模型,每只眼睛有12个关键点,我们选取其中6个关键点(眼睑上下沿各3个)来计算EAR。
EAR的计算公式如下:
EAR = (||P2 - P6|| + ||P3 - P5||) / (2 * ||P1 - P4||)
其中:
P1, P4 为眼睛左右眼角
P2, P3 为上眼睑关键点
P5, P6 为下眼睑关键点
当眼睛完全睁开时,EAR约为0.25-0.35;当眼睛闭合时,EAR趋近于0。通过设定阈值(通常为0.15-0.20),可以判断当前帧眼睛是否闭合。但单帧的EAR容易受光照和头部姿态影响,因此需要引入PERCLOS(Percentage of Eye Closure)指标——即单位时间内眼睛闭合帧数占总帧数的百分比。根据美国联邦公路管理局(FHWA)的研究,PERCLOS超过40%时,驾驶员处于严重疲劳状态。
工程实现中,还需要处理以下细节:
- 眨眼区分:正常眨眼持续约100-150ms,若闭合时间超过500ms,则判定为微睡眠事件。
- 姿态补偿:当驾驶员低头(Pitch角>20°)时,眼睛在图像中会变窄,EAR值会系统性偏低。此时需要根据头部姿态对EAR进行修正,或采用基于3D眼睑模型的方法。
- 光照鲁棒性:夜间行车时,红外摄像头下眼睛区域可能出现反光或暗瞳效应,建议在关键点检测前增加红外图像增强预处理。
| 指标 | 计算公式 | 阈值参考 | DMS告警等级 |
|---|---|---|---|
| EAR | 眼睑垂直距离/水平距离 | <0.18判定闭眼 | 单帧状态 |
| PERCLOS | 闭眼帧数/总帧数×100% | >40%判定疲劳 | 一级告警 |
| 闭眼时长 | 连续闭眼帧数×帧周期 | >500ms判定微睡眠 | 二级告警 |
| 眨眼频率 | 每分钟眨眼次数 | <5次/分钟判定疲劳 | 辅助指标 |
4.4 案例拆解:某量产车型DMS眼部疲劳告警误报优化
背景与约束:某主机厂在量产车型上部署了基于106点关键点的DMS系统,摄像头安装于仪表盘上方,俯仰角约15°,分辨率为1280×720@30fps。系统上线后,收到大量用户投诉:在正常驾驶过程中,系统频繁触发“疲劳驾驶”告警,尤其在驾驶员佩戴太阳镜或行驶在颠簸路面时。
初始现象与数据采集:通过车载日志分析发现,误报集中在两类场景:一是驾驶员佩戴偏光太阳镜时,关键点检测置信度从0.85骤降至0.4以下,导致EAR值异常偏低;二是车辆经过减速带时,摄像头振动导致关键点坐标在垂直方向产生±3像素的抖动,使得EAR值在0.15-0.25之间剧烈波动。
分析判断过程:团队首先排除了算法本身的问题——在实验室静态场景下,PERCLOS准确率达到95%。进一步分析发现,太阳镜场景下,红外摄像头无法穿透镜片获取眼睑轮廓,关键点检测器将镜框边缘误识别为眼睑,导致EAR计算失真。而振动场景下,单帧EAR的噪声方差增大,但PERCLOS的统计窗口(30秒)内,闭眼帧占比并未真正超过40%,问题出在告警逻辑中使用了过短的滑动窗口(5秒)。
实际操作步骤:
- 增加关键点置信度门控:当眼睛周围12个关键点的平均置信度低于0.6时,不计算EAR,而是将上一有效帧的EAR值保持,并标记为“低置信度状态”。
- 引入振动检测与补偿:利用IMU(惯性测量单元)数据检测车辆振动频率,当振动幅度超过阈值时,将PERCLOS的统计窗口从5秒延长至15秒,并采用中值滤波替代均值滤波。
- 优化告警逻辑:将“疲劳告警”触发条件从“单次PERCLOS>40%”改为“连续3个统计周期(每个周期30秒)PERCLOS均>40%”,同时增加眨眼频率作为辅助确认条件。
- 增加太阳镜检测分支:在关键点检测网络前增加一个轻量级分类器,判断驾驶员是否佩戴墨镜。若佩戴,则切换至基于头部姿态和方向盘握力的间接疲劳判断策略。
结果对比:优化后,误报率从每百公里2.3次降至0.4次,召回率(真实疲劳事件的检出率)保持在92%以上。太阳镜场景下的误报率降低了87%,振动场景下的误报率降低了76%。
风险与代价:置信度门控可能导致在极端光照下(如夜间无红外补光)出现“检测盲区”,此时系统无法判断驾驶员状态。为此,团队增加了“状态未知”的告警提示,并联动车内灯光提醒驾驶员注意安全。此外,IMU数据的接入增加了系统集成的复杂度,需要与整车CAN总线进行通信。
复盘经验:DMS关键点定位的工程化不仅仅是模型精度问题,更需要结合传感器特性、车辆动力学和用户使用习惯进行系统性调优。建议在项目初期就建立包含太阳镜、口罩、帽子、极端光照、振动路面等典型场景的测试矩阵,避免在量产后期被动修复。