19fdb429ebe21.png

"Splat, Track & Map —— 一句话概括 CVPR 2024 最令人兴奋的 SLAM 工作之一。"


📌 三大核心贡献

1️⃣ SplaTAM 是首个将 3D Gaussian Splatting(3DGS) 作为场景表示、端到端做 Dense RGB-D SLAM 的系统,由 CMU、MIT 等机构联合完成,入选 CVPR 2024。

2️⃣ 它把复杂的 SLAM 问题拆解为三个简洁步骤 —— Splat(初始化高斯)→ Track(跟踪位姿)→ Map(优化地图),全部基于可微栅格化器完成。

3️⃣ 在 Replica / ScanNet++ / TUM 等主流 benchmark 上,ATE(绝对轨迹误差)比 NICE-SLAM、Point-SLAM 低一个量级,新视角合成质量接近离线 3DGS。


一、🌍 背景:为什么 SLAM 需要一场"表示革命"?

1.1 传统 SLAM 的困境

同步定位与建图(SLAM)是机器人、AR/VR、自动驾驶的基石技术。过去十年,NeRF 和 SDF 等隐式神经表示被引入 SLAM,试图用 MLP 编码场景几何:

方法 表示方式 渲染速度 几何质量 在线可行性
NeRF-SLAM 隐式 MLP ❌ 慢(逐射线采样) 中 ❌ 难实时
SDF-SLAM 隐式符号距离 ❌ 慢 中 ❌ 难实时
点云 SLAM 显式点 ✅ 快 ❌ 稀疏 ✅ 实时
SplaTAM 显式 3D 高斯 ✅ 快(栅格化) ✅ 稠密 ✅ 实时

💡 核心洞察:3D Gaussian Splatting 天然适合 SLAM —— 它是显式的(可直接优化参数)、可微的(栅格化器支持反向传播)、并行的(GPU 栅格化极快)、各向同性的(简化旋转处理)。

1.2 SplaTAM 在 SLAM 家族中的位置

19fdb4504bd54.png

二、🏗️ 核心技术解析(代码级 🔍)

2.1 整体架构:三步走战略

19fdb4727ee0c.png

SplaTAM 的核心思想极其优雅 —— 整个 SLAM 系统只维护一组 3D 高斯参数,所有操作(跟踪、建图、渲染)都通过同一个可微栅格化器完成。

# splatam.py —— 主循环伪代码(已简化)
for time_idx in range(num_frames):
    # Step 1: TRACKING —— 只优化相机位姿
    params = initialize_camera_pose(params, time_idx)
    for iter in range(tracking_iters):
        loss, _, _ = get_loss(params, curr_data, ..., tracking=True)
        loss.backward()
        optimizer.step()  # 只更新 cam_unnorm_rots & cam_trans

    # Step 2: DENSIFICATION —— 在缺失区域插入新高斯
    if add_new_gaussians:
        params, variables = add_new_gaussians(params, variables, curr_data, ...)

    # Step 3: MAPPING —— 优化高斯参数
    for iter in range(mapping_iters):
        loss, _, _ = get_loss(params, curr_data, ..., mapping=True)
        loss.backward()
        optimizer.step()  # 只更新 means3D / rgb / scales / opacities

🔑 设计哲学:三个步骤交替进行、各司其职。Tracking 和 Mapping 的优化变量完全解耦,避免相互干扰。


2.2 关键创新①:用深度图反投影初始化高斯

SplaTAM 的第一帧处理是整个系统的"种子"——它决定了后续所有优化的起点。

# splatam.py —— get_pointcloud()
def get_pointcloud(color, depth, intrinsics, w2c, transform_pts=True, 
                   mask=None, compute_mean_sq_dist=False, mean_sq_dist_method="projective"):
    CX, CY = intrinsics[0][2], intrinsics[1][2]
    FX, FY = intrinsics[0][0], intrinsics[1][1]

    # 将像素坐标反投影到相机坐标系
    x_grid, y_grid = torch.meshgrid(torch.arange(width), torch.arange(height))
    xx = (x_grid - CX) / FX
    yy = (y_grid - CY) / FY
    depth_z = depth[0].reshape(-1)
    pts_cam = torch.stack((xx * depth_z, yy * depth_z, depth_z), dim=-1)

    # 转换到世界坐标系
    c2w = torch.inverse(w2c)
    pts4 = torch.cat((pts_cam, torch.ones_like(pts_cam[:, :1])), dim=1)
    pts = (c2w @ pts4.T).T[:, :3]

    # 用投影几何估算每个高斯的初始半径
    if compute_mean_sq_dist:
        scale_gaussian = depth_z / ((FX + FY) / 2)  # 远处高斯更大
        mean3_sq_dist = scale_gaussian ** 2

关键设计要点:

设计决策 原因
用深度图反投影而非随机初始化 首帧就有合理几何,加速收敛
高斯半径 ∝ 深度 远处场景覆盖更大区域,避免"空洞"
颜色直接用 RGB 跳过 SH 系数拟合,节省显存
各向同性(1 个 scale) 减少参数,SLAM 中旋转梯度不稳定

2.3 关键创新②:一次渲染,三路输出

这是 SplaTAM 最巧妙的设计 —— 它不修改栅格化器,而是通过构造特殊的 colors_precomp,让同一次 Renderer() 调用同时输出 RGB + 深度 + 轮廓:

# gs_helpers.py —— get_depth_and_silhouette()
def get_depth_and_silhouette(pts_3D, w2c):
    """用高斯中心在相机坐标系中的 z 值作为"颜色"来渲染"""
    pts4 = torch.cat((pts_3D, torch.ones_like(pts_3D[:, :1])), dim=-1)
    pts_in_cam = (w2c @ pts4.transpose(0, 1)).transpose(0, 1)
    depth_z = pts_in_cam[:, 2].unsqueeze(-1)       # 第 0 通道 → 深度
    depth_z_sq = torch.square(depth_z)               # 第 2 通道 → 深度²(用于算不确定性)

    depth_silhouette = torch.zeros((pts_3D.shape[0], 3)).cuda()
    depth_silhouette[:, 0] = depth_z.squeeze(-1)    # Channel 0: depth
    depth_silhouette[:, 1] = 1.0                    # Channel 1: silhouette(恒为1 → alpha累加=轮廓)
    depth_silhouette[:, 2] = depth_z_sq.squeeze(-1) # Channel 2: depth²

    return depth_silhouette

然后在 splatam.py 的 get_loss() 中:

# RGB 渲染(正常颜色)
rendervar = transformed_params2rendervar(params, transformed_gaussians)
im, radius, _, = Renderer(raster_settings=cam)(**rendervar)

# 深度+轮廓 渲染(用 depth_and_silhouette 作为"颜色")
depth_sil_rendervar = transformed_params2depthplussilhouette(params, w2c, ...)
depth_sil, _, _, = Renderer(raster_settings=cam)(**depth_sil_rendervar)
depth = depth_sil[0, :, :]       # ← 渲染出来的"深度图"
silhouette = depth_sil[1, :, :]   # ← 渲染出来的"轮廓图"
uncertainty = depth_sil[2] - depth**2  # ← 深度方差 = 不确定性

🎯 为什么这样做? – 不修改栅格化器:SplaTAM 直接复用 diff_gaussian_rasterization,零侵入 – 一次 forward,三路输出:省去额外渲染开销 – 不确定性天然可得:E[z²] - E[z]² 就是渲染深度的方差,用于 outlier rejection


2.4 关键创新③:Tracking 与 Mapping 的解耦优化

SplaTAM 的优化策略极其讲究。通过 transform_to_frame 控制哪些变量参与梯度计算:

# slam_helpers.py —— transform_to_frame()
def transform_to_frame(params, time_idx, gaussians_grad, camera_grad):
    """将高斯从世界坐标系变换到当前帧相机坐标系"""
    if camera_grad:
        cam_rot = F.normalize(params['cam_unnorm_rots'][..., time_idx])
        cam_tran = params['cam_trans'][..., time_idx]
    else:
        cam_rot = F.normalize(params['cam_unnorm_rots'][..., time_idx].detach())
        cam_tran = params['cam_trans'][..., time_idx].detach()

    rel_w2c = torch.eye(4).cuda()
    rel_w2c[:3, :3] = build_rotation(cam_rot)
    rel_w2c[:3, 3] = cam_tran

    # 将高斯中心变换到相机坐标系
    pts4 = torch.cat((params['means3D'], torch.ones_like(params['means3D'][:, :1])), dim=1)
    transformed_pts = (rel_w2c @ pts4.T).T[:, :3]

    return {'means3D': transformed_pts, 'unnorm_rotations': params['unnorm_rotations']}

三种模式,精准控制梯度流:

模式 gaussians_grad camera_grad 用途
Tracking ❌ Frozen ✅ Optimize 只算位姿,高斯不动
Mapping(帧内) ✅ Optimize ❌ Frozen 只优化地图,位姿不动
BA(Bundle Adjustment) ✅ Optimize ✅ Optimize 联合优化,关键帧回环用

对应的损失函数设计也截然不同:

# Tracking 损失 —— 用 sum 而非 mean,强调逐像素精度
if tracking:
    losses['depth'] = torch.abs(curr_data['depth'] - depth)[mask].sum()
    losses['im'] = torch.abs(curr_data['im'] - im).sum()
    # 额外:只在 silhouette > 0.99 的区域计算 loss(排除未建图区域)
    if use_sil_for_loss:
        mask = mask & (silhouette > sil_thres)  # sil_thres=0.99

# Mapping 损失 —— 用 SSIM + L1 组合,注重感知质量
else:
    losses['im'] = 0.8 * l1_loss_v1(im, curr_data['im']) + 0.2 * (1.0 - calc_ssim(im, curr_data['im']))
    losses['depth'] = torch.abs(curr_data['depth'] - depth)[mask].mean()

💡 Learning Rate 的极端差异(来自配置文件): – 相机位姿 LR:cam_unnorm_rots=0.0004, cam_trans=0.002(Tracking 时) – 高斯参数 LR:means3D=0.0001, rgb=0.0025, opacities=0.05 – 位姿 LR 比高斯 LR 大 4~20 倍 —— 因为位姿是 SLAM 的"骨架",必须快速收敛。


2.5 关键创新④:智能 densification(哪里缺补哪里)

SplaTAM 不像离线 3DGS 那样盲目 densify,而是用渲染结果主动发现"建图不足"的区域:

# splatam.py —— add_new_gaussians()
def add_new_gaussians(params, variables, curr_data, sil_thres, time_idx, ...):
    # 渲染当前帧的轮廓
    depth_sil = Renderer(**depth_sil_rendervar)
    silhouette = depth_sil[1, :, :]

    # 条件1:渲染轮廓稀薄 → 该区域高斯不够
    non_presence_sil_mask = (silhouette < sil_thres)  # sil_thres=0.5

    # 条件2:渲染深度远于 GT 深度 → 远处没建好
    gt_depth = curr_data['depth'][0, :, :]
    render_depth = depth_sil[0, :, :]
    depth_error = torch.abs(gt_depth - render_depth) * (gt_depth > 0)
    non_presence_depth_mask = (render_depth > gt_depth) * (depth_error > 50 * depth_error.median())

    # 两个条件取并集 → 反投影插新高斯
    non_presence_mask = non_presence_sil_mask | non_presence_depth_mask
    new_pt_cld, mean3_sq_dist = get_pointcloud(..., mask=non_presence_mask, ...)

🎯 两个触发条件,各管一摊: – Silhouette 稀薄 → 前景物体刚出现,需要更多高斯覆盖 – 渲染深度 > GT 深度 → 远处场景缺失,需要补充高斯


2.6 关键创新⑤:恒速位姿先验

对于非首帧,SplaTAM 用恒速运动模型初始化相机位姿,避免优化从零开始:

# splatam.py —— initialize_camera_pose()
def initialize_camera_pose(params, curr_time_idx, forward_prop):
    if curr_time_idx > 1 and forward_prop:
        # 恒速模型:current = prev + (prev - prev_prev)
        prev_rot1 = params['cam_unnorm_rots'][..., curr_time_idx-1].detach()
        prev_rot2 = params['cam_unnorm_rots'][..., curr_time_idx-2].detach()
        new_rot = F.normalize(prev_rot1 + (prev_rot1 - prev_rot2))

        prev_tran1 = params['cam_trans'][..., curr_time_idx-1].detach()
        prev_tran2 = params['cam_trans'][..., curr_time_idx-2].detach()
        new_tran = prev_tran1 + (prev_tran1 - prev_tran2)
    else:
        # 首帧或退化情况:沿用上一帧位姿
        new_rot = params['cam_unnorm_rots'][..., curr_time_idx-1].detach()
        new_tran = params['cam_trans'][..., curr_time_idx-1].detach()

💡 这看似简单,实则极其有效 —— 在高速运动或快速旋转时,恒速外推能将位姿误差降低 30%~50%。


2.7 关键帧选择:基于 3D 点云覆盖率

keyframe_selection.py 实现了 SplaTAM 的关键帧策略 —— 不是按帧间距机械选取,而是按"可见性"智能选取:

# keyframe_selection.py —— keyframe_selection_overlap()
def keyframe_selection_overlap(gt_depth, w2c, intrinsics, keyframe_list, k, pixels=1600):
    # Step 1: 从当前帧深度图采样 1600 个有效 3D 点
    pts = get_pointcloud(gt_depth, intrinsics, w2c, sampled_indices)

    # Step 2: 将 3D 点投影到每个候选关键帧的 image plane
    for keyframe in keyframe_list:
        est_w2c = keyframe['est_w2c']
        transformed_pts = (est_w2c @ pts4.T).T[:, :3]
        projected_2d = intrinsics @ transformed_pts.T
        projected_2d /= projected_2d[2:]  # 透视除法

        # Step 3: 统计落在图像范围内的点占比
        mask = (projected_2d[:, 0] > edge) & (projected_2d[:, 0] < width-edge)
        percent_inside = mask.sum() / projected_2d.shape[0]

    # Step 4: 选可见率最高的 K 个关键帧
    selected = sorted(list_keyframe, key=lambda x: x['percent_inside'], reverse=True)[:k]

🎯 为什么比"共视特征点数"更好? – 不依赖特征提取(更鲁棒) – 直接衡量几何重叠(更精确) – 计算量小(1600 个采样点足够)


2.8 相机建模:OpenCV ↔ OpenGL 投影桥接

recon_helpers.py 是 SplaTAM 的"隐形英雄" —— 它把 OpenCV/COLMAP 风格的内参转换成 diff_gaussian_rasterization 所需的 OpenGL 投影矩阵:

# recon_helpers.py —— setup_camera()
def setup_camera(w, h, k, w2c, near=0.01, far=100):
    fx, fy, cx, cy = k[0][0], k[1][1], k[0][2], k[1][2]

    # 构造 OpenGL 风格投影矩阵
    opengl_proj = torch.tensor([
        [2*fx/w, 0,        -(w-2*cx)/w,  0],
        [0,       2*fy/h,   -(h-2*cy)/h,  0],
        [0,       0,         far/(far-near), -far*near/(far-near)],
        [0,       0,         1,              0]
    ]).cuda().float()

    full_proj = w2c.bmm(opengl_proj)  # view × projection

    cam = Camera(
        image_height=h, image_width=w,
        tanfovx=w/(2*fx), tanfovy=h/(2*fy),
        bg=torch.tensor([0,0,0]), scale_modifier=1.0,
        viewmatrix=w2c, projmatrix=full_proj,
        sh_degree=0, campos=cam_center, prefiltered=False
    )
    return cam

⚠️ 踩坑提示:这是很多复现者会卡住的地方。OpenCV 和 OpenGL 的坐标系约定不同(Y 轴翻转、深度范围映射),SplaTAM 用上述转换完美桥接。


2.9 Pruning & Densification:生命周期管理

SplaTAM 在线管理高斯的"生老病死",借鉴了 Inria 原版 3DGS 的策略:

# slam_external.py —— prune_gaussians()
def prune_gaussians(params, variables, optimizer, iter, prune_dict):
    if iter <= prune_dict['stop_after']:
        if iter % prune_dict['prune_every'] == 0:
            # 移除低透明度高斯("死"高斯)
            to_remove = torch.sigmoid(params['logit_opacities']) < remove_threshold
            # 移除过大高斯(覆盖不合理)
            big_points = torch.exp(params['log_scales']).max(dim=1).values > 0.1 * scene_radius
            to_remove = to_remove | big_points
            params, variables = remove_points(to_remove, params, variables, optimizer)

# slam_external.py —— densify()
def densify(params, variables, optimizer, iter, densify_dict):
    # 梯度累积:哪些高斯"想要更多细节"
    grads = variables['means2D_gradient_accum'] / variables['denom']
    to_clone = grads >= grad_thresh  # 高梯度 → 克隆
    to_split = (grads >= grad_thresh) & (scales > threshold)  # 大高斯 → 分裂为2

完整的生命周期:

新帧到来
  │
  ├─ Tracking(优化位姿)
  │
  ├─ Densify Check(silhouette薄 or 深度远 → 插新高斯)
  │
  ├─ Mapping(优化高斯参数 K 次)
  │     ├─ 每 N 次:clone 高梯度小高斯
  │     ├─ 每 N 次:split 高梯度大高斯
  │     └─ 每 M 次:prune 低透明度/过大高斯
  │
  └─ 下一帧 →

2.10 PLY 导出:从研究到落地

export_ply.py 让 SplaTAM 的输出可以直接在 SuperSplat / PolyCam 等查看器中可视化:

# export_ply.py —— save_ply()
def save_ply(path, means, scales, rotations, rgbs, opacities):
    # 颜色 → 球谐系数(0阶 SH = 0.28209479)
    colors = (rgbs - 0.5) / 0.28209479177387814

    attrs = ['x', 'y', 'z',           # 位置
             'nx', 'ny', 'nz',       # 法向(占位)
             'f_dc_0', 'f_dc_1', 'f_dc_2',  # SH 颜色
             'opacity',                # 透明度
             'scale_0', 'scale_1', 'scale_2',  # 尺度
             'rot_0', 'rot_1', 'rot_2', 'rot_3']  # 四元数旋转

    PlyData([PlyElement.describe(elements, 'vertex')]).write(path)

🔑 SH 转换公式:sh = (rgb - 0.5) / C₀,其中 C₀ = 0.28209479。这是 3DGS 的标准约定,确保 PLY 文件可被所有主流查看器读取。


三、🚀 部署与工程实践建议

3.1 环境配置

# 推荐环境(官方验证通过)
conda create -n splatam python=3.10
conda activate splatam
conda install -c "nvidia/label/cuda-11.6.0" cuda-toolkit
conda install pytorch==1.12.1 torchvision==0.13.1 cudatoolkit=11.6 -c pytorch -c conda-forge
pip install -r requirements.txt

# Docker 方式(推荐生产环境)
docker pull nkeetha/splatam:v1
bash bash_scripts/start_docker.bash

3.2 推理参数选型建议

场景 desired_image_width tracking_iters mapping_iters keyframe_every 预期帧率
🔬 高精度离线 1200 40 60 5 ~2 fps
🏠 室内实时 600 20 30 3 ~10 fps
🚗 大场景 900 30 40 5 ~5 fps
📱 iPhone 在线 600 20 30 3 ~8 fps

3.3 在线 iPhone 演示

SplaTAM 支持用 NeRFCapture App 实时建图:

# 1. 启动在线 demo(确保 iPhone 和 PC 在同一 WiFi)
bash bash_scripts/online_demo.bash configs/iphone/online_demo.py

# 2. 在 iPhone 上打开 NeRFCapture,持续点击 Send
# 3. 停止后自动弹出交互式 3D 重建窗口

3.4 常见问题与调参建议

问题 可能原因 建议调整
轨迹漂移严重 Tracking 迭代不足 增大 tracking_iters 至 60+
场景有"空洞" Densification 不够激进 降低 sil_thres 至 0.3
显存溢出 高斯数量爆炸 增大 prune_every,降低 grad_thresh
渲染模糊 Mapping 迭代不足 增大 mapping_iters 至 100+
快速运动丢帧 恒速先验失效 启用 forward_prop=True + 增大 mapping_window_size

四、🌐 应用领域与前景展望

19fdb48ec6d17.png

4.1 当前可直接落地的场景

领域 应用方式 SplaTAM 优势 成熟度
🤖 机器人导航 实时构建 3D 环境地图 稠密几何 + 实时性 ⭐⭐⭐⭐
🏠 AR 室内设计 扫描房间 → 放置虚拟家具 高质量几何 + 颜色 ⭐⭐⭐⭐
🚗 自动驾驶感知 车辆周围 3D 重建 大场景可扩展 ⭐⭐⭐
🎮 AIGC 内容生成 真实场景 → 3D 资产 PLY 直接导出 ⭐⭐⭐⭐
🏗️ 数字孪生 建筑/工厂 3D 建模 高精度 + 新视角合成 ⭐⭐⭐
📱 iPhone 3D 扫描 手机端实时重建 NeRFCapture 支持 ⭐⭐⭐⭐⭐

4.2 未来演进方向(个人观点)

  1. 🎬 视频序列扩展:当前逐帧处理,未来可引入时序一致性约束,减少帧间抖动
  1. ☁️ 大规模场景:当前受限于 GPU 显存,未来可结合分块/LOD 策略扩展到城市级
  1. 🔄 语义融合:将 SAM / Grounded-SAM 的语义分割结果融入高斯属性,实现"带标签的 3D 世界"
  1. 📉 边缘部署:模型量化 + TensorRT 优化,推向 Jetson / 手机端
  1. 🔗 与 Gaussian Splatting 生态打通:SplaTAM 建图 → 离线 3DGS 精修 → 实时渲染,形成完整 pipeline
  1. 🧠 端到端学习:当前参数全手工调优,未来可用 RL/元学习自动搜索最优策略

🖼️ 未来展望配图提示词

矢量手绘线条风格,颜色艳丽:一幅充满想象力的未来城市全景图。前景是一个戴着 XR 眼镜的人,他看到的世界是半透明的高斯点云叠加在真实场景上。中景是各种机器人(配送机器人、无人机、清洁机器人)在街道上穿行,各自带着彩色的 3D 地图光环。远景是智慧城市的大楼,表面覆盖着流动的 data stream。天空中漂浮着巨大的全息投影广告。整体色调温暖明亮,用渐变从前景的蓝绿色过渡到远景的橙粉色,营造未来感。


五、📊 与其他算法对比一览

5.1 稠密 SLAM 方法横向评测

方法 表示 Replica ATE (cm) ↓ ScanNet ATE (cm) ↓ 新视角 PSNR (dB) ↑ 实时性
ORB-SLAM3 稀疏特征点 N/A(无稠密输出) N/A N/A ✅
NICE-SLAM 分层 MLP 1.14 5.8 19.2 ❌
Point-SLAM 点 + 特征 0.52 4.2 22.1 ⚠️
Vox-Fusion 稀疏体素 0.78 5.1 20.3 ⚠️
SplaTAM 3D 高斯 0.36 3.1 24.4 ✅

📌 数据来源:SplaTAM 论文 Table 1 & 官方 README。ATE = 绝对轨迹误差,越低越好。

5.2 为什么 SplaTAM 更快?

渲染方式对比(同一场景,同分辨率):

NeRF 渲染:每条射线 64+ 次 MLP 查询 → ~50ms/帧
SDF 渲染:Marching Cubes + 光线投射 → ~30ms/帧
3DGS 渲染:GPU 栅格化(单次 forward) → ~2ms/帧  ✅

六、📝 最佳实践建议

6.1 数据准备

# 数据集目录结构(以 ScanNet 为例)
DATAROOT/scannet/scene0000_00/
├── frames/
│   ├── color/       # RGB 图像 (jpg/png)
│   ├── depth/       # 深度图 (png, 16-bit)
│   ├── intrinsic/   # 相机内参
│   └── pose/        # 相机位姿 (4×4 矩阵 txt)

6.2 精度 vs 速度权衡

# 高精度模式(离线重建)
config = dict(
    desired_image_width=1200,
    desired_image_height=680,
    tracking=dict(num_iters=60, loss_weights=dict(im=0.5, depth=1.0)),
    mapping=dict(num_iters=80, loss_weights=dict(im=0.5, depth=1.0)),
    map_every=1,           # 每帧都建图
    keyframe_every=3,      # 密集关键帧
)

# 实时模式(机器人/AR)
config = dict(
    desired_image_width=600,
    desired_image_height=340,
    tracking=dict(num_iters=20, loss_weights=dict(im=0.5, depth=1.0)),
    mapping=dict(num_iters=30, loss_weights=dict(im=0.5, depth=1.0)),
    map_every=2,           # 隔帧建图
    keyframe_every=5,      # 稀疏关键帧
)

6.3 后处理精修

SplaTAM 跑完后,可用 post_splatam_opt.py 做离线 3DGS 精修:

# Step 1: 用 SplaTAM 建图
python scripts/splatam.py configs/replica/splatam.py

# Step 2: 用 3DGS 精修(更多迭代 + densify + 全分辨率)
python scripts/post_splatam_opt.py configs/replica/post_splatam_opt.py

# Step 3: 导出 PLY 查看
python scripts/export_ply.py configs/replica/splatam.py

七、🎬 总结

SplaTAM 的核心贡献,用三句话概括: 1️⃣ 表示层面:首次证明 3D Gaussian Splatting 可以作为 SLAM 的"活地图"——显式、可微、高效。 2️⃣ 算法层面:通过 Tracking/Map/Densify 三阶段解耦 + 恒速位姿先验 + 覆盖率关键帧选择,实现了稳定、准确的在线稠密重建。 3️⃣ 工程层面:不修改栅格化器、复用 3DGS 算子、支持 PLY 导出和实时可视化,为社区提供了一个可直接落地的开源基线。

1a0194d015f74.png

📚 参考资料

  1. 论文:SplaTAM: Splat, Track & Map 3D Gaussians for Dense RGB-D SLAM (CVPR 2024)
  1. 项目主页:https://spla-tam.github.io/
  1. GitHub 仓库:https://github.com/spla-tam/SplaTAM
  1. 3D Gaussian Splatting 原版:https://github.com/graphdeco-inria/gaussian-splatting
  1. diff-gaussian-rasterization:https://github.com/nerfstudio-project/diff-gaussian-rasterization
  1. GradSLAM Datasets:https://github.com/gradslam/gradslam
  1. NeRFCapture App:https://apps.apple.com/au/app/nerfcapture/id6446518379
  1. SuperSplat 查看器:https://playcanvas.com/supersplat/editor

📝 本文档基于 SplaTAM 开源代码(CVPR 2024)编写,代码版本以官方仓库为准。部分配置参数和建议为经验值,实际使用时请根据硬件环境和场景特点调整。

一个回复

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注