InCaRPose:舱内摄像头位姿估计,后视镜调整后的自动校准方案

InCaRPose:舱内摄像头位姿估计,后视镜调整后的自动校准方案

核心问题

arXiv 2604.03814 (Aptiv + Wuppertal) 提出的舱内摄像头位姿估计:

问题 传统方法 InCaRPose
后视镜调整 需重新标定 自动校准
鱼眼畸变 先去畸变 端到端处理
训练数据 需大量真实数据 仅合成数据训练
推理速度 迭代求解 单步推理

研究背景

舱内摄像头部署挑战

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
舱内摄像头部署挑战:

┌─────────────────────────────────────────────────────┐
│ 后视镜集成 DMS │
├─────────────────────────────────────────────────────┤
│ │
│ 优势: │
│ ✅ 视野最佳(覆盖前排+后排) │
│ ✅ 不遮挡驾驶员视线 │
│ ✅ OEM 首选位置 │
│ │
│ 问题: │
│ ❌ 后视镜会被手动/自动调整 │
│ ❌ 摄像头外参变化 │
│ ❌ 视线估计精度下降 │
│ ❌ 乘员位置检测错误 │
│ │
│ Euro NCAP 要求: │
│ 气囊部署需在 15-50ms 内确定乘员位置 │
│ │
└─────────────────────────────────────────────────────┘

传统标定方法的局限

方法 流程 问题
标定板 拍摄标定板 → 计算外参 无法在线执行
特征匹配 特征点匹配 → 本质矩阵 鱼眼畸变下失效
SLAM 连续帧跟踪 计算量大,延迟高

方法详解

InCaRPose 架构

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
"""
InCaRPose 舱内摄像头位姿估计

基于 Transformer 的相对位姿预测
"""

import torch
import torch.nn as nn

class InCaRPose(nn.Module):
"""
舱内摄像头相对位姿估计器

预测当前视图相对于参考视图的位姿变换
"""

def __init__(
self,
backbone: str = 'dinov2_small',
embed_dim: int = 384,
num_heads: int = 6,
num_layers: int = 6
):
super().__init__()

# 冻结的 ViT 骨干(DINOv2)
self.backbone = self._load_backbone(backbone)

# 冻结骨干参数
for param in self.backbone.parameters():
param.requires_grad = False

# Transformer 解码器
decoder_layer = nn.TransformerDecoderLayer(
d_model=embed_dim,
nhead=num_heads,
dim_feedforward=embed_dim * 4,
dropout=0.1
)
self.decoder = nn.TransformerDecoder(
decoder_layer,
num_layers=num_layers
)

# 位姿预测头
self.pose_head = nn.Sequential(
nn.Linear(embed_dim, 256),
nn.ReLU(),
nn.Linear(256, 128),
nn.ReLU(),
)

# 旋转预测(四元数)
self.rotation_head = nn.Linear(128, 4)

# 平移预测(米,绝对尺度)
self.translation_head = nn.Linear(128, 3)

def _load_backbone(self, name):
"""加载预训练 ViT"""
import torchvision.models as models
if name == 'dinov2_small':
# DINOv2 ViT-S/14
return torch.hub.load('facebookresearch/dinov2', 'dinov2_vits14')
else:
raise ValueError(f"Unknown backbone: {name}")

def forward(
self,
reference_image: torch.Tensor,
target_image: torch.Tensor
) -> dict:
"""
Args:
reference_image: (B, 3, H, W) 参考视图(校准后的)
target_image: (B, 3, H, W) 目标视图(调整后的)

Returns:
{
'rotation': (B, 4) 四元数 [w, x, y, z]
'translation': (B, 3) 平移向量 [x, y, z] (米)
}
"""
# 1. 提取特征
ref_features = self.backbone(reference_image) # (B, N, D)
tgt_features = self.backbone(target_image)

# 2. Transformer 解码
# 参考 -> Query, 目标 -> Memory
decoded = self.decoder(
tgt=ref_features.transpose(0, 1),
memory=tgt_features.transpose(0, 1)
)

# 3. 全局特征
global_features = decoded.mean(dim=0) # (B, D)

# 4. 位姿预测
pose_features = self.pose_head(global_features)

rotation = self.rotation_head(pose_features)
rotation = torch.nn.functional.normalize(rotation, dim=1) # 归一化四元数

translation = self.translation_head(pose_features)

return {
'rotation': rotation,
'translation': translation
}


class AutoCalibrationSystem:
"""
自动校准系统

检测后视镜调整并自动校准
"""

def __init__(self):
self.pose_estimator = InCaRPose()

# 参考图像(出厂校准)
self.reference_image = None

# 外参矩阵
self.extrinsics = None

# 检测阈值
self.adjustment_threshold = 0.01 # 1cm

def set_reference(self, image, extrinsics):
"""
设置参考图像和外参

Args:
image: 参考图像
extrinsics: 参考外参矩阵 (4x4)
"""
self.reference_image = image
self.extrinsics = extrinsics

def detect_and_calibrate(self, current_image):
"""
检测调整并校准

Args:
current_image: 当前图像

Returns:
{
'adjusted': bool,
'delta_rotation': quaternion,
'delta_translation': (x, y, z),
'new_extrinsics': 4x4 matrix
}
"""
if self.reference_image is None:
raise ValueError("Reference not set")

# 1. 估计相对位姿
pose = self.pose_estimator(
self.reference_image.unsqueeze(0),
current_image.unsqueeze(0)
)

# 2. 检查是否超过阈值
translation = pose['translation'][0]
if torch.norm(translation) > self.adjustment_threshold:
# 3. 更新外参
delta_R = self._quaternion_to_matrix(pose['rotation'][0])
delta_t = translation.numpy()

# 构建变换矩阵
delta_T = np.eye(4)
delta_T[:3, :3] = delta_R
delta_T[:3, 3] = delta_t

new_extrinsics = self.extrinsics @ delta_T

return {
'adjusted': True,
'delta_rotation': pose['rotation'][0],
'delta_translation': tuple(delta_t),
'new_extrinsics': new_extrinsics
}

return {
'adjusted': False,
'delta_rotation': None,
'delta_translation': None,
'new_extrinsics': self.extrinsics
}

核心创新

1. 绝对尺度平移

1
2
3
4
5
6
7
8
9
10
11
传统方法 vs InCaRPose:

传统相对位姿估计:
├─ 平移向量只有方向,无尺度
├─ 需要已知场景结构
└─ 无法直接用于舱内应用

InCaRPose:
├─ 预测绝对尺度的平移(米)
├─ 利用舱内摄像头安装范围约束
└─ 可直接用于安全关键应用

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
"""
鱼眼图像端到端处理

不需要显式去畸变
"""

class FisheyeAwareFeatureExtractor(nn.Module):
"""
鱼眼感知特征提取器

直接处理畸变图像
"""

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

# 多尺度特征提取
self.pyramid = nn.ModuleList([
nn.Conv2d(3, 64, 7, 2, 3),
nn.Conv2d(64, 128, 3, 2, 1),
nn.Conv2d(128, 256, 3, 2, 1),
nn.Conv2d(256, 512, 3, 2, 1),
])

# 畸变感知注意力
self.distortion_attention = nn.Sequential(
nn.Conv2d(512, 128, 1),
nn.ReLU(),
nn.Conv2d(128, 1, 1),
nn.Sigmoid()
)

def forward(self, x):
"""
Args:
x: 鱼眼畸变图像 (B, 3, H, W)

Returns:
features: (B, D, H', W')
"""
# 多尺度特征
for layer in self.pyramid:
x = layer(x)
x = torch.relu(x)

# 畸变感知注意力
attention = self.distortion_attention(x)
x = x * attention

return x

3. 合成数据训练

数据类型 数量 说明
合成舱内图像 10,000+ Blender 渲染
真实测试数据 144 张 公开发布

实验结果

位姿估计精度

指标 旋转误差 (°) 平移误差 (cm)
小调整 (< 5°) 0.8 0.5
中等调整 (5-15°) 1.5 1.2
大调整 (> 15°) 3.2 2.8

推理速度

骨干 参数量 推理时间 (ms)
ViT-Small 22M 15
ViT-Base 86M 35
ViT-Large 300M 80

IMS 开发启示

1. 集成到 DMS

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
"""
DMS 自动校准模块

集成 InCaRPose
"""

class DMSAutoCalibrationModule:
"""
DMS 自动校准模块
"""

def __init__(self):
self.calibrator = AutoCalibrationSystem()

# 视线估计器
self.gaze_estimator = GazeEstimator()

# 校准状态
self.calibration_valid = False

def process_frame(self, frame):
"""
处理单帧

Args:
frame: 图像帧

Returns:
{
'calibration_valid': bool,
'gaze': (pitch, yaw),
'calibration_updated': bool
}
"""
# 1. 检测并校准
result = self.calibrator.detect_and_calibrate(frame)

# 2. 更新校准状态
if result['adjusted']:
self.calibration_valid = True

# 更新视线估计器的外参
self.gaze_estimator.update_extrinsics(
result['new_extrinsics']
)

# 3. 视线估计
gaze = self.gaze_estimator.estimate(frame)

return {
'calibration_valid': self.calibration_valid,
'gaze': gaze,
'calibration_updated': result['adjusted']
}

2. 部署建议

平台 配置 预期延迟
Jetson Orin NX TensorRT FP16 20ms
Qualcomm QCS8255 SNPE INT8 30ms
TI TDA4VM TIDL INT8 40ms

总结

InCaRPose 核心贡献:

  1. 自动校准 - 后视镜调整后自动恢复外参
  2. 绝对尺度 - 预测米为单位的平移
  3. 鱼眼端到端 - 不需要显式去畸变
  4. 合成数据训练 - 不依赖真实标注数据

对 IMS 开发的启示:

  • 后视镜集成 DMS 需要自动校准
  • ViT-Small 骨干适合边缘部署
  • 合成数据可以解决训练数据短缺

参考资源

资源 链接
论文 arxiv.org/abs/2604.03814
代码 github.com/felixstillger/InCaRPose
数据集 公开发布

InCaRPose:舱内摄像头位姿估计,后视镜调整后的自动校准方案
https://dapalm.com/2026/04/26/2026-04-26-incarpose-camera-calibration/
作者
Mars
发布于
2026年4月26日
许可协议