差分视线估计:长时窄范围场景的DMS校准新方案

论文信息

项目 内容
标题 Adapting Appearance-Based Gaze Estimation to Narrow-Range, Long-Duration Screen Viewing
arXiv 2610.11036
时间 2026年10月8日
作者 Jordan Prescott 等
领域 eess.IV (Image and Video Processing)
链接 https://arxiv.org/abs/2610.11036

核心创新

提出差分视线估计(Differential Gaze Estimation)方法,专门针对长时间、窄范围场景(如驾驶员注视前方道路)的视线追踪问题。在140段长时面部视频+同步眼动仪数据上,差分方法是唯一显著优于”预测每段平均视线”基线的静态方法。

一句话总结: 长途驾驶中驾驶员大部分时间看前方,传统视线估计模型校准会漂移——差分模型只追踪”偏离中心多少”而非”看向哪里”,更稳定。

为什么传统视线估计在DMS中有问题

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
# 传统视线估计 vs 差分视线估计
paradigm_comparison = {
"传统方法": {
"目标": "预测绝对视线方向 (yaw, pitch)",
"范围": "设计为大范围 (±40°)",
"问题1": "长途驾驶中90%时间看前方±5°——大范围模型在窄范围精度差",
"问题2": "长时间校准漂移——头部微动+摄像头微移导致误差累积",
"问题3": "低角度误差≠好的眼动重建——fixation/saccade可能失真"
},
"差分方法": {
"目标": "预测相对个人基线的偏移 (Δyaw, Δpitch)",
"范围": "专门窄范围 (±10°)",
"优势1": "自动消除个人偏置(基线中心化)",
"优势2": "对校准漂移鲁棒(漂移是低频的,差分消除低频)",
"优势3": "与时序模型结合提升fixation/saccade一致性"
}
}

方法详解

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
import numpy as np
import torch
import torch.nn as nn

class DifferentialGazeModel(nn.Module):
"""
差分视线估计模型

核心思想:
不预测绝对视线方向 θ = (yaw, pitch)
而预测相对个人基线的偏移 Δθ = θ - θ_baseline

θ_baseline = 该段视频前N帧的视线平均值

优势:
1. 消除个人偏置(每人习惯性视线方向不同)
2. 消除校准漂移(低频误差被差分消除)
3. 窄范围内精度更高
"""

def __init__(self, backbone: str = "resnet18",
baseline_frames: int = 30):
super().__init__()
self.backbone = self._build_backbone(backbone)
self.regressor = nn.Sequential(
nn.Linear(512, 256),
nn.GELU(),
nn.Dropout(0.1),
nn.Linear(256, 2) # Δyaw, Δpitch
)
self.baseline_frames = baseline_frames

def _build_backbone(self, name: str) -> nn.Module:
if name == "resnet18":
import torchvision.models as models
model = models.resnet18(weights='DEFAULT')
model.fc = nn.Identity()
return model
return nn.Identity()

def forward(self, face_images: torch.Tensor,
baseline_images: torch.Tensor = None) -> torch.Tensor:
"""
Args:
face_images: (B, T, C, H, W) 面部图像序列
baseline_images: (B, N, C, H, W) 基线帧(前N帧)

Returns:
delta_gaze: (B, T, 2) 相对基线的视线偏移
"""
B, T, C, H, W = face_images.shape

# 编码当前帧
x = face_images.view(B * T, C, H, W)
feat = self.backbone(x) # (B*T, 512)
feat = feat.view(B, T, -1)

# 编码基线帧并取平均
if baseline_images is not None:
N = baseline_images.size(1)
bl = baseline_images.view(B * N, C, H, W)
bl_feat = self.backbone(bl).view(B, N, -1)
bl_feat = bl_feat.mean(dim=1, keepdim=True) # (B, 1, 512)

# 差分特征
feat_diff = feat - bl_feat # (B, T, 512)
else:
feat_diff = feat

# 回归差分视线
delta_gaze = self.regressor(feat_diff) # (B, T, 2)
return delta_gaze

def predict_absolute(self, face_images: torch.Tensor,
baseline_gaze: torch.Tensor,
baseline_images: torch.Tensor = None) -> torch.Tensor:
"""
预测绝对视线 = 基线视线 + 差分视线

baseline_gaze: (B, 2) 已知基线视线方向
"""
delta = self.forward(face_images, baseline_images)
absolute = delta + baseline_gaze.unsqueeze(1)
return absolute


# 时序增强版
class TemporalDifferentialGaze(nn.Module):
"""
加入时序上下文的差分视线估计

论文发现:差分+时序模型 = 最强fixation/saccade一致性
"""

def __init__(self, backbone: str = "resnet18",
d_model: int = 256,
n_temporal_layers: int = 2):
super().__init__()
self.spatial_encoder = DifferentialGazeModel(backbone)

# 时序Transformer
encoder_layer = nn.TransformerEncoderLayer(
d_model=2, # 差分视线2维
nhead=2,
dim_feedforward=64,
dropout=0.1,
batch_first=True
)
self.temporal = nn.TransformerEncoder(encoder_layer, n_temporal_layers)

def forward(self, face_images: torch.Tensor,
baseline_images: torch.Tensor = None) -> torch.Tensor:
# 空间编码
delta = self.spatial_encoder(face_images, baseline_images)
# 时序平滑
delta_smooth = self.temporal(delta)
return delta_smooth


# 测试
if __name__ == "__main__":
model = DifferentialGazeModel()

# 模拟30秒驾驶视频 (30fps)
B, T, C, H, W = 2, 900, 3, 224, 224
face_seq = torch.randn(B, T, C, H, W)
baseline = torch.randn(B, 30, C, H, W) # 前30帧

delta_gaze = model(face_seq, baseline)
print(f"输入: {face_seq.shape}")
print(f"差分视线: {delta_gaze.shape}")
print(f"数值范围: yaw=[{delta_gaze[0,:,0].min():.3f}, {delta_gaze[0,:,0].max():.3f}]")
print(f" pitch=[{delta_gaze[0,:,1].min():.3f}, {delta_gaze[0,:,1].max():.3f}]")

# 绝对视线 = 基线 + 差分
baseline_gaze = torch.tensor([[0.0, -0.1], [0.05, -0.08]]) # 弧度
abs_gaze = model.predict_absolute(face_seq, baseline_gaze, baseline)
print(f"\n绝对视线: {abs_gaze.shape}")
print(f"→ 驾驶员1基线: (0.0, -0.1) rad = (0°, -5.7°) [略向下看仪表]")

2. 实验结果

方法 角度误差(°) 优于基线? fixation一致性 saccade一致性
基线(每段均值) 3.82 N/A 弱 弱
6种传统估计器 3.5-5.2 大多不显著 中 中
差分(静态) 3.1 ✅ 显著 中 中
差分+时序 2.8 ✅ 显著 强 强

3. 关键发现

1
2
3
4
5
6
7
8
9
10
11
12
13
14
# 论文最重要的发现
key_findings = {
"发现1": "低角度误差≠好的眼动重建",
"解释1": "传统指标只看每帧角度误差,但fixation/saccade一致性更重要",
"含义1": "DMS评估需要新增fixation/saccade一致性指标",

"发现2": "差分方法消除校准漂移",
"解释2": "漂移是低频信号,差分操作天然高通滤波",
"含义2": "长途驾驶无需频繁重新校准",

"发现3": "时序上下文增强一致性",
"解释3": "单帧估计有抖动,时序模型平滑fixation",
"含义3": "DMS视线追踪应用时序模型是必要的"
}

IMS开发启示

1. DMS校准策略改进

2. 与Euro NCAP分心检测的对应

Euro NCAP场景 差分方法优势 说明
D-02 手机使用 ✅ 视线偏移>15°易检测 差分在±15°内精度最高
D-05 视线偏离>3s ✅ fixation一致性高 时序模型准确判断持续偏移
D-08 闭眼>1.5s ❌ 不适用 需眼睑检测,非视线
正常驾驶 ✅ 基线消除误报 不再因个人习惯性视线偏移误报

3. 部署建议

优先级 建议 难度
🔴 P0 DMS加入个人基线建立流程 低
🔴 P0 视线输出改为差分模式 中
🟡 P1 加入时序Transformer 中
🟡 P1 评估新增fixation一致性指标 中
🟢 P2 动态基线更新(基于fixation) 高

测试场景

DG-01 长途驾驶校准稳定性测试

前置条件:

  • DMS红外摄像头正常
  • 驾驶员正常坐姿
  • 基线帧:前30帧(1秒@30fps)

测试步骤:

  1. 驾驶员正常驾驶10分钟,每2分钟记录视线估计误差
  2. 驾驶员10分钟内微移头部(模拟自然驾驶)
  3. 对比传统绝对估计 vs 差分估计

判定条件:

时间 传统误差 差分误差 要求
0min 2.5° 2.5° 相当
5min 3.5° 2.7° 差分<传统
10min 4.5° 2.8° 差分显著优

结论

差分视线估计方法直击DMS在长途驾驶中的痛点:校准漂移。核心启示:

  1. 窄范围优化 — 驾驶场景90%时间看前方±5°,专用窄范围模型优于通用大范围模型
  2. 差分消除漂移 — 个人基线中心化+低频漂移消除,双保险
  3. 时序必要 — 单帧差分已有改善,加入时序后fixation/saccade一致性最强
  4. 评估指标需更新 — 角度误差不够,需要fixation/saccade一致性

论文来源:arXiv:2610.11036 (2026-10-08)