可解释面部关键点驾驶员状态监测:面向人机协作的透明DMS

论文信息

项目 内容
标题 Interpretable Driver Behavioral State Monitoring using Facial Landmarks for Human-Autonomous Vehicle Interaction
期刊 Frontiers in Robotics and AI, 13, 1896859
发表 2026年9月
DOI 10.3389/frobt.2026.1896859
关键词 interpretable, facial landmarks, driver state, human-vehicle interaction, autonomous

核心创新

提出基于面部关键点(而非原始图像/深度学习黑盒)的可解释驾驶员状态监测框架。通过几何特征+轻量级分类器实现透明、可解释、可审计的DMS,同时支持人机协作交互。


方法

1. 面部关键点提取

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
import numpy as np

class FacialLandmarkDMS:
"""
基于面部关键点的可解释DMS

不使用原始图像→CNN黑盒
而是提取68/468关键点→几何特征→轻量分类器

优势:
- 可解释(每个判断可追溯到具体几何特征)
- 轻量(关键点<1KB,图像>100KB)
- 隐私友好(不存储图像)
- 跨平台(关键点是通用表示)
"""

LANDMARK_INDICES = {
"left_eye": [36, 37, 38, 39, 40, 41],
"right_eye": [42, 43, 44, 45, 46, 47],
"mouth": [48, 49, 50, 51, 52, 53, 54, 55, 56, 57],
"left_eyebrow": [17, 18, 19, 20, 21],
"right_eyebrow": [22, 23, 24, 25, 26],
"nose_tip": [30],
"chin": [8],
"face_left": [1, 2, 3],
"face_right": [13, 14, 15]
}

def extract_geometric_features(self, landmarks):
"""
从关键点提取几何特征

Args:
landmarks: (68, 2) 面部关键点坐标

Returns:
features: 几何特征向量
"""
features = {}

# 1. 眼睛开度(EAR - Eye Aspect Ratio)
features['left_ear'] = self._ear(landmarks[36:42])
features['right_ear'] = self._ear(landmarks[42:48])
features['avg_ear'] = (features['left_ear'] + features['right_ear']) / 2

# 2. 嘴部开度(MAR - Mouth Aspect Ratio)
features['mar'] = self._mar(landmarks[48:68])

# 3. 头部姿态估计
features['pitch'], features['yaw'], features['roll'] = \
self._estimate_head_pose(landmarks)

# 4. 眉毛高度
features['left_brow_height'] = \
landmarks[21, 1] - landmarks[36, 1] # y坐标差
features['right_brow_height'] = \
landmarks[26, 1] - landmarks[45, 1]

# 5. 鼻尖偏离
features['nose_deviation_x'] = \
landmarks[30, 0] - np.mean([landmarks[1, 0], landmarks[15, 0]])

# 6. 面部对称性
features['symmetry'] = self._symmetry_score(landmarks)

return features

def _ear(self, eye_points):
"""眼睛纵横比(EAR)"""
# EAR = (|p2-p6| + |p3-p5|) / (2 * |p1-p4|)
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 * C + 1e-8)

def _mar(self, mouth_points):
"""嘴部纵横比(MAR)"""
A = np.linalg.norm(mouth_points[2] - mouth_points[8]) # 垂直
B = np.linalg.norm(mouth_points[0] - mouth_points[6]) # 水平
return A / (B + 1e-8)

def _estimate_head_pose(self, landmarks):
"""从关键点估计头部姿态"""
# 简化的姿态估计
# 使用鼻尖、下巴、面部轮廓估算
nose = landmarks[30]
chin = landmarks[8]
left_face = landmarks[1]
right_face = landmarks[15]

# Yaw: 左右面部宽度比
left_width = abs(nose[0] - left_face[0])
right_width = abs(right_face[0] - nose[0])
yaw = np.arctan2(right_width - left_width,
right_width + left_width + 1e-8)

# Pitch: 鼻尖到下巴距离 vs 额头距离
pitch = np.arctan2(chin[1] - nose[1],
np.linalg.norm(chin - nose) + 1e-8)

# Roll: 两眼连线角度
roll = np.arctan2(
landmarks[45, 1] - landmarks[36, 1],
landmarks[45, 0] - landmarks[36, 0]
)

return np.degrees(pitch), np.degrees(yaw), np.degrees(roll)

def _symmetry_score(self, landmarks):
"""面部对称性评分"""
# 以鼻尖为中心计算左右对称性
nose_x = landmarks[30, 0]
left_mirror = np.flip(landmarks[:30], axis=0)
right = landmarks[30:]

# 简化:计算左右对应点距离差异
return 1.0 - np.mean(np.abs(left_mirror[:, 0] - (2*nose_x - right[:, 0])))


# 测试
if __name__ == "__main__":
dms = FacialLandmarkDMS()

# 模拟68个关键点
np.random.seed(42)
landmarks = np.random.randint(100, 200, (68, 2))

features = dms.extract_geometric_features(landmarks)
print("提取的几何特征:")
for k, v in features.items():
print(f" {k}: {v:.3f}")

2. 可解释分类器

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
from sklearn.tree import DecisionTreeClassifier, export_text

class InterpretableClassifier:
"""
可解释决策树分类器

每个判断可追溯为规则链:
IF avg_ear < 0.2 AND mar > 0.5 THEN "疲劳+打哈欠"
"""

def __init__(self):
self.clf = DecisionTreeClassifier(
max_depth=5,
min_samples_leaf=50,
class_names=["alert", "drowsy", "distracted", "yawning"]
)

def train(self, features, labels):
self.clf.fit(features, labels)

def explain_prediction(self, sample):
"""解释单个预测的决策路径"""
decision_path = self.clf.decision_path([sample])

# 提取规则链
rules = []
node = 0
for feature_idx, threshold in zip(
self.clf.tree_.feature,
self.clf.tree_.threshold
):
if self.clf.tree_.children_left[node] == -1:
break
if sample[feature_idx] <= threshold:
rules.append(f"{feature_name[feature_idx]} ≤ {threshold:.3f}")
node = self.clf.tree_.children_left[node]
else:
rules.append(f"{feature_name[feature_idx]} > {threshold:.3f}")
node = self.clf.tree_.children_right[node]

return " AND ".join(rules)


# 示例规则
interpretation_examples = {
"疲劳检测": "avg_ear ≤ 0.180 AND yaw > 15.0° → 疲劳",
"打哈欠": "mar > 0.450 AND avg_ear < 0.200 → 疲劳+打哈欠",
"分心-左看": "yaw > 25.0° AND nose_deviation_x > 8.0 → 分心(左看)",
"分心-右看": "yaw < -25.0° AND nose_deviation_x < -8.0 → 分心(右看)",
"低头": "pitch > 20.0° → 低头(可能看手机)"
}

实验结果

与黑盒CNN对比

维度 面部关键点+决策树 CNN黑盒 (ResNet)
准确率 87.3% 92.1%
可解释性 ✅ 完全可解释 ❌ 黑盒
模型大小 5KB 45MB
推理速度 <1ms 15ms
隐私 ✅ 不存储图像 ⚠️ 需图像
审计性 ✅ 规则可审计 ❌ 无法审计
对抗鲁棒性 ✅ 几何特征难伪造 ⚠️ 对抗样本

不同状态检测性能

状态 准确率 关键特征 规则示例
清醒 94% EAR>0.25, yaw<15° EAR正常+头部正
疲劳(闭眼) 91% EAR<0.18 闭眼超过2秒
打哈欠 88% MAR>0.45 嘴部张开大
左分心 85% yaw>25° 头部左偏
右分心 84% yaw<-25° 头部右偏
低头 89% pitch>20° 头部下垂
眨眼频率 82% EAR方差 眨眼频率异常

IMS开发启示

1. 可解释DMS的合规价值

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
compliance_value = {
"法规要求": {
"Euro NCAP": "要求DMS可审计",
"GDPR": "要求算法可解释",
"EU AI Act": "高风险AI需可解释"
},
"黑盒CNN风险": [
"无法解释为什么判定疲劳",
"无法应对法规审计",
"对抗样本攻击风险",
"偏见和公平性问题"
],
"可解释DMS优势": [
"每个判断有明确规则链",
"可审计、可申诉",
"几何特征难伪造",
"跨平台一致性"
]
}

2. 分层架构(可解释+深度学习)

3. 隐私优势

方案 存储内容 隐私等级 GDPR合规
原始图像CNN 驾驶员面部图像 低 需同意
关键点CNN 68/468个坐标点 中 基本合规
几何特征+决策树 10个数值特征 高 完全合规

4. 部署方案

平台 关键点提取 分类器 总延迟 总大小
QCS8295 (SoC) MediaPipe 5ms 决策树 0.1ms 5.1ms 6KB
STM32H7 (MCU) dlib 15ms 决策树 0.1ms 15.1ms 6KB
ESP32 (低端) 轻量关键点 50ms 决策树 0.1ms 50.1ms 6KB

总结

可解释面部关键点DMS在准确率上略低于黑盒CNN(87.3% vs 92.1%),但在可解释性、隐私、审计、对抗鲁棒性方面具有显著优势。

对IMS的建议:采用分层架构——几何特征+决策树作为可解释基线(满足合规和审计),CNN深度学习作为精度增强层(处理复杂场景)。两层输出融合后既保持可解释性又保证准确率。特别是在GDPR和EU AI Act日益严格的背景下,可解释DMS是合规的必然要求。