CCGF:驾驶员追踪丢失时的因果注视预测——arXiv 2609.12374解读

论文:Context-Aware Causal Gaze Forecasting for Human-Vehicle Interaction During In-Cabin Tracking Dropouts
作者:Shabnam Shabani 等
arXiv:2609.12374 (2026-09-11)
篇幅:8页, 5图

核心创新

本文解决DMS实际部署中的关键痛点——头部大旋转导致追踪丢失时如何恢复注视估计。提出CCGF(Causal Context-Gated Forecaster),在追踪丢失期间利用60帧历史+DINOv3场景特征预测注视方向,误差10.5°(比仅用历史降低33%)。

一句话总结: 当驾驶员转头看后视镜/肩膀检查时,摄像头丢失眼睛追踪——CCGF利用之前60帧注视历史和当前场景信息”预测”注视方向,无需未来数据。

问题定义

追踪丢失:DMS的盲区

场景 追踪丢失原因 发生频率 重要性
肩膀检查 头部大旋转 高 🔴 关键变道时刻
后视镜查看 头部偏转 中 🔴 换道准备
交叉路口扫描 头部大旋转 高 🔴 安全关键
阳光遮挡 眯眼/闭眼 中 🟡
手遮挡 手挡面部 低 🟡

核心矛盾: 追踪丢失恰好发生在注视信息最有价值的时候(变道/路口)。

因果预测 vs 非因果预测

1
2
3
4
5
非因果(离线):              因果(在线/实时):
过去 ── 丢失 ── 未来 过去 ── 丢失 ── ???
↑ ↑ ↑
用两侧数据填充 只能用过去数据预测
❌ DMS不可用 ✅ 本文方案

方法详解

CCGF架构

核心代码复现

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

class CCGF(nn.Module):
"""
Causal Context-Gated Forecaster (CCGF)

论文: arXiv:2609.12374
功能: 在追踪丢失期间因果预测驾驶员注视方向

输入:
- 60帧历史注视+头部姿态
- DINOv3场景特征(Live或Frozen模式)
输出:
- 预测注视坐标 (2D)

核心创新:
1. 可靠性门控:随丢失时间增长,动态调整历史vs场景权重
2. DINOv3场景特征:自监督场景理解
3. 因果预测:仅用过去数据,不依赖未来
"""

def __init__(self, gaze_dim=2, head_dim=6,
hist_feat_dim=256, scene_feat_dim=768,
num_heads=8, num_layers=3):
super().__init__()

# 1. 历史编码器:编码60帧历史
self.history_encoder = nn.LSTM(
input_size=gaze_dim + head_dim,
hidden_size=hist_feat_dim,
num_layers=2,
batch_first=True,
bidirectional=False # 因果:只能看过去
)

# 2. 场景特征投影(DINOv3输出768维)
self.scene_proj = nn.Sequential(
nn.Linear(scene_feat_dim, hist_feat_dim),
nn.GELU(),
nn.Linear(hist_feat_dim, hist_feat_dim)
)

# 3. 可靠性门控:动态融合历史和场景
self.reliability_gate = ReliabilityGate(
hist_dim=hist_feat_dim,
scene_dim=hist_feat_dim
)

# 4. 预测头
self.predictor = nn.Sequential(
nn.Linear(hist_feat_dim, hist_feat_dim),
nn.GELU(),
nn.Linear(hist_feat_dim, gaze_dim)
)

def forward(self, history_gaze_head, scene_feat, dropout_progress):
"""
Args:
history_gaze_head: (B, 60, gaze_dim+head_dim) 历史60帧
scene_feat: (B, scene_feat_dim) DINOv3场景特征
dropout_progress: (B,) 丢失进度 0-1 (0=刚丢失, 1=长时间丢失)

Returns:
pred_gaze: (B, gaze_dim) 预测注视坐标
gate_weights: (B, 2) 历史/场景权重
"""
# 1. 编码历史
_, hist_feat = self.history_encoder(history_gaze_head)
hist_feat = hist_feat[-1] # (B, hist_feat_dim)

# 2. 投影场景特征
scene_feat = self.scene_proj(scene_feat) # (B, hist_feat_dim)

# 3. 可靠性门控融合
fused_feat, gate_weights = self.reliability_gate(
hist_feat, scene_feat, dropout_progress
)

# 4. 预测注视
pred_gaze = self.predictor(fused_feat)

return pred_gaze, gate_weights


class ReliabilityGate(nn.Module):
"""
可靠性门控模块

核心思想:
- 丢失初期:历史信息可靠(短期记忆有效)
- 丢失后期:场景信息更可靠(长期记忆衰减)
"""

def __init__(self, hist_dim, scene_dim):
super().__init__()

# 历史可靠性衰减
self.hist_decay = nn.Sequential(
nn.Linear(1, 32),
nn.ReLU(),
nn.Linear(32, hist_dim),
nn.Sigmoid()
)

# 场景可靠性增长
self.scene_growth = nn.Sequential(
nn.Linear(1, 32),
nn.ReLU(),
nn.Linear(32, scene_dim),
nn.Sigmoid()
)

# 融合
self.fusion = nn.Sequential(
nn.Linear(hist_dim + scene_dim, hist_dim),
nn.GELU(),
nn.Linear(hist_dim, hist_dim)
)

def forward(self, hist_feat, scene_feat, dropout_progress):
"""
Args:
hist_feat: (B, hist_dim)
scene_feat: (B, scene_dim)
dropout_progress: (B,) 0-1

Returns:
fused: (B, hist_dim)
weights: (B, 2) [hist_weight, scene_weight]
"""
# 进度扩展到特征维度
progress = dropout_progress.unsqueeze(-1) # (B, 1)

# 历史权重:随时间衰减
hist_weight = self.hist_decay(progress) # (B, hist_dim)
hist_weighted = hist_feat * hist_weight

# 场景权重:随时间增长
scene_weight = self.scene_growth(progress) # (B, scene_dim)
scene_weighted = scene_feat * scene_weight

# 融合
fused = self.fusion(torch.cat([hist_weighted, scene_weighted], dim=-1))

# 记录平均权重
weights = torch.stack([
hist_weight.mean(dim=-1),
scene_weight.mean(dim=-1)
], dim=-1)

return fused, weights


# 测试
if __name__ == "__main__":
model = CCGF(gaze_dim=2, head_dim=6, hist_feat_dim=256, scene_feat_dim=768)

# 模拟输入
history = torch.randn(4, 60, 8) # 4样本, 60帧, 2注视+6头部
scene = torch.randn(4, 768) # DINOv3特征
progress = torch.rand(4) # 丢失进度

pred, gates = model(history, scene, progress)
print(f"History input: {history.shape}")
print(f"Scene feature: {scene.shape}")
print(f"Predicted gaze: {pred.shape}")
print(f"Gate weights [hist, scene]: {gates.shape}")
print(f"Parameters: {sum(p.numel() for p in model.parameters()):,}")

# 验证:随丢失时间增长,历史权重应下降,场景权重应上升
progress_long = torch.ones(4) # 长时间丢失
_, gates_long = model(history, scene, progress_long)
progress_short = torch.zeros(4) # 刚丢失
_, gates_short = model(history, scene, progress_short)
print(f"\n刚丢失 - 历史权重: {gates_short[:, 0].mean():.3f}")
print(f"长时间 - 历史权重: {gates_long[:, 0].mean():.3f}")
print("✅ 历史权重应随时间下降")

实验结果

数据集

属性 数值
数据来源 GazeSense自然驾驶数据
驾驶时长 10.5小时
驾驶员数 10人
追踪丢失事件 2,047个
丢失时间占比 8.5%
评估标注 Neon头戴式追踪器(仅用于评估,不作为输入)
评估方式 Leave-one-driver-out

核心结果

方法 场景模式 中位误差(px) 中位误差(°) 相对改善
仅历史(基线) - 262.8 15.7 -
CCGF Live(实时场景更新) 175.7 10.5 33%↓
CCGF Frozen(冻结场景) 210.8 12.9 20%↓

关键发现

  1. Live场景更新优于冻结:实时更新的场景特征比冻结的更有价值(10.5° vs 12.9°)
  2. 33%误差降低:相对仅历史预测,场景信息显著提升
  3. 8.5%丢失时间:实际驾驶中追踪丢失占8.5%——不可忽视
  4. 数据集和基线将公开:可复现和后续研究

IMS 应用启示

1. 直接解决DMS追踪丢失痛点

Euro NCAP场景 追踪丢失风险 CCGF价值
变道(肩膀检查) 🔴 高 ✅ 恢复注视估计
路口(左右扫描) 🔴 高 ✅ 恢复注视估计
后视镜查看 🟡 中 ✅ 恢复注视估计
正常驾驶 🟢 低 维持追踪

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
# DMS追踪丢失恢复管道

class DMSWithRecovery:
"""
集成CCGF的完整DMS管道

追踪正常 → 标准注视估计
追踪丢失 → CCGF因果预测
"""

def __init__(self):
self.gaze_tracker = "标准注视追踪器"
self.ccgf = CCGF()
self.history_buffer = [] # 60帧环形缓冲
self.scene_encoder = "DINOv3" # 场景特征提取

def process_frame(self, camera_frame):
# 1. 标准追踪
gaze, confidence = self.gaze_tracker(camera_frame)

if confidence > 0.5:
# 追踪正常
self.history_buffer.append(gaze)
return gaze, "normal"
else:
# 追踪丢失 → CCGF预测
if len(self.history_buffer) >= 60:
history = self._get_history_tensor()
scene_feat = self.scene_encoder(camera_frame)
dropout_progress = self._calc_progress()

pred_gaze, gates = self.ccgf(
history, scene_feat, dropout_progress
)

return pred_gaze, "predicted"
else:
return None, "lost"

3. 与IMS现有模块集成

IMS模块 CCGF集成点 价值
分心检测 追踪丢失期间不漏检 减少8.5%漏检
疲劳检测 微睡眠期间追踪可能丢失 恢复闭眼注视
视线落点 头部大旋转时维持 换道场景覆盖
Euro NCAP合规 换道场景DMS连续性 评估加分

4. 关键限制

限制 影响 缓解
10.5°误差仍较大 不足以精确注视物体 用区域分类代替精确点
依赖DINOv3 增加计算负担 用轻量场景编码器
仅验证于GazeSense 跨数据集泛化未验证 多数据集评估
8.5%丢失时间 91.5%时间不需要 但这8.5%是最关键的时刻

论文下载


本文为论文解读类博客,包含方法详解、代码复现、性能对比、IMS落地指导。