流程

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16

多张图片 + 相机参数
↓
用 COLMAP 得到相机位姿和稀疏点云
↓
用稀疏点云初始化一堆 3D Gaussian
↓
从某个相机视角把 Gaussian 渲染成图片
↓
和真实图片比较,计算 loss
↓
反向传播优化 Gaussian 的位置、大小、颜色、不透明度
↓
不断增删 Gaussian
↓
得到可以实时新视角渲染的 3D 场景

核心链路

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

COLMAP 点云
↓
初始化 3D Gaussians
↓
选择相机视角
↓
外参:世界坐标 → 相机坐标
↓
内参:相机坐标 → 像素坐标
↓
3D Gaussian 投影成 2D 椭圆
↓
深度排序
↓
alpha blending
↓
渲染图
↓
和真实图计算 loss
↓
反向传播优化 Gaussian
↓
densify / prune
↓
最终 3D Gaussian 场景

COLMAP 流程

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17

图片
↓
特征提取
↓
特征匹配
↓
几何验证
↓
增量式 SfM (选择初始图像对 , 根据匹配点估计两台相机之间的相对姿态)
↓
三角化生成稀疏点云
↓
Bundle Adjustment 联合优化
↓
输出相机参数 + 相机位姿 + 稀疏点云

Gaussian 参数

参数作用
mean / xyzGaussian 在 3D 空间中的中心位置
scaleGaussian 在三个方向上的大小
rotation / quaternionGaussian 椭球的朝向
opacity不透明度
color / SH颜色,通常用球谐函数表示视角相关颜色

训练

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

gaussians = init_from_colmap_points()
cameras = load_colmap_cameras()
images = load_training_images()

for iter in range(num_iterations):

# 1. 随机选择一个训练视角
camera = random_choice(cameras)
gt_image = camera.gt_image

# 2. 用当前 Gaussian 从该视角渲染图像
render_image = render(gaussians, camera)

# 3. 和真实图像比较
loss = l1_loss(render_image, gt_image) + ssim_loss(render_image, gt_image)

# 4. 反向传播
loss.backward()

# 5. 更新 Gaussian 参数
optimizer.step()
optimizer.zero_grad()

# 6. 定期增加 / 删除 Gaussian
if iter in densification_stage:
densify_and_prune(gaussians)