戴墨镜时DMS失效?红外+多模态融合解决方案

问题背景

Euro NCAP测试发现的问题

2024年UNECE JRC报告指出:

“When wearing sunglasses, drivers were able to stay distracted indefinitely without receiving any warning from the DMS.”

墨镜对DMS的影响

DMS类型 工作原理 戴墨镜时表现
RGB摄像头 可见光成像 完全失效(无法看到眼睛)
红外摄像头 940nm成像 部分有效(可穿透部分墨镜)
头姿估计 仅用头部姿态 可工作(但准确率下降30%)

技术分析

1. 墨镜光谱特性

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
sunglasses_transmission = {
"可见光": {
"波长": "380-780nm",
"透过率": "<15%",
"结论": "几乎完全阻挡"
},
"近红外(NIR)": {
"波长": "780-1400nm",
"透过率": "30-60%",
"结论": "部分穿透(取决于镜片)"
},
"短波红外(SWIR)": {
"波长": "1400-3000nm",
"透过率": ">80%",
"结论": "几乎完全穿透"
}
}

2. 红外DMS原理

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
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
import numpy as np
import cv2

class InfraredEyeTracker:
"""
红外眼动追踪

利用940nm红外光的特性:
1. 部分穿透墨镜
2. 不受可见光干扰
3. 瞳孔-虹膜对比度高

核心技术:瞳孔-角膜反射法(PCCR)
"""

def __init__(self):
# 红外LED位置(相对于摄像头)
self.led_positions = np.array([
[0, -50], # 上方LED
[-30, 0], # 左侧LED
[30, 0], # 右侧LED
[0, 50] # 下方LED
])

def detect_pupil(self, ir_image):
"""
检测瞳孔

Args:
ir_image: 红外图像

Returns:
pupil_center: 瞳孔中心坐标
pupil_radius: 瞳孔半径
"""
# 红外图像瞳孔检测(暗瞳孔效应)
# 瞳孔在红外光下呈现为暗区

# 高斯模糊
blurred = cv2.GaussianBlur(ir_image, (7, 7), 0)

# 自适应阈值(处理光照变化)
thresh = cv2.adaptiveThreshold(
blurred, 255,
cv2.ADAPTIVE_THRESH_GAUSSIAN_C,
cv2.THRESH_BINARY_INV,
11, 2
)

# 形态学操作
kernel = cv2.getStructuringElement(cv2.MORPH_ELLIPSE, (5, 5))
thresh = cv2.morphologyEx(thresh, cv2.MORPH_OPEN, kernel)
thresh = cv2.morphologyEx(thresh, cv2.MORPH_CLOSE, kernel)

# 查找轮廓
contours, _ = cv2.findContours(thresh, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)

if not contours:
return None, None

# 找最大轮廓(假设是瞳孔)
pupil_contour = max(contours, key=cv2.contourArea)

# 拟合椭圆
if len(pupil_contour) >= 5:
ellipse = cv2.fitEllipse(pupil_contour)
center = np.array(ellipse[0])
axes = ellipse[1]
radius = np.mean(axes) / 2
return center, radius

return None, None

def detect_corneal_reflection(self, ir_image, threshold=200):
"""
检测角膜反射(Purkinje image)

Args:
ir_image: 红外图像
threshold: 亮度阈值

Returns:
cr_center: 角膜反射中心
"""
# 角膜反射呈现为高亮区域
_, bright = cv2.threshold(ir_image, threshold, 255, cv2.THRESH_BINARY)

contours, _ = cv2.findContours(bright, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)

if not contours:
return None

# 找最大亮点
cr_contour = max(contours, key=cv2.contourArea)
M = cv2.moments(cr_contour)

if M["m00"] > 0:
cr_center = np.array([M["m10"] / M["m00"], M["m01"] / M["m00"]])
return cr_center

return None

def estimate_gaze(self, pupil_center, cr_center):
"""
估计视线方向

Args:
pupil_center: 瞳孔中心
cr_center: 角膜反射中心

Returns:
gaze_vector: 视线向量
"""
if pupil_center is None or cr_center is None:
return None

# PCCR法:瞳孔-角膜反射向量
vector = pupil_center - cr_center

# 归一化
gaze_vector = vector / (np.linalg.norm(vector) + 1e-6)

return gaze_vector


# ============ 墨镜穿透增强 ============

class SunglassesRobustTracker:
"""
墨镜鲁棒追踪器

策略:
1. 红外光穿透
2. 头姿补偿
3. 多LED源
"""

def __init__(self):
self.ir_tracker = InfraredEyeTracker()
self.head_pose_estimator = None # 简化

def detect_with_sunglasses(self, ir_image):
"""
戴墨镜时的检测

Returns:
result: {
'eye_detected': bool,
'gaze_vector': array or None,
'confidence': float,
'fallback_mode': str
}
"""
# 尝试红外检测
pupil, radius = self.ir_tracker.detect_pupil(ir_image)
cr = self.ir_tracker.detect_corneal_reflection(ir_image)

if pupil is not None and cr is not None:
# 红外成功穿透
gaze = self.ir_tracker.estimate_gaze(pupil, cr)
return {
'eye_detected': True,
'gaze_vector': gaze,
'confidence': 0.9,
'fallback_mode': 'infrared'
}

# 红外无法穿透,使用头姿补偿
if pupil is None:
# 只能检测到角膜反射(墨镜表面反射)
if cr is not None:
# 使用角膜反射估计大概视线
return {
'eye_detected': False,
'gaze_vector': None,
'confidence': 0.4,
'fallback_mode': 'corneal_only'
}

# 完全无法检测,使用头姿
return {
'eye_detected': False,
'gaze_vector': None,
'confidence': 0.2,
'fallback_mode': 'head_pose'
}


# ============ 多LED源增强穿透 ============

class MultiLEDGazeTracker:
"""
多LED源视线追踪

使用多个不同角度的红外LED增强穿透:
- 部分墨镜对某些角度的光穿透率更高
- 多源提供冗余
"""

def __init__(self, num_leds=4):
self.num_leds = num_leds
# 不同波长LED
self.led_wavelengths = [850, 880, 910, 940] # nm

def select_best_led(self, ir_images):
"""
选择最佳LED源

Args:
ir_images: (num_leds, H, W) 多个LED照明的图像

Returns:
best_idx: 最佳LED索引
contrast: 对比度值
"""
contrasts = []

for img in ir_images:
# 计算瞳孔区域的对比度
# 高对比度表示穿透效果好
contrast = self._compute_contrast(img)
contrasts.append(contrast)

best_idx = np.argmax(contrasts)
return best_idx, contrasts[best_idx]

def _compute_contrast(self, img):
"""计算图像对比度"""
return np.std(img) / (np.mean(img) + 1e-6)


# ============ 多模态融合 ============

class MultimodalDistractionDetector:
"""
多模态分心检测

当视线无法检测时,使用其他模态补偿
"""

def __init__(self):
self.gaze_tracker = SunglassesRobustTracker()

def detect_distraction(self, ir_image, head_pose, steering_angle, lane_offset):
"""
多模态分心检测

Args:
ir_image: 红外图像
head_pose: 头部姿态 (pitch, yaw, roll)
steering_angle: 方向盘转角
lane_offset: 车道偏移

Returns:
result: 分心检测结果
"""
# 尝试视线检测
eye_result = self.gaze_tracker.detect_with_sunglasses(ir_image)

# 根据检测模式调整权重
if eye_result['fallback_mode'] == 'infrared':
# 正常模式:主要依赖视线
weights = {
'gaze': 0.6,
'head_pose': 0.2,
'steering': 0.1,
'lane': 0.1
}
gaze_score = self._gaze_to_distraction(eye_result['gaze_vector'])

elif eye_result['fallback_mode'] == 'head_pose':
# 墨镜模式:主要依赖头姿和车辆行为
weights = {
'gaze': 0.0,
'head_pose': 0.4,
'steering': 0.3,
'lane': 0.3
}
gaze_score = 0.5 # 中性值

else:
# 中间状态
weights = {
'gaze': 0.3,
'head_pose': 0.3,
'steering': 0.2,
'lane': 0.2
}
gaze_score = 0.5

# 各模态得分
head_score = self._head_pose_to_distraction(head_pose)
steering_score = self._steering_to_distraction(steering_angle)
lane_score = self._lane_to_distraction(lane_offset)

# 融合
distraction_score = (
weights['gaze'] * gaze_score +
weights['head_pose'] * head_score +
weights['steering'] * steering_score +
weights['lane'] * lane_score
)

return {
'is_distracted': distraction_score > 0.6,
'score': distraction_score,
'mode': eye_result['fallback_mode'],
'confidence': eye_result['confidence']
}

def _gaze_to_distraction(self, gaze_vector):
"""视线偏离得分"""
if gaze_vector is None:
return 0.5
# 简化:偏离中心程度
deviation = np.linalg.norm(gaze_vector)
return min(1.0, deviation / 0.5)

def _head_pose_to_distraction(self, head_pose):
"""头部姿态得分"""
yaw = abs(head_pose[1]) # 水平转动
return min(1.0, yaw / 30) # 30度为阈值

def _steering_to_distraction(self, steering_angle):
"""方向盘行为得分"""
# 大角度修正表示分心后修正
return min(1.0, abs(steering_angle) / 15)

def _lane_to_distraction(self, lane_offset):
"""车道偏移得分"""
return min(1.0, abs(lane_offset) / 0.5)


# ============ 实际测试 ============

if __name__ == "__main__":
# 模拟测试
print("=" * 60)
print("墨镜鲁棒性DMS测试")
print("=" * 60)

# 初始化
detector = MultimodalDistractionDetector()

# 模拟场景
scenarios = [
{
"name": "正常驾驶(无墨镜)",
"ir_quality": "good",
"head_pose": [0, 0, 0],
"steering": 0,
"lane_offset": 0
},
{
"name": "分心看手机(无墨镜)",
"ir_quality": "good",
"head_pose": [-20, 30, 0],
"steering": 5,
"lane_offset": 0.1
},
{
"name": "分心看手机(戴墨镜)",
"ir_quality": "blocked",
"head_pose": [-20, 30, 0],
"steering": 5,
"lane_offset": 0.1
},
{
"name": "正常驾驶(戴墨镜)",
"ir_quality": "blocked",
"head_pose": [0, 5, 0],
"steering": 0,
"lane_offset": 0
}
]

for scenario in scenarios:
# 模拟红外图像
ir_image = np.random.randint(0, 255, (480, 640), dtype=np.uint8)

# 模拟检测结果
if scenario["ir_quality"] == "blocked":
# 墨镜阻挡,模拟只能用头姿
eye_result = {
'fallback_mode': 'head_pose',
'confidence': 0.3,
'gaze_vector': None
}
else:
eye_result = {
'fallback_mode': 'infrared',
'confidence': 0.9,
'gaze_vector': np.array([0.1, 0.2])
}

result = detector.detect_distraction(
ir_image,
scenario["head_pose"],
scenario["steering"],
scenario["lane_offset"]
)

print(f"\n场景: {scenario['name']}")
print(f" 检测模式: {result['mode']}")
print(f" 置信度: {result['confidence']:.2f}")
print(f" 分心得分: {result['score']:.2f}")
print(f" 判定: {'分心' if result['is_distracted'] else '正常'}")

解决方案对比

方案 技术 墨镜穿透 成本 Euro NCAP合规
RGB摄像头 可见光 ❌ 完全失效 ❌ 不合规
红外摄像头(940nm) 近红外 ⚠️ 部分穿透 ⚠️ 需要补偿
红外摄像头(850nm) 近红外 ⚠️ 穿透更好 ⚠️ 需要补偿
多LED源 多角度照明 ✅ 显著改善 中高 ✅ 合规
多模态融合 视线+头姿+车辆 ✅ 补偿生效 ✅ 合规

IMS开发启示

1. 硬件选型

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
hardware_recommendation = {
"基础配置": {
"摄像头": "RGB-IR双摄",
"红外波长": "940nm",
"LED功率": "100mW/sr",
"穿透能力": "中等"
},
"推荐配置": {
"摄像头": "专用IR摄像头",
"红外波长": "850nm+940nm双波长",
"LED功率": "150mW/sr × 4",
"穿透能力": "高"
},
"最佳配置": {
"摄像头": "SWIR摄像头(1400nm)",
"红外波长": "1400-1700nm",
"LED功率": "200mW/sr",
"穿透能力": "极高(几乎穿透所有墨镜)"
}
}

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
class IMSSunglassesHandling:
"""
IMS墨镜处理策略
"""

def __init__(self):
self.strategies = [
{
"condition": "红外穿透成功",
"action": "正常视线检测",
"accuracy": 95
},
{
"condition": "红外部分穿透",
"action": "视线+头姿融合",
"accuracy": 85
},
{
"condition": "红外完全阻挡",
"action": "头姿+车辆行为",
"accuracy": 75
},
{
"condition": "检测到墨镜",
"action": "提示用户摘下墨镜",
"accuracy": "N/A"
}
]

3. 测试场景

场景 墨镜类型 预期检测率 补偿方案
正常驾驶 95% 正常
分心 92% 正常
分心 普通墨镜 85% 多LED
分心 偏光墨镜 70% 多模态融合
分心 红外阻挡墨镜 60% 提示摘下

关键结论

  1. 墨镜是DMS重大挑战:部分系统完全失效
  2. 红外有部分穿透能力:850nm > 940nm
  3. 多LED源有效:不同角度增强穿透
  4. 多模态融合必要:视线失效时补偿
  5. Euro NCAP要求明确:必须能检测戴墨镜驾驶员

参考资源:


戴墨镜时DMS失效?红外+多模态融合解决方案
https://dapalm.com/2026/04/25/2026-04-25-dms-sunglasses-robustness-infrared-2025/
作者
Mars
发布于
2026年4月25日
许可协议