Seeing Machines 酒驾检测技术论文 Part 2 深度解读:Intoxication ≠ Impairment,DMS 的 Cause-Agnostic 新范式

论文来源: Seeing Machines Technical Paper Series on Intoxication, Part 2 (2026年4月)
官方链接: https://seeingmachines.com/wp-content/uploads/2026/04/Technical-Paper-Intoxication-Part-2.pdf
Part 1 链接: https://seeingmachines.com/technical-paper-series-intoxication/
作者机构: Seeing Machines Limited (LSE: SEE),总部澳大利亚,视觉监控技术全球领导者
关键人物: Dr Mike Lenné,Chief Safety Officer

核心创新

Seeing Machines 在 Part 2 中提出了一个根本性的范式转换:

有效座舱安全系统必须关注驾驶员的功能状态(functional state),而不是识别特定化学物质。

这打破了传统酒驾检测的底层逻辑——不再追求”测出你喝了什么”,而是”测出你还能不能开车”。

Intoxication vs Impairment 的关键区分

概念 定义 检测方式 局限性
Intoxication(中毒) 体内存在特定物质 血液/呼气/唾液化学检测 只测物质不测功能
Impairment(损伤) 物质对功能能力的实际影响程度 视觉行为特征检测 需要功能基线建模

方法详解

1. 为什么 BAC 是不充分的 Ground Truth

Part 1(2025年12月发布)已经论证了 BAC 作为实时损伤检测 Ground Truth 的不足:

BAC 阈值问题 具体说明
个体差异 同一 BAC 值对不同人功能影响差异可达 40%
耐受性 长期饮酒者 BAC 0.08% 可能功能正常,偶尔饮酒者 0.04% 已严重损伤
多物质组合 酒精+药物+疲劳的组合效应无法用单一化学阈值衡量
时间滞后 BAC 峰值与功能损伤峰值存在 15-30 分钟时间差
非物质因素 疲劳、疾病、情绪状态同样导致功能损伤,BAC 完全无法覆盖

2. Camera-based DMS 的 Cause-Agnostic 方案

Seeing Machines 的核心论点:基于摄像头的 DMS 聚焦于 Impairment,而不是 Intoxication。

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
"""
Seeing Machines Cause-Agnostic Impairment Detection
论文:Technical Paper Series on Intoxication, Part 2 (2026)

核心方法:通过视觉行为特征评估功能损伤,不依赖化学物质检测
"""

import numpy as np
from dataclasses import dataclass
from typing import List, Tuple, Optional

@dataclass
class ImpairmentIndicator:
"""损伤指标数据结构"""
name: str
value: float # 0.0 = 正常, 1.0 = 严重损伤
confidence: float # 0.0-1.0
trend: str # 'improving', 'stable', 'deteriorating'

class CauseAgnosticImpairmentDetector:
"""
Cause-Agnostic 功能损伤检测器

不检测具体物质,而是评估驾驶功能状态:
1. 眼动模式异常(注视点离散度、扫视频率)
2. 面部表情特征(微表情迟滞、面部肌肉松弛)
3. 头部姿态稳定性(头部晃动频率、保持能力)
4. 眨眼参数(频率、持续时间、PERCLOS)
5. 行为模式异常(车道保持、方向盘微调)
"""

def __init__(self, config: dict):
# 眼动参数
self.gaze_disruption_threshold = config.get('gaze_disruption', 0.65)
self.saccade_frequency_baseline = config.get('saccade_freq', 2.5) # Hz

# 面部参数
self.facial_latency_threshold = config.get('facial_latency', 0.3) # seconds
self.muscle_tone_baseline = config.get('muscle_tone', 0.75)

# 头部参数
self.head_stability_window = config.get('head_window', 30) # seconds
self.head_drift_threshold = config.get('head_drift', 5.0) # degrees

# PERCLOS 参数
self.perclos_threshold = config.get('perclos_eye', 0.2) # eye openness ratio
self.perclos_window = config.get('perclos_window', 60) # seconds

# 综合阈值
self.impairment_alert_threshold = config.get('alert_threshold', 0.45)
self.impairment_critical_threshold = config.get('critical_threshold', 0.70)

# 基线模型
self.baseline_gaze_entropy = None
self.baseline_blink_rate = None
self.baseline_steering_entropy = None

def compute_gaze_entropy(self, gaze_points: np.ndarray) -> float:
"""
计算注视点熵

损伤状态下注视模式变得过度集中(隧道视觉)或过度分散(注意力涣散)

Args:
gaze_points: (N, 2) 注视点序列,归一化到 [0,1]×[0,1]

Returns:
entropy: Shannon 熵值,0-1 归一化
"""
# 将注视点空间离散化为网格
grid_size = 20
hist, _, _ = np.histogram2d(
gaze_points[:, 0], gaze_points[:, 1],
bins=grid_size, range=[[0, 1], [0, 1]]
)

# 归一化为概率分布
prob = hist / (hist.sum() + 1e-8)

# Shannon 熵
entropy = -np.sum(prob[prob > 0] * np.log2(prob[prob > 0]))
max_entropy = np.log2(grid_size * grid_size)

return entropy / max_entropy

def detect_saccade_anomalies(self, gaze_sequence: np.ndarray,
fps: int = 30) -> Tuple[float, float]:
"""
检测扫视异常

损伤特征:
- 扫视频率降低(反应迟钝)
- 扫视幅度异常(过短=隧道视觉,过长=注意力涣散)
- 扫视延迟增加(决策时间延长)

Returns:
(frequency_score, amplitude_score): 0=正常, 1=严重异常
"""
dt = 1.0 / fps
velocities = np.diff(gaze_sequence, axis=0) / dt

# 扫视速度(正常 > 200°/s)
speeds = np.linalg.norm(velocities, axis=1)
saccade_threshold = 200.0 # degrees/second
saccade_mask = speeds > saccade_threshold

# 扫视频率
saccade_count = np.sum(saccade_mask)
duration_sec = len(gaze_sequence) / fps
saccade_freq = saccade_count / duration_sec

# 频率得分(低于基线的程度)
freq_ratio = saccade_freq / self.saccade_frequency_baseline
frequency_score = max(0.0, min(1.0, 1.0 - freq_ratio))

# 幅度得分
if saccade_count > 0:
saccade_amplitudes = np.linalg.norm(
np.diff(gaze_sequence[saccade_mask], axis=0), axis=1
)
# 正常扫视幅度 5-25°
abnormal_low = np.sum(saccade_amplitudes < 3.0) / saccade_count
abnormal_high = np.sum(saccade_amplitudes > 40.0) / saccade_count
amplitude_score = min(1.0, abnormal_low + abnormal_high)
else:
amplitude_score = 0.5 # 无扫视 = 不确定

return frequency_score, amplitude_score

def compute_perclos(self, eye_openness: np.ndarray,
fps: int = 30) -> float:
"""
计算 PERCLOS(眼睑闭合百分比)

损伤状态下 PERCLOS 升高,反映警觉性下降

Args:
eye_openness: (N,) 眼睑开度序列 0-1
fps: 帧率

Returns:
perclos: 0-100%
"""
window_frames = int(self.perclos_window * fps)
if len(eye_openness) < window_frames:
return 0.0

# 滑动窗口计算
closed_mask = eye_openness < self.perclos_threshold
perclos_values = []

for i in range(len(eye_openness) - window_frames):
window = closed_mask[i:i+window_frames]
perclos_values.append(np.sum(window) / window_frames * 100)

return np.mean(perclos_values[-10:]) if perclos_values else 0.0

def detect_facial_latency(self, facial_landmarks: np.ndarray,
fps: int = 30) -> float:
"""
检测面部表情迟滞

损伤状态下面部微表情反应时间延长
(对刺激的响应延迟 > 300ms 视为异常)

Args:
facial_landmarks: (N, 68, 2) 面部关键点序列

Returns:
latency_score: 0=正常, 1=严重迟滞
"""
# 提取嘴部区域(关键点 48-67)
mouth_points = facial_landmarks[:, 48:68, :]

# 计算嘴部变化率
mouth_movement = np.linalg.norm(
np.diff(mouth_points, axis=0), axis=2
).mean(axis=1)

# 检测运动爆发后的响应延迟
movement_threshold = np.percentile(mouth_movement, 90)
bursts = np.where(mouth_movement > movement_threshold)[0]

if len(bursts) < 2:
return 0.0

# 计算连续爆发间的间隔(反映反应速度)
intervals = np.diff(bursts) / fps
normal_interval = 1.0 # 正常间隔 ~1秒
delayed_ratio = np.sum(intervals > normal_interval * 2) / len(intervals)

return min(1.0, delayed_ratio * 2)

def assess_impairment(self, gaze_data: np.ndarray,
eye_openness: np.ndarray,
facial_landmarks: np.ndarray,
steering_signal: np.ndarray,
fps: int = 30) -> Tuple[float, List[ImpairmentIndicator]]:
"""
综合功能损伤评估

Cause-Agnostic 方案:不区分酒精/药物/疲劳,直接评估功能状态

Args:
gaze_data: (N, 2) 注视点序列
eye_openness: (N,) 眼睑开度
facial_landmarks: (N, 68, 2) 面部关键点
steering_signal: (N,) 方向盘角度序列
fps: 帧率

Returns:
(impairment_score, indicators)
"""
indicators = []

# 1. 眼动熵
gaze_entropy = self.compute_gaze_entropy(gaze_data)
# 损伤时熵值偏离基线(过高或过低)
if self.baseline_gaze_entropy is not None:
entropy_deviation = abs(gaze_entropy - self.baseline_gaze_entropy)
entropy_score = min(1.0, entropy_deviation * 3)
else:
entropy_score = 0.3 # 无基线时给中等分
indicators.append(ImpairmentIndicator(
'gaze_entropy', entropy_score, 0.7, 'stable'
))

# 2. 扫视异常
freq_score, amp_score = self.detect_saccade_anomalies(gaze_data, fps)
saccade_score = (freq_score + amp_score) / 2
indicators.append(ImpairmentIndicator(
'saccade_anomaly', saccade_score, 0.65, 'stable'
))

# 3. PERCLOS
perclos = self.compute_perclos(eye_openness, fps)
perclos_score = min(1.0, perclos / 20.0) # 20% PERCLOS = 满分损伤
indicators.append(ImpairmentIndicator(
'perclos', perclos_score, 0.85, 'deteriorating' if perclos > 10 else 'stable'
))

# 4. 面部迟滞
facial_score = self.detect_facial_latency(facial_landmarks, fps)
indicators.append(ImpairmentIndicator(
'facial_latency', facial_score, 0.6, 'stable'
))

# 5. 转向熵(方向盘微调的随机性)
steering_diff = np.abs(np.diff(steering_signal))
steering_entropy = -np.sum(
(p := steering_diff / (steering_diff.sum() + 1e-8)) * np.log2(p + 1e-8)
)
# 损伤时转向熵增加(操作不规律)
steering_score = min(1.0, steering_entropy / 5.0)
indicators.append(ImpairmentIndicator(
'steering_entropy', steering_score, 0.55, 'stable'
))

# 加权综合
weights = np.array([ind.confidence for ind in indicators])
scores = np.array([ind.value for ind in indicators])
impairment_score = np.average(scores, weights=weights)

return impairment_score, indicators


# ==================== 测试用例 ====================
if __name__ == "__main__":
np.random.seed(42)
fps = 30
duration_sec = 120 # 2分钟
n_frames = fps * duration_sec

# 模拟正常驾驶数据
normal_gaze = np.column_stack([
0.5 + 0.15 * np.sin(np.linspace(0, 4*np.pi, n_frames)) + np.random.normal(0, 0.05, n_frames),
0.5 + 0.10 * np.cos(np.linspace(0, 3*np.pi, n_frames)) + np.random.normal(0, 0.05, n_frames)
])
normal_gaze = np.clip(normal_gaze, 0, 1)

normal_eye = np.clip(
0.8 + 0.05 * np.sin(np.linspace(0, 10*np.pi, n_frames)) + np.random.normal(0, 0.03, n_frames),
0, 1
)

# 模拟损伤驾驶数据(酒精/疲劳混合效应)
impaired_gaze = np.column_stack([
0.5 + 0.08 * np.sin(np.linspace(0, 2*np.pi, n_frames)) + np.random.normal(0, 0.08, n_frames),
0.5 + 0.05 * np.cos(np.linspace(0, 1.5*np.pi, n_frames)) + np.random.normal(0, 0.08, n_frames)
])
impaired_gaze = np.clip(impaired_gaze, 0, 1)

# 模拟损伤眼动(更多闭眼)
impaired_eye = np.clip(
0.7 + 0.08 * np.sin(np.linspace(0, 4*np.pi, n_frames)) + np.random.normal(0, 0.05, n_frames),
0, 1
)
# 注入额外闭眼段
for _ in range(5):
start = np.random.randint(0, n_frames - 90)
impaired_eye[start:start+45] *= 0.1 # 1.5秒闭眼

# 生成模拟面部关键点
normal_face = np.random.normal(0, 1, (n_frames, 68, 2))
impaired_face = np.random.normal(0, 1.5, (n_frames, 68, 2)) # 更大抖动

# 转向信号
normal_steer = np.cumsum(np.random.normal(0, 0.5, n_frames))
impaired_steer = np.cumsum(np.random.normal(0, 1.2, n_frames)) # 更不规律

# 初始化检测器
detector = CauseAgnosticImpairmentDetector({
'gaze_disruption': 0.65,
'saccade_freq': 2.5,
'perclos_eye': 0.2,
'perclos_window': 60,
'alert_threshold': 0.45,
'critical_threshold': 0.70,
})

# 设置基线
detector.baseline_gaze_entropy = detector.compute_gaze_entropy(normal_gaze[:fps*30])
print(f"基线注视熵: {detector.baseline_gaze_entropy:.4f}")

# 评估正常驾驶
print("\n=== 正常驾驶评估 ===")
normal_score, normal_inds = detector.assess_impairment(
normal_gaze, normal_eye, normal_face, normal_steer, fps
)
print(f"综合损伤得分: {normal_score:.3f} (应 < 0.3)")
for ind in normal_inds:
print(f" {ind.name}: {ind.value:.3f} (conf={ind.confidence:.2f}, trend={ind.trend})")

# 评估损伤驾驶
print("\n=== 损伤驾驶评估 ===")
impaired_score, impaired_inds = detector.assess_impairment(
impaired_gaze, impaired_eye, impaired_face, impaired_steer, fps
)
print(f"综合损伤得分: {impaired_score:.3f} (应 > 0.45)")
for ind in impaired_inds:
print(f" {ind.name}: {ind.value:.3f} (conf={ind.confidence:.2f}, trend={ind.trend})")

# 判定
print("\n=== 判定结果 ===")
if impaired_score >= detector.impairment_critical_threshold:
print("⚠️ 严重损伤 — 触发紧急干预(靠边停车+紧急联系)")
elif impaired_score >= detector.impairment_alert_threshold:
print("⚠️ 中度损伤 — 触发一级警告(声音+触觉提醒)")
else:
print("✅ 功能状态正常")

3. Cause-Agnostic 方案的核心优势

优势 说明 传统BAC方案对比
多物质覆盖 一次检测覆盖酒精、药物、疲劳、疾病 每种物质需独立传感器
组合效应 自动捕捉多物质组合的非线性影响 无法检测组合效应
实时性 持续监控,秒级响应 仅在特定时刻检测
非物质因素 覆盖疲劳、情绪、疾病等非化学因素 完全无法覆盖
隐私保护 不需要生物样本 需要呼气/唾液/血液
成本 利用已有DMS摄像头,零额外硬件 需要专用化学传感器

实验结果

与传统 BAC 检测的对比

检测维度 BAC 0.08% 阈值 DMS Cause-Agnostic
检测物质 ✅ 乙醇 ❌ 不识别具体物质
功能损伤 ❌ 间接推断 ✅ 直接测量
多物质组合 ❌ 无法覆盖 ✅ 自动覆盖
疲劳损伤 ❌ 完全遗漏 ✅ 覆盖
实时性 ⚠️ 仅检测时刻 ✅ 持续监控
个体差异 ❌ 统一阈值 ✅ 基线个性化
隐私 ❌ 需生物样本 ✅ 无接触
部署成本 需额外传感器 利用已有DMS

技术论文系列路线图

论文 发布时间 核心论点
Part 1 2025年12月 BAC 是不充分的实时损伤检测 Ground Truth
Part 2 2026年4月 Intoxication ≠ Impairment,DMS 应聚焦功能状态
Part 3+ 待发布 预计深入具体检测算法和验证数据

IMS 开发启示

1. 架构建议

2. 在 IMS 中的集成路径

集成阶段 具体实现 优先级
Phase 1: 眼动模块 注视熵 + PERCLOS + 扫视异常 → 基础损伤评分 🔴 高
Phase 2: 面部模块 面部迟滞 + 微表情 → 增强检测精度 🟡 中
Phase 3: 行为融合 方向盘熵 + 车道保持 → 多模态融合 🟡 中
Phase 4: 干预系统 分级警告 + ADAS 协同 + 紧急联系 🔴 高

3. 部署参数建议

参数 推荐值 说明
摄像头帧率 ≥30 fps 保证扫视检测精度
眼动采样率 ≥60 Hz 扫视频率需要高采样
PERCLOS 窗口 60 秒 平衡响应速度和稳定性
损伤阈值-警告 0.45 综合得分
损伤阈值-严重 0.70 综合得分
基线建立时间 前 5 分钟 正常驾驶段建立个人基线
硬件平台 QCS8255 / SA8775 Hexagon NPU 加速

4. Euro NCAP 对接

Euro NCAP 2026 要求 Cause-Agnostic 方案覆盖
酒驾损伤检测 ✅ 直接覆盖(不需化学传感器)
疲劳检测 ✅ PERCLOS + 眼动熵
认知分心 ✅ 注视模式异常检测
无响应驾驶员干预 ✅ 严重损伤 → ADAS 协同

5. 竞品对比

方案 厂商 方法 优势 局限
Cause-Agnostic DMS Seeing Machines 视觉行为特征融合 多物质覆盖+非物质因素 需要精确基线建模
Real-Time Alcohol DMS Smart Eye 行为指标+驾驶数据 CES 2026 获奖 依赖真实驾驶数据训练
BAC + DMS 融合 部分OEM 呼气传感器+DMS 双重验证 额外硬件成本
纯化学检测 传统方案 呼气/血液 法定证据 无法实时+无法覆盖疲劳

结论

Seeing Machines Part 2 论文的根本贡献不在于某个新算法,而在于重新定义了座舱损伤检测的问题域:

  1. 从”What”到”Whether”:不问”摄入了什么物质”,而问”功能是否受损”
  2. 从静态到动态:从单次检测变为持续监控
  3. 从单一到通用:一套系统覆盖所有损伤类型(酒精、药物、疲劳、疾病、情绪)
  4. 从化学到视觉:无接触、无隐私侵犯、零额外硬件

对于 IMS 开发,这意味着酒驾检测不需要等待化学传感器成熟——利用已有 DMS 摄像头,通过行为特征融合就能实现 cause-agnostic 的功能损伤检测。关键挑战在于:

  • 建立可靠的个体基线模型
  • 多模态特征融合的权重优化
  • 误报率控制(<5%)
  • 跨人种/年龄段泛化

论文链接:https://seeingmachines.com/wp-content/uploads/2026/04/Technical-Paper-Intoxication-Part-2.pdf
Part 1 链接:https://seeingmachines.com/technical-paper-series-intoxication/