CDATW论文解读:置信度驱动的自适应时间窗口疲劳检测,误报率降低35%

CDATW论文解读:置信度驱动的自适应时间窗口疲劳检测,误报率降低35%

论文: Confidence-driven adaptive time window for real-time driver fatigue detection in Level 2-3 autonomous vehicles: a multi-dataset validation study
期刊: Frontiers in Neurorobotics, 2026
链接: https://www.frontiersin.org/articles/10.3389/fnbot.2026.1857548/full


核心突破

指标 CDATW 固定窗口基准 提升
准确率 88.6-91.8% 85-90% +3-5%
误报率降低 35.2% - 显著
实时性 38-45 FPS 30-35 FPS +27%
ECE校准误差 0.078 0.15+ 更准确
高置信度准确率 95.6% - >0.9置信度时

问题背景

L2-L3自动驾驶的疲劳检测挑战

graph TD
    A[L2-L3自动驾驶] --> B[驾驶员角色转变]
    B --> C[监控任务为主]
    C --> D[认知负荷降低]
    D --> E[疲劳风险增加]
    
    F[现有DMS问题] --> G[固定时间窗口<br/>无法适应个体差异]
    F --> H[二元分类<br/>无置信度输出]
    F --> I[误报率高<br/>用户疲劳感]

固定窗口的缺陷

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
"""
固定时间窗口疲劳检测的问题

传统方法:
- PERCLOS使用固定60秒窗口
- 无法适应疲劳发展速度的个体差异
- 高置信度时延迟警告,低置信度时频繁误报
"""

# 固定窗口示例(传统方法)
class FixedWindowFatigue:
"""固定时间窗口疲劳检测(传统方法)"""

def __init__(self, window_sec=60):
self.window_sec = window_sec
self.eye_states = [] # 眼睛状态历史

def update(self, eye_openness: float, timestamp: float):
"""更新状态"""
self.eye_states.append({
'openness': eye_openness,
'timestamp': timestamp
})

# 移除超期数据
cutoff = timestamp - self.window_sec
self.eye_states = [s for s in self.eye_states if s['timestamp'] > cutoff]

def get_perclos(self) -> float:
"""计算PERCLOS"""
if len(self.eye_states) == 0:
return 0.0

# 闭眼阈值
threshold = 0.2

# PERCLOS = 闭眼帧数 / 总帧数
closed = sum(1 for s in self.eye_states if s['openness'] < threshold)
perclos = closed / len(self.eye_states) * 100

return perclos

def detect(self) -> dict:
"""检测疲劳"""
perclos = self.get_perclos()

# 固定阈值(无置信度)
is_fatigue = perclos > 30.0 # PERCLOS > 30%

return {
'is_fatigue': is_fatigue,
'perclos': perclos,
'confidence': None # 无置信度输出
}


# 问题演示
"""
问题1:高置信度时延迟警告
- 疲劳发展快,但窗口太长(60秒)
- 等到PERCLOS超过阈值时已经危险

问题2:低置信度时频繁误报
- 短暂眨眼被误判为疲劳
- 用户收到大量无效警告

问题3:无法适应个体差异
- 不同人疲劳发展速度不同
- 固定窗口无法自适应
"""

CDATW核心创新

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
import numpy as np
from typing import List, Dict, Tuple

class AdaptiveTimeWindow:
"""
CDATW自适应时间窗口

原理:
- 高置信度时缩短窗口(5-10秒),快速警告
- 低置信度时延长窗口(20-30秒),减少误报
- 中等置信度时使用中等窗口(15秒)
"""

def __init__(self):
# 窗口范围
self.min_window = 5.0 # 最短5秒
self.max_window = 30.0 # 最长30秒

# 置信度阈值
self.high_confidence = 0.85
self.low_confidence = 0.60

# 当前窗口
self.current_window = 15.0 # 初始15秒

def adjust_window(self, confidence: float, stability: float = 1.0) -> float:
"""
调整时间窗口

Args:
confidence: 模型输出置信度(0-1)
stability: 特征稳定性(0-1)

Returns:
window_sec: 调整后的窗口长度(秒)
"""
if confidence > self.high_confidence:
# 高置信度:缩短窗口
# 快速警告,避免延迟
target_window = self.min_window

elif confidence < self.low_confidence:
# 低置信度:延长窗口
# 减少误报,等待更多证据
target_window = self.max_window

else:
# 中等置信度:线性插值
ratio = (confidence - self.low_confidence) / \
(self.high_confidence - self.low_confidence)
target_window = self.max_window - ratio * (self.max_window - self.min_window)

# 考虑特征稳定性
# 稳定性低时延长窗口
target_window = target_window / stability

# 平滑过渡(避免窗口突变)
self.current_window = 0.7 * self.current_window + 0.3 * target_window

# 限制范围
self.current_window = np.clip(
self.current_window,
self.min_window,
self.max_window
)

return self.current_window

def get_window(self) -> float:
"""获取当前窗口长度"""
return self.current_window

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
import torch
import torch.nn as nn
import torch.nn.functional as F

class UncertaintyEstimator:
"""
蒙特卡洛Dropout不确定性估计

原理:
- 在推理时保持Dropout激活
- 多次前向传播获得预测分布
- 计算均值(预测)和方差(不确定性)
"""

def __init__(self, model: nn.Module, num_samples: int = 20):
self.model = model
self.num_samples = num_samples

def estimate_uncertainty(self, x: torch.Tensor) -> Tuple[torch.Tensor, torch.Tensor]:
"""
估计不确定性

Args:
x: 输入特征,shape=(B, C, T) 或 (B, C, H, W)

Returns:
mean_pred: 预测均值
uncertainty: 不确定性(方差)
"""
self.model.train() # 保持Dropout激活

predictions = []

with torch.no_grad():
for _ in range(self.num_samples):
pred = self.model(x) # (B, num_classes) 或 (B, 1)
predictions.append(pred)

# 堆叠预测
predictions = torch.stack(predictions, dim=0) # (num_samples, B, ...)

# 计算均值和方差
mean_pred = predictions.mean(dim=0)
variance = predictions.var(dim=0)

# 转换为置信度
# 方差小 → 置信度高
# 方差大 → 置信度低
confidence = 1.0 / (1.0 + variance)

return mean_pred, confidence

def get_epistemic_uncertainty(self, predictions: torch.Tensor) -> float:
"""
计算认知不确定性(Epistemic Uncertainty)

与数据不确定性(Aleatoric)不同,
认知不确定性来源于模型对数据的无知
"""
# 预测熵
if predictions.dim() == 2 and predictions.shape[1] > 1:
# 分类任务
prob = F.softmax(predictions, dim=1)
entropy = -torch.sum(prob * torch.log(prob + 1e-10), dim=1)
else:
# 回归任务
entropy = predictions.var(dim=0)

return entropy.mean().item()

3. MobileNetV3-CBAM-BiLSTM架构

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
class CDATWModel(nn.Module):
"""
CDATW疲劳检测模型

架构:
1. MobileNetV3 + CBAM 空间特征提取
2. BiLSTM 时序建模
3. Monte Carlo Dropout 不确定性估计
4. 自适应窗口控制器
"""

def __init__(self, config: dict):
super().__init__()

# 1. 空间特征提取器(MobileNetV3 + CBAM)
self.backbone = MobileNetV3Encoder(
width_mult=0.75,
output_dim=128
)

# CBAM注意力模块
self.cbam = CBAM(
channels=128,
reduction_ratio=16,
kernel_size=7
)

# 2. 时序建模器(BiLSTM)
self.temporal_encoder = nn.LSTM(
input_size=128,
hidden_size=64,
num_layers=2,
batch_first=True,
bidirectional=True,
dropout=0.2
)

# 3. 疲劳预测头
self.fatigue_head = nn.Sequential(
nn.Linear(128, 64), # BiLSTM双向输出
nn.ReLU(),
nn.Dropout(0.3),
nn.Linear(64, 1),
nn.Sigmoid()
)

# 4. Monte Carlo Dropout
self.mc_dropout = nn.Dropout(0.2)

# 5. 自适应窗口控制器
self.window_controller = AdaptiveTimeWindow()

def forward(self, x: torch.Tensor, return_uncertainty: bool = False):
"""
前向传播

Args:
x: 输入视频片段,shape=(B, T, C, H, W)
return_uncertainty: 是否返回不确定性

Returns:
output: {
'fatigue_prob': 疲劳概率,
'confidence': 置信度,
'window_sec': 建议窗口长度
}
"""
B, T, C, H, W = x.shape

# 1. 空间特征提取
x_flat = x.view(B * T, C, H, W)
spatial_features = self.backbone(x_flat) # (B*T, 128)
spatial_features = self.cbam(spatial_features)
spatial_features = spatial_features.view(B, T, -1) # (B, T, 128)

# 2. 时序建模
temporal_features, _ = self.temporal_encoder(spatial_features)

# 使用最后时间步
last_hidden = temporal_features[:, -1, :] # (B, 128)

# 3. 疲劳预测
fatigue_prob = self.fatigue_head(last_hidden) # (B, 1)

# 4. 不确定性估计(可选)
if return_uncertainty:
# Monte Carlo Dropout
last_hidden_drop = self.mc_dropout(last_hidden)
fatigue_prob_drop = self.fatigue_head(last_hidden_drop)

# 简化的置信度(基于预测值与0.5的距离)
confidence = 1.0 - 2.0 * torch.abs(fatigue_prob_drop - 0.5)
confidence = confidence.squeeze(-1)
else:
confidence = torch.ones(B, device=x.device)

# 5. 计算窗口长度
window_sec = self.window_controller.adjust_window(
confidence.mean().item()
)

return {
'fatigue_prob': fatigue_prob.squeeze(-1),
'confidence': confidence,
'window_sec': window_sec
}


class CBAM(nn.Module):
"""
Convolutional Block Attention Module

包含:
- 通道注意力(Channel Attention)
- 空间注意力(Spatial Attention)
"""

def __init__(self, channels: int, reduction_ratio: int = 16, kernel_size: int = 7):
super().__init__()

# 通道注意力
self.channel_attention = nn.Sequential(
nn.AdaptiveAvgPool2d(1),
nn.Conv2d(channels, channels // reduction_ratio, 1),
nn.ReLU(),
nn.Conv2d(channels // reduction_ratio, channels, 1),
nn.Sigmoid()
)

# 空间注意力
self.spatial_attention = nn.Sequential(
nn.Conv2d(2, 1, kernel_size, padding=kernel_size // 2),
nn.Sigmoid()
)

def forward(self, x: torch.Tensor) -> torch.Tensor:
# 通道注意力
ca = self.channel_attention(x)
x = x * ca

# 空间注意力
avg_out = torch.mean(x, dim=1, keepdim=True)
max_out = torch.max(x, dim=1, keepdim=True)[0]
sa_input = torch.cat([avg_out, max_out], dim=1)
sa = self.spatial_attention(sa_input)
x = x * sa

return x

实验验证

多数据集验证

数据集 准确率 AUC 特点
NTHU-DDD 91.8% 0.95 实验室场景
YawDD 89.5% 0.93 打哈欠检测
UTA-RLDD 88.6% 0.92 真实驾驶
DROZY 90.3% 0.94 瞌睡检测

误报率对比

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
"""
CDATW vs 固定窗口误报率对比
"""

COMPARISON = {
"CDATW自适应": {
"false_alarm_rate": 8.2,
"detection_delay_sec": 7.5,
"window_adaptation": "动态5-30秒"
},

"固定15秒窗口": {
"false_alarm_rate": 12.7,
"detection_delay_sec": 15.0,
"window_adaptation": "固定15秒"
},

"固定60秒窗口": {
"false_alarm_rate": 9.1,
"detection_delay_sec": 60.0,
"window_adaptation": "固定60秒"
}
}

# 误报率降低
reduction = (12.7 - 8.2) / 12.7 * 100
print(f"误报率降低: {reduction:.1f}%") # 35.2%

边缘部署性能

平台 帧率 功耗 延迟
Jetson Xavier NX 38-45 FPS 10W <30ms
Jetson Nano 18-22 FPS 5W <60ms

对IMS开发的启示

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
"""
Euro NCAP要求DMS输出置信度

CDATW的价值:
- 提供疲劳概率 + 置信度
- 高置信度时快速警告
- 低置信度时避免误报
"""

class IMS_FatigueDetector:
"""IMS疲劳检测器(集成CDATW)"""

def __init__(self):
self.model = CDATWModel({})
self.window_controller = AdaptiveTimeWindow()

def detect(self, video_clip: np.ndarray) -> dict:
"""
检测疲劳

Args:
video_clip: 视频片段,shape=(T, H, W, C)

Returns:
result: {
'fatigue_level': 'normal' | 'mild' | 'severe',
'fatigue_prob': float,
'confidence': float,
'window_sec': float,
'action': 'none' | 'warn' | 'alert'
}
"""
# 预处理
x = self._preprocess(video_clip)

# 推理
with torch.no_grad():
output = self.model(x, return_uncertainty=True)

fatigue_prob = output['fatigue_prob'].item()
confidence = output['confidence'].item()
window_sec = output['window_sec']

# 疲劳等级
if fatigue_prob < 0.3:
fatigue_level = 'normal'
action = 'none'
elif fatigue_prob < 0.7:
fatigue_level = 'mild'
action = 'warn' if confidence > 0.7 else 'none'
else:
fatigue_level = 'severe'
action = 'alert' if confidence > 0.85 else 'warn'

return {
'fatigue_level': fatigue_level,
'fatigue_prob': fatigue_prob,
'confidence': confidence,
'window_sec': window_sec,
'action': action
}

2. L2-L3接管场景

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
"""
L2-L3自动驾驶接管场景的疲劳检测策略

CDATW优势:
- 高置信度时快速警告(5-10秒窗口)
- 为接管预留足够时间
- 减少误报避免用户疲劳
"""

# 接管场景配置
TAKEOVER_CONFIG = {
"高置信度检测": {
"置信度阈值": 0.85,
"窗口长度": "5-10秒",
"接管预留时间": "≥10秒",
"Euro NCAP L3要求": "10秒接管窗口"
},

"低置信度检测": {
"置信度阈值": "<0.60",
"窗口长度": "20-30秒",
"策略": "等待更多证据,避免误报"
}
}

3. 多模态融合扩展

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
"""
CDATW可扩展到多模态融合

融合方案:
- 视觉:眼动、面部表情
- 方向盘:操控熵
- 座椅:压力分布
"""

class MultimodalCDATW(nn.Module):
"""多模态CDATW扩展"""

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

# 视觉特征
self.visual_encoder = MobileNetV3Encoder()

# 方向盘特征
self.steering_encoder = nn.LSTM(2, 32, batch_first=True) # (角度, 角速度)

# 座椅压力特征
self.pressure_encoder = nn.Linear(16, 32) # 16个压力传感器

# 多模态融合
self.fusion = nn.Linear(128 + 64 + 32, 128)

# 不确定性估计
self.uncertainty_head = nn.Linear(128, 1)

def forward(self, visual, steering, pressure):
# 各模态编码
v_feat = self.visual_encoder(visual)
s_feat, _ = self.steering_encoder(steering)
p_feat = self.pressure_encoder(pressure)

# 拼接
combined = torch.cat([
v_feat,
s_feat[:, -1, :],
p_feat
], dim=-1)

# 融合
fused = self.fusion(combined)

# 不确定性
uncertainty = self.uncertainty_head(fused)

return {
'features': fused,
'uncertainty': uncertainty
}

总结

CDATW核心价值

  1. 误报率降低35%:自适应窗口减少无效警告
  2. 置信度输出:符合Euro NCAP和用户预期
  3. 实时部署:38-45 FPS,Jetson Xavier NX
  4. 跨数据集泛化:四数据集验证,88.6-91.8%准确率

IMS应用建议

应用场景 CDATW优势
L2-L3接管检测 高置信度快速警告,预留10秒接管窗口
Euro NCAP合规 提供置信度输出,符合DMS要求
边缘部署 38 FPS实时性能,功耗<10W
多模态融合 框架可扩展至方向盘+座椅压力

参考资料

  1. 论文原文https://www.frontiersin.org/articles/10.3389/fnbot.2026.1857548/full
  2. NTHU-DDD数据集:疲劳检测标准数据集
  3. MobileNetV3论文:Howard et al., 2019
  4. CBAM论文:Woo et al., 2018

相关文章:


CDATW论文解读:置信度驱动的自适应时间窗口疲劳检测,误报率降低35%
https://dapalm.com/2026/07/15/2026-07-15-cdatw-confidence-driven-adaptive-time-window-fatigue-detection/
作者
Mars
发布于
2026年7月15日
许可协议