GazeAnywhere:CVPR 2026 可提示视线目标估计——自然语言驱动的端到端DMS视线分析

论文信息

  • 标题: Gaze Target Estimation Anywhere with Concepts
  • 会议: CVPR 2026
  • 作者: Houze Yang, Vipin Gunda 等 (UIUC + Google)
  • 链接: https://arxiv.org/abs/2608.11367
  • 代码: https://github.com/IrohXu/GazeAnywhere
  • 数据集: Gaze-Co,120K 可提示标注图像对
  • 核心方法: 冻结DINOv3视觉编码器 + 冻结文本编码器 + Transformer检测器,端到端视线目标估计

核心创新

首次提出可提示视线目标估计(PGE)任务: 用自然语言提示(如”穿红衣服的男孩”)指定目标人物,端到端预测其视线落点。消除了传统多阶段流水线对头部边界框、姿态关键点等中间输入的依赖。

关键突破:

  • 传统方法:人脸检测→头部边界框→视线方向→落点(级联误差)
  • GazeAnywhere:文本提示→端到端→视线热力图(无中间依赖)
  • 支持文本提示 + 视觉坐标提示两种模式
  • 在真实临床自闭症儿童数据集上验证泛化能力

方法详解

1. 架构总览

2. PGE任务定义

输入: RGB图像 I ∈ ℝ^(3×H×W) + 提示 P(文本T或视觉坐标)

输出: 视线热力图 Ĥ ∈ ℝ^(Hout×Wout),每个元素 Ĥ(i,j) 表示被指定主体注视位置 (i,j) 的概率

提示类型:

类型 示例 说明
外观 “穿红衣服的男孩” 身份+修饰词
位置 “左侧的人” 空间位置
姿态 “坐着的人” 静态姿态
动作 “看书的人” 动词短语

3. GazeAnywhere模型架构

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
import torch
import torch.nn as nn
from typing import Tuple

class GazeAnywhere(nn.Module):
"""
GazeAnywhere: 可提示视线目标估计模型

论文: CVPR 2026
架构: 冻结DINOv3 + 冻结文本编码器 + Transformer检测器

核心创新:
1. 自然语言提示指定目标人物
2. 端到端,无中间检测阶段
3. 同时解决定位+在帧判断+视线估计
"""

def __init__(self,
dino_model_name='dinov3_vitl14',
text_embed_dim=768,
hidden_dim=256,
num_queries=100,
num_decoder_layers=6):
super().__init__()

# 冻结视觉编码器 (DINOv3)
self.image_encoder = self._load_frozen_dino(dino_model_name)
D_V = self.image_encoder.embed_dim # 视觉特征维度

# 冻结文本编码器
self.text_encoder = self._load_frozen_text_encoder()
D_T = text_embed_dim

# 投影到统一空间
self.image_proj = nn.Linear(D_V, hidden_dim)
self.text_proj = nn.Linear(D_T, hidden_dim)

# Transformer检测器(可训练)
decoder_layer = nn.TransformerDecoderLayer(
d_model=hidden_dim,
nhead=8,
dim_feedforward=hidden_dim * 4,
dropout=0.1,
batch_first=True
)
self.transformer_decoder = nn.TransformerDecoder(
decoder_layer,
num_layers=num_decoder_layers
)

# 查询嵌入
self.queries = nn.Embedding(num_queries, hidden_dim)

# 预测头
self.bbox_head = MLP(hidden_dim, hidden_dim, 4, 3) # 头部边界框
self.presence_head = nn.Linear(hidden_dim, 1) # 在/不在画面
self.gaze_head = MLP(hidden_dim, hidden_dim, 2, 3) # 视线落点(x,y)
self.gaze_heatmap_head = nn.Linear(hidden_dim, 1) # 热力图

def _load_frozen_dino(self, name):
"""加载冻结的DINOv3模型"""
# 实际使用 torchvision 或 hub 加载
model = torch.hub.load('facebookresearch/dinov3', name)
for param in model.parameters():
param.requires_grad = False
return model

def _load_frozen_text_encoder(self):
"""加载冻结的文本编码器"""
# 使用 dino.txt 或 CLIP 文本编码器
model = torch.hub.load('facebookresearch/dinov3', 'dinotxt_base')
for param in model.parameters():
param.requires_grad = False
return model

def forward(self, image: torch.Tensor,
text_prompt: str = None,
visual_prompt: Tuple[float, float] = None) -> dict:
"""
前向传播

Args:
image: (B, 3, H, W) 输入图像
text_prompt: 文本提示字符串
visual_prompt: (x, y) 归一化坐标提示

Returns:
dict: {
'bbox': (B, 4) 头部边界框,
'presence': (B, 1) 在画面内的概率,
'gaze_point': (B, 2) 视线落点,
'gaze_heatmap': (B, H//14, W//14) 视线热力图
}
"""
B = image.shape[0]

# 1. 提取冻结视觉特征
with torch.no_grad():
visual_features = self.image_encoder(image)
# DINOv3输出: [CLS] + patch tokens
# visual_features: (B, 1+N_V, D_V)

visual_features = self.image_proj(visual_features)

# 2. 提取文本特征
if text_prompt is not None:
with torch.no_grad():
text_features = self.text_encoder(text_prompt)
text_features = self.text_proj(text_features)
# (B, D_T) -> (B, 1, hidden_dim)
text_features = text_features.unsqueeze(1)
elif visual_prompt is not None:
# 将坐标提示映射到embedding
coord_embed = self._coord_to_embed(visual_prompt, visual_features, image)
text_features = coord_embed # (B, 1, hidden_dim)

# 3. Transformer解码
queries = self.queries.weight.unsqueeze(0).expand(B, -1, -1)

# 将文本特征作为key,视觉特征+文本作为memory
memory = torch.cat([visual_features, text_features], dim=1)

decoded = self.transformer_decoder(queries, memory)
# decoded: (B, num_queries, hidden_dim)

# 取第一个query的输出作为主体特征
subject_feat = decoded[:, 0, :] # (B, hidden_dim)

# 4. 预测
bbox = self.bbox_head(subject_feat).sigmoid() # 归一化坐标
presence = self.presence_head(subject_feat).sigmoid()
gaze_point = self.gaze_head(subject_feat).sigmoid()

# 热力图(简化版,实际用所有query的attention)
heatmap_logits = self.gaze_heatmap_head(decoded) # (B, num_queries, 1)
gaze_heatmap = heatmap_logits.sigmoid()

return {
'bbox': bbox,
'presence': presence,
'gaze_point': gaze_point,
'gaze_heatmap': gaze_heatmap
}

def _coord_to_embed(self, coord, visual_features, image):
"""将坐标提示转换为embedding(通过位置编码)"""
B, N, D = visual_features.shape
H_patches = image.shape[2] // 14
W_patches = image.shape[3] // 14

x_idx = int(coord[0] * W_patches)
y_idx = int(coord[1] * H_patches)
token_idx = y_idx * W_patches + x_idx + 1 # +1 for CLS

coord_embed = visual_features[:, token_idx:token_idx+1, :]
return coord_embed


class MLP(nn.Module):
"""多层感知机"""
def __init__(self, input_dim, hidden_dim, output_dim, num_layers):
super().__init__()
h = [hidden_dim] * (num_layers - 1)
self.layers = nn.ModuleList(
nn.Linear(n, k) for n, k in zip([input_dim] + h, h + [output_dim])
)

def forward(self, x):
for i, layer in enumerate(self.layers):
x = torch.relu(layer(x)) if i < len(self.layers) - 1 else layer(x)
return x


# 测试代码
if __name__ == "__main__":
model = GazeAnywhere()
model.eval()

# 模拟输入
image = torch.randn(2, 3, 224, 224)
text_prompt = "the person wearing a red shirt"

with torch.no_grad():
output = model(image, text_prompt=text_prompt)

print("=== GazeAnywhere 测试 ===")
print(f"输入图像: {image.shape}")
print(f"文本提示: '{text_prompt}'")
print(f"预测bbox: {output['bbox'].shape} → {output['bbox'][0].tolist()}")
print(f"在画面内: {output['presence'][0].item():.4f}")
print(f"视线落点: {output['gaze_point'][0].tolist()}")
print(f"视线热力图: {output['gaze_heatmap'].shape}")
print()
print("论文核心价值: 端到端,无中间检测阶段")
print("→ IMS应用: 可用自然语言指定驾驶员,无需人脸检测前置")

4. Gaze-Co数据集

属性 值
总图像对 120K
标注类型 文本提示 + 视线落点对齐
来源 GazeFollow + VideoAttentionTarget 扩展
提示覆盖 外观/位置/姿态/动作四类
测试集 包含真实临床自闭症儿童数据

IMS开发启示

1. 对DMS视线检测的直接影响

传统DMS流水线 GazeAnywhere方式 优势
人脸检测→头部框→视线方向 文本提示→端到端视线 消除级联误差
需要清晰人脸 不需要人脸检测 墨镜/口罩场景可用
固定ROI裁剪 全图理解 多人场景灵活
需要头部姿态 隐式学习 减少计算量

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
class DMSGazeIntegration:
"""
DMS + GazeAnywhere集成方案

用途: 驾驶员视线落点检测
优势: 无需人脸检测前置,支持墨镜/口罩场景
"""

# 视线区域定义(归一化坐标)
GAZE_ZONES = {
'road_ahead': [(0.3, 0.4), (0.7, 0.6)], # 前方道路
'left_mirror': [(0.0, 0.3), (0.2, 0.5)], # 左后视镜
'right_mirror': [(0.8, 0.3), (1.0, 0.5)], # 右后视镜
'dashboard': [(0.3, 0.6), (0.7, 1.0)], # 仪表盘
'infotainment': [(0.4, 0.7), (0.6, 0.9)], # 中控屏
'phone': [(0.2, 0.6), (0.4, 0.8)], # 手机区域
'passenger': [(0.6, 0.2), (0.9, 0.5)] # 乘客区域
}

def __init__(self):
self.model = GazeAnywhere()
self.distraction_timer = 0

def detect_distraction(self, image, gaze_point):
"""检测分心状态"""
x, y = gaze_point
zone = self._classify_zone(x, y)

if zone in ['left_mirror', 'right_mirror', 'dashboard']:
# 正常区域,重置计时
self.distraction_timer = 0
return {'zone': zone, 'distraction': False}
elif zone in ['phone', 'passenger', 'infotainment']:
# 分心区域
self.distraction_timer += 1
if self.distraction_timer > 90: # 3秒@30fps
return {
'zone': zone,
'distraction': True,
'duration_s': self.distraction_timer / 30,
'level': 'warning' if self.distraction_timer < 180 else 'danger'
}

return {'zone': zone, 'distraction': False}

3. 与传统方法的对比

维度 传统DMS视线 GazeAnywhere IMS推荐
前置依赖 人脸检测+头部框 无 ✅ GazeAnywhere
多人场景 困难 文本提示指定 ✅ GazeAnywhere
墨镜/口罩 失效 仍可工作 ✅ GazeAnywhere
实时性 ~5ms ~30ms(DINOv3) ⚠️ 需优化
部署成本 低 高(大模型) ⚠️ 2027+
精度 ±2-3° SOTA ✅ GazeAnywhere

4. 部署优化建议

优化方向 方案 预期效果
模型蒸馏 DINOv3-L→DINOv3-S 推理快2-3x
量化 INT8量化Transformer 内存减50%
裁剪 固定驾驶员ROI 计算量减70%
早期退出 简单场景快速路径 平均延迟降40%

总结

GazeAnywhere代表了视线估计从”多阶段流水线”到”端到端可提示”的范式转变。

对IMS的4条可执行建议:

  1. 文本提示消除级联误差——不再依赖人脸检测前置
  2. 墨镜/口罩场景可用——不依赖面部关键点
  3. 2027+年部署——需蒸馏+量化后才能车规级实时
  4. Gaze-Co数据集可用于微调——120K标注,含儿童数据

论文链接: https://arxiv.org/abs/2608.11367
代码: https://github.com/IrohXu/GazeAnywhere
数据集: https://huggingface.co/datasets/IrohXu/Gaze-Co-Benchmark