TransGaze-Object:基于Transformer的驾驶员注视物体预测框架深度解析

论文信息

项目 内容
标题 TransGaze-Object: Transformer Based Driver Gaze Object Prediction Framework in Real Driving
作者 Pavan Kumar Sharma, Ayush Pande, Pranamesh Chakraborty
机构 Indian Institute of Technology Kanpur, India
时间 2026年9月9日
arXiv 2609.10139
页数 32页, 17张图
代码 未开源(论文中未提及代码仓库)

核心创新

TransGaze-Object 首次将驾驶员视线估计问题从传统的”注视点回归(Point-of-Gaze, PoG)”重新定义为**”注视物体预测(Gaze Object Prediction)”**。

传统方法的局限:

graph LR
    A[驾驶员面部图像] --> B[视线方向估计]
    B --> C[注视点PoG回归]
    C --> D[后处理: PoG与物体包围框匹配]
    D --> E[注视物体]
    A -.->|误差累积| D
    B -.->|光照/遮挡| C
    C -.->|关联失败| D

TransGaze-Object 的方法:

graph LR
    A[驾驶员面部图像] --> B[面部+虹膜特征提取]
    C[交通场景图像] --> D[物体检测+空间特征]
    B --> E[Transformer交叉注意力]
    D --> E
    E --> F[直接预测注视物体]

关键突破: 不再需要先估计注视点再关联物体,而是通过Transformer交叉注意力直接从人脸特征和交通物体信息预测注视物体,避免了中间步骤的误差累积。


方法详解

1. 整体架构

TransGaze-Object 由三个核心模块组成:

graph TB
    subgraph "模块1: 面部特征提取"
        A[驾驶员面部图像] --> B[MediaPipe Face Mesh<br/>468个关键点]
        B --> C[面部ROI裁剪]
        C --> D[ResNet-18特征提取<br/>512维面部特征]
        D --> E[虹膜加权眼部区域]
        E --> F[独立ResNet-18<br/>512维眼部特征]
    end
    
    subgraph "模块2: 交通物体特征提取"
        G[前向场景图像] --> H[YOLOv8物体检测]
        H --> I[物体包围框坐标]
        I --> J[每个物体空间特征<br/>归一化坐标+尺寸]
        J --> K[MLP编码<br/>128维物体特征]
    end
    
    subgraph "模块3: Transformer交叉注意力融合"
        F --> L[Query: 面部+眼部特征]
        K --> M[Key/Value: 物体特征]
        L --> N[Multi-Head Cross-Attention]
        M --> N
        N --> O[注意力权重+相似度得分]
        O --> P[Softmax分类]
        P --> Q[输出: 注视物体或背景]
    end

2. 面部特征提取

2.1 面部关键点检测

使用 MediaPipe Face Mesh 检测468个面部关键点,提取两个关键区域:

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
import cv2
import mediapipe as mp
import numpy as np

class FacialFeatureExtractor:
"""
面部特征提取模块

使用MediaPipe Face Mesh检测468个关键点,
分别提取面部ROI和虹膜加权眼部区域

参考论文 Section 4.1
"""

def __init__(self):
self.mp_face_mesh = mp.solutions.face_mesh.FaceMesh(
max_num_faces=1,
refine_landmarks=True, # 启用虹膜关键点
min_detection_confidence=0.5,
min_tracking_confidence=0.5
)
# 虹膜关键点索引(MediaPipe 468模型 + 虹膜扩展)
self.iris_left_indices = [468, 469, 470, 471, 472]
self.iris_right_indices = [473, 474, 475, 476, 477]
# 眼部周围关键点
self.left_eye_indices = [33, 7, 163, 144, 145, 153, 154, 155,
133, 173, 157, 158, 159, 160, 161, 246]
self.right_eye_indices = [362, 382, 381, 380, 374, 373, 390,
249, 263, 466, 388, 387, 386, 385, 384, 398]

def extract_features(self, face_image: np.ndarray) -> dict:
"""
从面部图像提取面部特征和虹膜加权眼部特征

Args:
face_image: BGR格式面部图像, shape=(H, W, 3)

Returns:
features: 包含面部ROI和眼部ROI的字典

Example:
>>> extractor = FacialFeatureExtractor()
>>> features = extractor.extract(face_img)
>>> face_tensor = preprocess(features['face_roi']) # -> ResNet-18
>>> eye_tensor = preprocess(features['eye_roi']) # -> ResNet-18
"""
h, w = face_image.shape[:2]
rgb_image = cv2.cvtColor(face_image, cv2.COLOR_BGR2RGB)
results = self.mp_face_mesh.process(rgb_image)

if not results.multi_face_landmarks:
return None

landmarks = results.multi_face_landmarks[0].landmark

# 提取面部包围框
face_points = np.array([[lm.x * w, lm.y * h] for lm in landmarks])
x_min, y_min = face_points.min(axis=0).astype(int)
x_max, y_max = face_points.max(axis=0).astype(int)
# 扩展20%边距
x_min = max(0, x_min - int(0.1 * w))
y_min = max(0, y_min - int(0.1 * h))
x_max = min(w, x_max + int(0.1 * w))
y_max = min(h, y_max + int(0.1 * h))
face_roi = face_image[y_min:y_max, x_min:x_max]

# 提取虹膜加权眼部区域
left_iris = np.array([[landmarks[i].x * w, landmarks[i].y * h]
for i in self.iris_left_indices])
right_iris = np.array([[landmarks[i].x * w, landmarks[i].y * h]
for i in self.iris_right_indices])
left_eye = np.array([[landmarks[i].x * w, landmarks[i].y * h]
for i in self.left_eye_indices])
right_eye = np.array([[landmarks[i].x * w, landmarks[i].y * h]
for i in self.right_eye_indices])

# 计算眼部ROI(包含虹膜)
all_eye_points = np.vstack([left_eye, right_eye,
left_iris, right_iris])
ex_min, ey_min = all_eye_points.min(axis=0).astype(int)
ex_max, ey_max = all_eye_points.max(axis=0).astype(int)
# 扩展边距
margin = int(0.3 * (ex_max - ex_min))
ex_min = max(0, ex_min - margin)
ey_min = max(0, ey_min - margin)
ex_max = min(w, ex_max + margin)
ey_max = min(h, ey_max + margin)
eye_roi = face_image[ey_min:ey_max, ex_min:ex_max]

return {
'face_roi': face_roi,
'eye_roi': eye_roi,
'iris_left': left_iris,
'iris_right': right_iris,
'face_bbox': (x_min, y_min, x_max, y_max)
}

2.2 特征提取网络

论文使用两个独立的 ResNet-18 分别处理面部 ROI 和眼部 ROI:

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
import torch
import torch.nn as nn
from torchvision import models

class DualStreamFaceEncoder(nn.Module):
"""
双流面部特征编码器

流1: 面部ROI -> ResNet-18 -> 512维面部特征
流2: 虹膜加权眼部ROI -> ResNet-18 -> 512维眼部特征

论文 Section 4.1: 两条流独立提取特征后拼接
"""

def __init__(self, feature_dim: int = 512):
super().__init__()
# 面部特征提取流
self.face_backbone = models.resnet18(weights=models.ResNet18_Weights.DEFAULT)
self.face_backbone.fc = nn.Identity() # 移除分类头

# 眼部特征提取流(共享架构但独立参数)
self.eye_backbone = models.resnet18(weights=models.ResNet18_Weights.DEFAULT)
self.eye_backbone.fc = nn.Identity()

# 特征投影层
self.face_proj = nn.Linear(feature_dim, 256)
self.eye_proj = nn.Linear(feature_dim, 256)
self.relu = nn.ReLU()
self.dropout = nn.Dropout(0.1)

def forward(self, face_img: torch.Tensor, eye_img: torch.Tensor) -> torch.Tensor:
"""
Args:
face_img: (B, 3, 224, 224) 面部ROI
eye_img: (B, 3, 224, 224) 眼部ROI

Returns:
fused_feature: (B, 512) 拼接特征
"""
face_feat = self.face_backbone(face_img) # (B, 512)
eye_feat = self.eye_backbone(eye_img) # (B, 512)

# 投影到256维
face_proj = self.dropout(self.relu(self.face_proj(face_feat))) # (B, 256)
eye_proj = self.dropout(self.relu(self.eye_proj(eye_feat))) # (B, 256)

# 拼接
fused = torch.cat([face_proj, eye_proj], dim=-1) # (B, 512)
return fused

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
class TrafficObjectEncoder(nn.Module):
"""
交通物体空间特征编码器

使用YOLOv8检测场景物体,提取每个物体的空间特征
论文 Section 4.2

输入: 物体包围框坐标 [x_min, y_min, x_max, y_max]
输出: 128维物体空间特征
"""

def __init__(self, num_object_types: int = 8, feat_dim: int = 128):
super().__init__()
# 物体类型嵌入
self.obj_type_embed = nn.Embedding(num_object_types, 32)

# 空间特征编码
self.spatial_encoder = nn.Sequential(
nn.Linear(4, 32), # 归一化坐标
nn.ReLU(),
nn.Linear(32, 64),
nn.ReLU(),
nn.Linear(64, feat_dim - 32), # 拼接类型嵌入
)

def forward(self, bboxes: torch.Tensor, obj_types: torch.Tensor) -> torch.Tensor:
"""
Args:
bboxes: (B, N, 4) 归一化包围框 [x_min, y_min, x_max, y_max]
obj_types: (B, N) 物体类型索引

Returns:
obj_features: (B, N, feat_dim) 物体空间特征
"""
B, N, _ = bboxes.shape

# 归一化坐标
spatial_feat = self.spatial_encoder(bboxes) # (B, N, 96)

# 物体类型嵌入
type_embed = self.obj_type_embed(obj_types) # (B, N, 32)

# 拼接
obj_features = torch.cat([spatial_feat, type_embed], dim=-1) # (B, N, 128)
return obj_features

4. Transformer交叉注意力融合

这是论文的核心创新——使用交叉注意力机制融合面部特征和物体特征:

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
class GazeObjectTransformer(nn.Module):
"""
基于Transformer交叉注意力的注视物体预测模型

论文 Section 4.3 核心

Query: 面部+眼部特征
Key/Value: 交通物体空间特征
输出: 每个物体的注意力权重 + 背景类

准确率: 60%(vs PoG关联方法 51%)
错误率: 11.68%(vs PoG方法 23.21%,降低49.7%)
"""

def __init__(self, face_feat_dim: int = 512, obj_feat_dim: int = 128,
d_model: int = 256, nhead: int = 8, num_layers: int = 3):
super().__init__()

# 特征投影到统一维度
self.face_proj = nn.Linear(face_feat_dim, d_model)
self.obj_proj = nn.Linear(obj_feat_dim, d_model)

# 位置编码(物体在场景中的位置)
self.pos_embed = nn.Sequential(
nn.Linear(4, 64),
nn.ReLU(),
nn.Linear(64, d_model)
)

# Transformer交叉注意力层
cross_attention_layer = nn.TransformerDecoderLayer(
d_model=d_model,
nhead=nhead,
dim_feedforward=512,
dropout=0.1,
batch_first=True
)
self.cross_attention = nn.TransformerDecoder(
cross_attention_layer,
num_layers=num_layers
)

# 分类头
self.classifier = nn.Sequential(
nn.Linear(d_model, 128),
nn.ReLU(),
nn.Dropout(0.1),
nn.Linear(128, 1) # 每个物体的二分类得分
)

def forward(self, face_features: torch.Tensor,
obj_features: torch.Tensor,
obj_bboxes: torch.Tensor) -> dict:
"""
Args:
face_features: (B, 512) 面部+眼部融合特征
obj_features: (B, N, 128) 物体空间特征
obj_bboxes: (B, N, 4) 物体归一化坐标

Returns:
output: {
'scores': (B, N+1) 每个物体+背景的得分,
'attn_weights': (B, 1, N) 注意力权重
}
"""
B, N, _ = obj_features.shape

# 投影特征
face_query = self.face_proj(face_features) # (B, 256)
obj_kv = self.obj_proj(obj_features) # (B, N, 256)

# 加入位置编码
pos = self.pos_embed(obj_bboxes) # (B, N, 256)
obj_kv = obj_kv + pos

# 面部特征作为query (B, 1, 256)
face_query = face_query.unsqueeze(1)

# 交叉注意力
# query: 面部特征, key/value: 物体特征
attn_out = self.cross_attention(
tgt=face_query, # (B, 1, 256)
memory=obj_kv # (B, N, 256)
) # (B, 1, 256)

# 提取注意力权重
attn_weights = torch.matmul(
face_query, # (B, 1, 256)
obj_kv.transpose(-1, -2) # (B, 256, N)
) / (256 ** 0.5) # (B, 1, N)

# 分类得分
obj_scores = self.classifier(attn_out.squeeze(1)) # (B, 1)

# 背景类得分(注意力权重的均值)
bg_score = attn_weights.mean(dim=-1) # (B, 1)

# 拼接所有得分
all_scores = torch.cat([obj_scores.squeeze(-1), bg_score.squeeze(-1)],
dim=-1) # (B, N+1)

return {
'scores': all_scores,
'attn_weights': attn_weights
}


# 完整推理流程
class TransGazeObjectInference:
"""
TransGaze-Object 完整推理流程

从摄像头输入到注视物体预测的端到端流程
"""

def __init__(self, device='cuda'):
self.device = device
self.face_extractor = FacialFeatureExtractor()
self.face_encoder = DualStreamFaceEncoder().to(device).eval()
self.object_encoder = TrafficObjectEncoder().to(device).eval()
self.gaze_transformer = GazeObjectTransformer().to(device).eval()

# YOLOv8 物体检测器
from ultralytics import YOLO
self.detector = YOLO('yolov8n.pt')

# 图像预处理
self.transform = __import__('torchvision.transforms').transforms.Compose([
__import__('torchvision.transforms').transforms.ToPILImage(),
__import__('torchvision.transforms').transforms.Resize((224, 224)),
__import__('torchvision.transforms').transforms.ToTensor(),
__import__('torchvision.transforms').transforms.Normalize(
mean=[0.485, 0.456, 0.406],
std=[0.229, 0.224, 0.225]
)
])

def predict(self, face_img: np.ndarray, scene_img: np.ndarray) -> dict:
"""
端到端注视物体预测

Args:
face_img: 驾驶员面部图像 (H, W, 3) BGR
scene_img: 前向场景图像 (H, W, 3) BGR

Returns:
result: {
'gaze_object_idx': int, # 注视物体索引(-1=背景)
'gaze_object_class': str, # 物体类别
'confidence': float, # 置信度
'all_scores': np.ndarray # 所有物体得分
}
"""
with torch.no_grad():
# Step 1: 提取面部特征
face_data = self.face_extractor.extract(face_img)
if face_data is None:
return {'gaze_object_idx': -1, 'confidence': 0.0}

face_tensor = self.transform(face_data['face_roi']).unsqueeze(0).to(self.device)
eye_tensor = self.transform(face_data['eye_roi']).unsqueeze(0).to(self.device)
face_feat = self.face_encoder(face_tensor, eye_tensor) # (1, 512)

# Step 2: 检测交通物体
results = self.detector(scene_img, verbose=False)
boxes = results[0].boxes
if len(boxes) == 0:
return {'gaze_object_idx': -1, 'confidence': 1.0}

# 提取物体坐标和类别
h, w = scene_img.shape[:2]
bboxes = []
obj_types = []
for box in boxes:
x1, y1, x2, y2 = box.xyxy[0].cpu().numpy()
bboxes.append([x1/w, y1/h, x2/w, y2/h])
obj_types.append(int(box.cls[0]))

bboxes = torch.tensor(bboxes).float().unsqueeze(0).to(self.device)
obj_types = torch.tensor(obj_types).long().unsqueeze(0).to(self.device)

# Step 3: 物体特征编码
obj_feat = self.object_encoder(bboxes, obj_types) # (1, N, 128)

# Step 4: Transformer交叉注意力预测
output = self.gaze_transformer(face_feat, obj_feat, bboxes)
scores = output['scores'] # (1, N+1)

# Step 5: 取最高得分的物体
probs = torch.softmax(scores, dim=-1)
pred_idx = probs.argmax(dim=-1).item()
confidence = probs.max().item()

if pred_idx >= len(boxes):
gaze_class = 'background'
gaze_idx = -1
else:
gaze_idx = pred_idx
gaze_class = results[0].names[int(boxes[pred_idx].cls[0])]

return {
'gaze_object_idx': gaze_idx,
'gaze_object_class': gaze_class,
'confidence': confidence,
'all_scores': probs.cpu().numpy()
}


# 测试
if __name__ == "__main__":
import numpy as np

# 模拟测试
inference = TransGazeObjectInference(device='cpu')

# 生成模拟图像
face_img = np.random.randint(0, 255, (480, 640, 3), dtype=np.uint8)
scene_img = np.random.randint(0, 255, (720, 1280, 3), dtype=np.uint8)

result = inference.predict(face_img, scene_img)
print(f"注视物体: {result['gaze_object_class']}")
print(f"置信度: {result['confidence']:.4f}")
print(f"所有得分: {result['all_scores']}")

UD-FSG 数据集

论文贡献了新的驾驶注视数据集 UD-FSG (Urban Driving-Face Scene Gaze):

属性 数值
驾驶员人数 35(男性,平均年龄35.77±6.30岁)
驾驶经验 平均13.70±5.85年
采集地点 印度 Kanpur 城市道路
采集时长 每人约1小时,30-35km
帧率 原始10fps,抽取5fps
交通密度 高密度异质城市交通
传感器 面部摄像头 + 前向场景摄像头 + Pupil Invisible眼动仪
标注 2D注视坐标 + 注视物体类别

与现有数据集对比

数据集 面部图像 场景图像 物体标注 注视物体标签 交通密度
DMD ✅ ❌ ❌ ❌ N/A
DGAZE ✅ ✅(投影) ✅ ❌ 低
LBW ✅ ✅ ❌ ❌ 低(平均4物体/图)
UD-FSG ✅ ✅ ✅ ✅ 高(城市密集交通)

数据采集流程

graph TB
    A[驾驶员佩戴Pupil Invisible眼动仪] --> B[面部摄像头记录面部视频]
    A --> C[眼动仪场景摄像头记录注视点]
    D[前向场景摄像头记录交通视频] --> E[GStreamer同步所有摄像头]
    B --> E
    C --> E
    D --> E
    E --> F[5fps帧提取]
    F --> G[AprilTag参考标记]
    G --> H[眼动仪坐标系→固定场景坐标系<br/>Homography变换]
    H --> I[2D注视点归一化]
    I --> J[YOLOv8物体检测+人工标注]
    J --> K[注视物体标签分配]

实验结果

注视物体预测准确率

方法 准确率 物体-背景混淆错误率
PoG关联方法 51% 23.21%
TransGaze-Object 60% 11.68%
提升 +9pp 降低49.7%

错误分析

论文的混淆矩阵分析揭示了关键发现:

错误类型 PoG方法 TransGaze-Object 改善
物体→背景 高 低 ✅ 显著改善
背景→物体 中 低 ✅ 改善
物体→物体 中 中 ➡️ 相当
远距离物体 高 中 ✅ 改善

核心发现: TransGaze-Object 最大的改善在于减少了”物体-背景”混淆,这是因为直接预测方法能更好地区分驾驶员是否在看某个具体物体还是在看背景区域。

消融实验

配置 准确率
仅面部特征 48%
面部+眼部特征 54%
面部+眼部+物体位置 58%
面部+眼部+物体位置+物体类别 60%

IMS 开发启示

1. 架构启示:从”估计-关联”到”直接预测”

1
2
3
4
5
6
7
传统DMS视线估计流程:
面部 → 视线向量 → 注视点 → 物体关联 → 语义理解
误差:每一步都累积

TransGaze-Object流程:
面部 + 场景物体 → 直接语义预测
优势:端到端优化,避免中间误差

对IMS的启示: 当前的疲劳/分心检测可以借鉴这个思路——不一定要先估计PERCLOS/视线偏离度再判断状态,可以直接从面部特征+场景上下文直接预测”驾驶员是否在关注关键区域”。

2. 部署可行性评估

维度 评估
计算量 2×ResNet-18 + YOLOv8 + 3层Transformer ≈ 可接受
实时性 论文未报告FPS,估计 15-20fps(需优化)
部署芯片 Qualcomm QCS8255 可运行,Hexagon NPU支持Transformer
传感器需求 2个摄像头(面部+前向场景),与现有DMS配置一致
训练数据 需要采集场景-面部配对数据,成本较高

3. 与 Euro NCAP 2026 的关联

Euro NCAP 要求 TransGaze-Object 支持度
视线区域估计 ✅ 可直接输出注视物体(比区域更精确)
分心检测 ✅ 注视物体可判断是否关注道路
驾驶员接管准备度 ✅ 注视物体可评估情景意识
遮挡处理 ⚠️ 论文未重点讨论遮挡场景

4. 技术路线建议

优先级 行动项 时间
🔴 高 下载论文PDF,团队内分享研读 1周内
🔴 高 评估UD-FSG数据集获取可能性 1周内
🟡 中 在现有DMS数据上复现核心方法 2-4周
🟡 中 评估Transformer在QCS8255上的推理速度 2周内
🟢 低 探索使用更轻量级模型替代ResNet-18 1-2月

5. 代码复现要点

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
# 关键复现步骤
# 1. 安装依赖
# pip install torch torchvision mediapipe ultralytics opencv-python

# 2. 数据准备
# 需要: 面部视频 + 前向场景视频 + 眼动仪标注
# 使用AprilTag进行坐标系对齐

# 3. 模型训练
# - 面部编码器预训练: ImageNet权重初始化
# - 物体检测器: YOLOv8n 预训练
# - Transformer: 随机初始化, 3层, 8头注意力
# - 学习率: 1e-4, AdamW优化器
# - Batch size: 32
# - 训练轮次: 50 epochs

# 4. 关键超参数
HYPERPARAMS = {
'd_model': 256, # 统一特征维度
'nhead': 8, # 注意力头数
'num_layers': 3, # Transformer层数
'dropout': 0.1, # Dropout率
'face_feat_dim': 512, # 面部特征维度
'obj_feat_dim': 128, # 物体特征维度
'learning_rate': 1e-4, # 学习率
'batch_size': 32, # 批量大小
'epochs': 50, # 训练轮次
}

局限性与未来方向

论文局限

问题 分析
仅男性驾驶员 35名全男性,性别偏差未验证
印度交通场景 异质交通密度高,泛化性需验证
未报告FPS 实时性不确定
无开源代码 复现成本高
背景类定义模糊 “背景”包含什么不明确
60%准确率 仍有40%误

TransGaze-Object:基于Transformer的驾驶员注视物体预测框架深度解析
https://dapalm.com/2026/10/01/2026-10-01-16-transgaze-object-transformer-driver-gaze-object-prediction-ims/
作者
Mars
发布于
2026年10月1日
许可协议