DMS 眼动追踪鲁棒性优化:墨镜/口罩/低光照场景解决方案

问题背景

实际驾驶场景中的挑战:

场景 影响 发生频率
墨镜 遮挡眼睛,瞳孔检测失败 高频(白天驾驶)
口罩 遮挡下半脸,面部识别困难 高频(后疫情时代)
低光照 信噪比下降,检测精度降低 中频(夜间/隧道)
逆光 面部阴影,特征提取困难 中频
帽子/头巾 部分遮挡面部 低频

Tesla 2026.14.6.7 更新: 改进了墨镜和低光照条件下的眼动追踪,减少误报。

技术方案

1. 墨镜场景

问题分析:

  • 可见光摄像头被墨镜镜片阻挡
  • 偏光墨镜进一步降低可见光透过率
  • 镜面反射干扰

解决方案:

1.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
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
"""
红外补光方案

使用 940nm 红外 LED 穿透墨镜
"""

import numpy as np

class IRIlluminator:
"""
红外补光控制器

动态调整红外 LED 强度
"""

def __init__(self):
# 红外 LED 参数
self.wavelength = 940e-9 # 940nm
self.max_intensity = 1.0 # 最大强度
self.current_intensity = 0.5

# 检测阈值
self.eye_detection_confidence_threshold = 0.7

def adjust_intensity(self, image, eye_detection_result):
"""
根据检测结果调整红外强度

Args:
image: 输入图像
eye_detection_result: {
'left_eye_detected': bool,
'right_eye_detected': bool,
'confidence': float
}

Returns:
intensity: 调整后的红外强度
"""
if not eye_detection_result['left_eye_detected'] or not eye_detection_result['right_eye_detected']:
# 眼睛未检测到,增加红外强度
self.current_intensity = min(self.max_intensity, self.current_intensity + 0.1)
elif eye_detection_result['confidence'] < self.eye_detection_confidence_threshold:
# 置信度低,略微增加
self.current_intensity = min(self.max_intensity, self.current_intensity + 0.05)
else:
# 检测正常,保持或略微降低
self.current_intensity = max(0.3, self.current_intensity - 0.02)

return self.current_intensity


class SunglassesRobustDetector:
"""
墨镜场景鲁棒检测器

结合可见光和红外图像
"""

def __init__(self):
self.ir_illuminator = IRIlluminator()

# 眼动追踪模型
# 红外专用模型 vs 可见光模型
self.ir_model = self._load_model('eye_tracker_ir.pth')
self.rgb_model = self._load_model('eye_tracker_rgb.pth')

def detect(self, rgb_image, ir_image):
"""
检测眼动

Args:
rgb_image: 可见光图像
ir_image: 红外图像

Returns:
result: {
'gaze_direction': (x, y, z),
'eye_openness': float,
'confidence': float,
'sunglasses_detected': bool
}
"""
# 1. 检测是否佩戴墨镜
sunglasses_detected = self._detect_sunglasses(rgb_image)

# 2. 选择模型
if sunglasses_detected:
# 使用红外模型
result = self._detect_with_ir(ir_image)
else:
# 使用可见光模型
result = self._detect_with_rgb(rgb_image)

# 3. 调整红外强度
self.ir_illuminator.adjust_intensity(ir_image, result)

result['sunglasses_detected'] = sunglasses_detected
return result

def _detect_sunglasses(self, rgb_image):
"""
检测是否佩戴墨镜

方法:分析眼部区域的亮度和对比度
"""
# 提取眼部区域
eye_region = self._extract_eye_region(rgb_image)

# 计算亮度
brightness = np.mean(eye_region)

# 计算对比度
contrast = np.std(eye_region)

# 墨镜特征:低亮度 + 低对比度
# 正常眼睛:较高亮度 + 较高对比度
if brightness < 50 and contrast < 30:
return True

return False

def _detect_with_ir(self, ir_image):
"""红外图像检测"""
# 红外图像的优势:
# 1. 可穿透墨镜
# 2. 不受可见光干扰
# 3. 可检测瞳孔

result = self.ir_model.predict(ir_image)
return result

def _detect_with_rgb(self, rgb_image):
"""可见光图像检测"""
result = self.rgb_model.predict(rgb_image)
return result

def _extract_eye_region(self, image):
"""提取眼部区域"""
# 使用人脸关键点定位眼睛
# 返回眼部区域的图像
pass

def _load_model(self, path):
"""加载模型"""
# 实际实现需要加载预训练模型
return None


# ============ 测试 ============

if __name__ == "__main__":
detector = SunglassesRobustDetector()

# 模拟数据
rgb_image = np.random.randint(0, 255, (480, 640, 3), dtype=np.uint8)
ir_image = np.random.randint(0, 255, (480, 640), dtype=np.uint8)

result = detector.detect(rgb_image, ir_image)
print(f"检测结果: {result}")

1.2 偏光墨镜处理

偏光墨镜特点:

  • 选择性吸收特定偏振方向的光
  • 可能导致红外 LED 光被部分吸收

解决方案:

  • 使用圆偏振红外 LED
  • 多角度红外光源
  • 增加红外功率

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
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
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
"""
口罩场景鲁棒检测

基于上半脸特征推断整体状态
"""

class MaskRobustDetector:
"""
口罩场景鲁棒检测器

仅依赖上半脸特征
"""

def __init__(self):
# 可用特征
self.available_features = [
'eye_openness',
'eye_blink_rate',
'gaze_direction',
'head_pose',
'eyebrow_position',
'forehead_wrinkles'
]

# 缺失特征
self.missing_features = [
'mouth_openness',
'yawn_detection',
'jaw_position'
]

# 权重调整
self.adjusted_weights = {
'eye_openness': 0.35, # 提高眼动特征权重
'eye_blink_rate': 0.25,
'gaze_direction': 0.20,
'head_pose': 0.15,
'eyebrow_position': 0.05
}

def detect(self, face_landmarks, mask_detected: bool):
"""
检测驾驶员状态

Args:
face_landmarks: 面部关键点
mask_detected: 是否检测到口罩

Returns:
state: {
'fatigue_level': int,
'distraction': bool,
'confidence': float
}
"""
if mask_detected:
# 使用调整后的权重
return self._detect_with_mask(face_landmarks)
else:
# 正常检测
return self._detect_normal(face_landmarks)

def _detect_with_mask(self, landmarks):
"""
口罩场景检测

仅使用上半脸特征
"""
# 提取上半脸特征
upper_face_features = self._extract_upper_face_features(landmarks)

# 疲劳检测
fatigue_score = self._calculate_fatigue_with_mask(upper_face_features)

# 分心检测
distraction_score = self._calculate_distraction_with_mask(upper_face_features)

return {
'fatigue_level': self._score_to_level(fatigue_score),
'distraction': distraction_score > 0.6,
'confidence': 0.85, # 口罩场景置信度略低
'mask_mode': True
}

def _extract_upper_face_features(self, landmarks):
"""
提取上半脸特征
"""
# 眼睛关键点
left_eye = landmarks['left_eye']
right_eye = landmarks['right_eye']

# 眉毛关键点
left_eyebrow = landmarks['left_eyebrow']
right_eyebrow = landmarks['right_eyebrow']

# 计算特征
features = {
'eye_openness': self._calculate_eye_openness(left_eye, right_eye),
'eye_blink_rate': self._calculate_blink_rate(),
'gaze_direction': self._estimate_gaze(left_eye, right_eye),
'head_pose': landmarks.get('head_pose', (0, 0, 0)),
'eyebrow_position': self._calculate_eyebrow_position(left_eyebrow, right_eyebrow)
}

return features

def _calculate_fatigue_with_mask(self, features):
"""
口罩场景疲劳检测

使用替代指标:
1. PERCLOS(眼睑闭合百分比)
2. 眨眼频率
3. 注视稳定性
4. 头部姿态稳定性
"""
score = 0.0

# PERCLOS
if features['eye_openness'] < 0.2:
score += 0.35

# 眨眼频率
if features['eye_blink_rate'] > 25: # >25次/分钟
score += 0.25

# 注视稳定性
gaze_stability = np.std(features['gaze_direction'])
if gaze_stability > 0.5:
score += 0.20

# 头部稳定性
head_stability = np.std(features['head_pose'])
if head_stability > 10:
score += 0.15

return score

def _calculate_distraction_with_mask(self, features):
"""
口罩场景分心检测
"""
score = 0.0

# 视线偏离
gaze_deviation = np.linalg.norm(features['gaze_direction'])
if gaze_deviation > 30: # 偏离 > 30度
score += 0.50

# 头部偏转
head_yaw = abs(features['head_pose'][0])
if head_yaw > 20:
score += 0.30

return score

def _detect_normal(self, landmarks):
"""正常检测"""
# 完整面部特征检测
pass

def _calculate_eye_openness(self, left_eye, right_eye):
"""计算眼睑开度"""
# EAR 计算
pass

def _calculate_blink_rate(self):
"""计算眨眼频率"""
pass

def _estimate_gaze(self, left_eye, right_eye):
"""估计视线方向"""
pass

def _calculate_eyebrow_position(self, left_eyebrow, right_eyebrow):
"""计算眉毛位置"""
pass

def _score_to_level(self, score):
"""分数转等级"""
if score < 0.3:
return 0
elif score < 0.6:
return 1
else:
return 2


# 测试
if __name__ == "__main__":
detector = MaskRobustDetector()

# 模拟数据
landmarks = {
'left_eye': [(x, y) for x, y in zip(range(6), range(6))],
'right_eye': [(x, y) for x, y in zip(range(6), range(6))],
'left_eyebrow': [(x, y) for x, y in zip(range(5), range(5))],
'right_eyebrow': [(x, y) for x, y in zip(range(5), range(5))],
'head_pose': (5, 3, 0)
}

result = detector.detect(landmarks, mask_detected=True)
print(f"检测结果: {result}")

3. 低光照场景

问题分析:

  • 信噪比下降
  • 面部特征模糊
  • 颜色信息丢失

解决方案:

方案 原理 效果
红外补光 940nm LED 照明 ✅ 高效
近红外摄像头 850nm 敏感传感器 ✅ 高效
高灵敏度传感器 大像素、低噪声 ✅ 成本高
AI 增强 低光照图像增强网络 ⚠️ 计算量大
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
"""
低光照图像增强

使用深度学习增强低光照图像
"""

import torch
import torch.nn as nn

class LowLightEnhancer(nn.Module):
"""
低光照图像增强网络

基于 Zero-DCE 架构
"""

def __init__(self):
super().__init__()

# 增强曲线参数估计网络
self.enhance_net = nn.Sequential(
nn.Conv2d(3, 32, 3, padding=1),
nn.ReLU(),
nn.Conv2d(32, 32, 3, padding=1),
nn.ReLU(),
nn.Conv2d(32, 32, 3, padding=1),
nn.ReLU(),
nn.Conv2d(32, 24, 3, padding=1), # 8组曲线参数
nn.Tanh()
)

def forward(self, low_light_image):
"""
增强低光照图像

Args:
low_light_image: (B, 3, H, W)

Returns:
enhanced_image: (B, 3, H, W)
"""
# 估计曲线参数
curve_params = self.enhance_net(low_light_image)

# 应用增强曲线
enhanced = self._apply_curve(low_light_image, curve_params)

return enhanced

def _apply_curve(self, image, curve_params):
"""
应用增强曲线

Zero-DCE 的核心:通过迭代曲线调整增强图像
"""
# 分离参数
params = curve_params.view(-1, 8, 3, image.shape[2], image.shape[3])

enhanced = image
for i in range(8):
# 每次迭代的曲线参数
alpha = params[:, i, :, :, :]

# 曲线增强
enhanced = enhanced + alpha * (enhanced - torch.pow(enhanced, 2))

return enhanced


# 测试
if __name__ == "__main__":
enhancer = LowLightEnhancer()

# 模拟低光照图像
low_light = torch.rand(1, 3, 224, 224) * 0.3 # 低亮度

enhanced = enhancer(low_light)

print(f"输入亮度: {low_light.mean():.3f}")
print(f"输出亮度: {enhanced.mean():.3f}")

鲁棒性测试标准

Euro NCAP 2026 鲁棒性要求

场景 测试方法 通过条件
墨镜(非偏光) 驾驶员佩戴标准墨镜 检测准确率 ≥ 85%
墨镜(偏光) 驾驶员佩戴偏光墨镜 检测准确率 ≥ 80%
口罩 驾驶员佩戴医用口罩 检测准确率 ≥ 80%
低光照 光照 < 10 lux 检测准确率 ≥ 85%
逆光 强光源在驾驶员背后 检测准确率 ≥ 85%
帽子 驾驶员佩戴帽子 检测准确率 ≥ 90%

硬件选型建议

组件 推荐配置 原因
摄像头传感器 RGB-IR 传感器 同时支持可见光和红外
红外 LED 940nm × 4 穿透墨镜、低光照
镜头 广角镜头 + IR 滤光片切换 适应不同场景
处理器 支持 AI 加速 实时图像增强

总结: 墨镜/口罩/低光照是 DMS 实际部署的主要挑战。解决方案的核心是红外补光 + 多模态融合 + 鲁棒性算法。建议在硬件设计阶段就考虑这些场景,确保 Euro NCAP 鲁棒性测试通过。


DMS 眼动追踪鲁棒性优化:墨镜/口罩/低光照场景解决方案
https://dapalm.com/2026/06/05/2026-06-05-DMS-Robustness-Sunglasses-Mask-LowLight/
作者
Mars
发布于
2026年6月5日
许可协议