Gaussian Splatting SLAM日期2026-06-21论文链接https://arxiv.org/abs/2312.06741代码仓库https://github.com/muskie82/MonoGS项目主页https://rmurai.co.uk/projects/GaussianSplattingSLAM/作者与机构Hidenobu Matsuki, Riku Murai, Paul H. J. Kelly, Andrew J. DavisonImperial College London / Dyson Robotics Lab 相关团队发表 venue / 年份CVPR 2024 Highlight一句话总结Gaussian Splatting SLAM仓库中常称 MonoGS把 3D Gaussian Splatting 从“离线重建 已知 SfM 位姿”的范式改造成可在线运行的稠密 SLAM用同一组 3D Gaussians 同时支持相机跟踪、局部建图和高质量渲染。它的工程核心不是再维护传统点云/TSDF/NeRF 隐式场而是把高斯作为唯一地图表示并通过可微光栅化把位姿和地图参数放进同一个优化闭环。工程视角这篇论文要实现什么从实现角度看系统要做的是一个 RGB 单目优先、可扩展到 RGB-D / Stereo 的在线稠密 SLAM。输入是按时间到来的图像帧以及可选深度或双目几何输出包括当前相机位姿、关键帧轨迹、持续增长和优化的 3D Gaussian 地图以及可用于可视化的 novel-view 渲染图像。运行时可拆成四类模块Tracking 前端给定上一帧位姿预测和当前 Gaussian 地图渲染当前视角最小化当前真实图像与渲染图像的 photometric / depth loss优化当前帧相机位姿。Keyframe / Mapping 管理决定当前帧是否成为关键帧维护局部窗口内关键帧集合为地图优化提供观测。Gaussian Map 更新对高斯的均值、尺度、旋转、不透明度和颜色参数做局部优化必要时新增、剪枝或重置高斯。GUI / Logging / Evaluation实时显示轨迹和渲染结果保存 checkpoint计算 ATE、渲染质量等指标。论文报告的在线速度约为数 FPS 量级仓库 README 还提到 speed-up 分支在高端 GPU 上可达到更高帧率。工程上这类系统高度依赖 CUDA 可微 rasterizer、PyTorch autograd、关键帧数量控制和显存管理。核心数据结构与状态量传统 VSLAM 中地图点常是MapPoint{position, descriptor, observations}这里的地图基本单元变成 3D Gaussian。一个面向实现的结构体可以写成structGaussian{Vec3 mu_world;// 3D 均值世界坐标Quat q_world;// 各向异性椭球旋转Vec3 log_scale;// 三轴尺度通常优化 log-space 保证正数floatopacity_logit;// alpha不透明度参数常用 sigmoid 映射Vec3 sh_dc_or_rgb;// 低阶颜色完整 3DGS 可用 SH 系数VecN sh_rest;// 可选高阶 spherical harmonicsintlast_seen_kf;intobs_count;};structFrame{intid;Image rgb;OptionalImagedepth;Mat3 K;SE3 T_cw;// world - camera 或 camera - world必须全工程统一boolis_keyframe;};structKeyframe:Frame{Image grad_mask;// 选择有信息量像素Image valid_depth_mask;// RGB-D / Stereo 时使用vectorintvisible_gaussians;};structGaussianMap{Tensor xyz;// [N,3]Tensor rotation;// [N,4]Tensor scaling;// [N,3]Tensor opacity;// [N,1]Tensor features;// [N,C]Optimizer map_optimizer;};状态量分两层相机状态当前帧T_cw或T_wc。单目场景中尺度和深度初始化是难点系统需要从几何验证、深度先验或多视角增量中稳定地图。地图状态所有 Gaussian 参数。实际代码里通常以 PyTorchnn.Parameter/ Tensor 形式批量存储而不是大量 C 对象否则 autograd 和 GPU kernel 调用会非常低效。如果要在 C/CUDA 中复写建议逻辑层保留类但优化层必须是 SOAstructure of arraysfloat* xyz, *scale, *quat, *opacity, *color便于 rasterizer coalesced memory access。算法主流程在线主循环可以抽象成下面的伪代码mapGaussianMap()keyframes[]T_prevIdentity()forframeinstream:ifnotmap.initialized:T_cw,init_gaussiansinitialize(frame,next_frame_or_depth)map.add(init_gaussians)keyframes.append(make_keyframe(frame,T_cw))continue# 1. Tracking只优化当前位姿不大幅改地图T_initmotion_model(T_prev)T_cwoptimize_pose_by_rendering(frame.rgb,frame.depth,map,T_init,K,iterstracking_iters,loss_weights{rgb:w_rgb,depth:w_depth})# 2. 判断是否关键帧ifneed_new_keyframe(frame,T_cw,keyframes,map):kfmake_keyframe(frame,T_cw)keyframes.append(kf)# 3. 用当前观测补充新高斯candidatesfind_unexplained_pixels(frame,render(map,T_cw))new_gaussiansbackproject_or_triangulate(candidates,frame,keyframes)map.add(new_gaussians)# 4. Mapping优化局部窗口内高斯和可选关键帧位姿local_windowselect_local_keyframes(keyframes)foriinrange(mapping_iters):ksample(local_window)preddifferentiable_render(map,k.T_cw,k.K)lossphotometric_loss(pred.rgb,k.rgb,maskk.mask)lossdepth_loss(pred.depth,k.depth,maskk.valid_depth)lossregularization(map)loss.backward()map.optimizer.step()prune_or_densify_if_needed(map)T_prevT_cw注意论文和官方实现的具体调度会更细例如单目初始化、几何验证、关键帧采样和 GUI 进程通信但主干就是“位姿用当前地图 render 对齐地图用关键帧 render 反向传播更新”。关键模块实现细节1. 前端跟踪rendering-based direct tracking输入当前 RGB 图、可选深度图、内参 K、上一帧位姿预测、当前 GaussianMap。输出当前帧位姿T_cw和 tracking loss / valid mask。实现步骤把位姿参数化为 Lie algebrase3增量或可优化 quaternion translation。用可微 Gaussian rasterizer 在当前位姿下渲染 RGB、深度、silhouette / alpha。构造 lossRGBL1或L1 SSIM深度有深度传感器时加|D_render - D_obs|mask只在有足够 alpha、非动态、非无效深度区域计算。只更新 pose optimizer地图参数先requires_gradFalse或不传给 optimizer。关键超参tracking 迭代次数、金字塔层数或图像下采样倍率、RGB/depth 权重、有效 alpha 阈值、鲁棒核阈值。坑点T_wc/T_cw方向极易写反。建议所有渲染接口显式命名world_to_camera。单目 photometric tracking 在纯旋转、低纹理、曝光变化时会陷入局部最小。可微 rasterizer 的 pose gradient 需要支持相机位姿反传官方 README 指向了带 pose gradient 的 rasterizer fork。2. 后端优化局部关键帧上的 differentiable mapping输入局部关键帧集合、当前 GaussianMap。输出更新后的 Gaussian 参数必要时更新关键帧位姿。工程上不应每次用所有关键帧优化全图否则显存和时间都会爆。常见策略维护滑窗最近若干关键帧 与当前视角重叠高的关键帧每次迭代随机采样一个或几个 keyframe对每个 keyframe 渲染全图或可见高斯子集用 Adam 优化 Gaussian 参数。forstepinrange(num_steps):kfrandom.choice(local_keyframes)render_pkgrasterize(map.params,kf.T_cw,kf.K,H,W)loss_rgbl1_ssim(render_pkg.rgb,kf.rgb,mask)loss_ddepth_l1(render_pkg.depth,kf.depth,valid_depth)ifhas_depthelse0lossloss_rgblambda_d*loss_dlambda_reg*reg_terms(map)optimizer.zero_grad()loss.backward()optimizer.step()复杂度主要取决于可见 Gaussian 数量、图像分辨率和 rasterizer tile 排序。实现上应尽量避免 Python 层逐点循环。3. 地图更新新增、剪枝与几何验证论文强调为了在线 SLAM需要突破原始 3DGS 对离线 SfM 位姿的依赖。代码里通常要回答两个问题哪里需要新高斯哪些高斯不可信新增高斯在当前帧中找渲染解释不好的像素例如 alpha 低、photometric residual 高、depth residual 高有深度时直接反投影单目时可由相邻关键帧几何或初始化策略给深度。几何验证检查候选高斯是否在多帧投影一致、深度顺序合理、不是漂浮噪声。剪枝删除 opacity 长期很低、尺度异常、观测次数太少或总是产生高 residual 的高斯。局部 densification类似 3DGS根据梯度和尺度把大高斯 split / clone但在线系统要更保守否则实时性和显存会失控。4. Keyframe 管理Keyframe 策略直接决定稳定性。常见触发条件与最近关键帧平移/旋转超过阈值当前视角可见地图比例低tracking loss 或 unexplained pixels 比例高距离上次关键帧已有固定帧数。局部窗口选择可用 covisibility渲染时统计哪些 keyframe 共享高斯优先保留重叠高且时间近的帧。坑点是窗口太小会遗忘太大则 mapping 卡顿。5. 初始化、重定位、失败恢复单目高斯 SLAM 的初始化比 RGB-D 难很多。一个最小实现可以先从 RGB-D 或 Replica/TUM depth 版本做起第一帧按深度反投影生成高斯再逐步加入 tracking。若必须单目建议先实现两帧特征匹配 Essential matrix 三角化得到稀疏点和相对位姿再把稀疏点膨胀为初始高斯。失败恢复方面工程上应记录tracking loss、有效像素比例、位姿增量范数、渲染 alpha 覆盖率。一旦超阈值可以回退到上一关键帧位姿、扩大迭代次数、降低分辨率、或触发基于图像检索的 relocalization。原始系统主要聚焦在线重建和跟踪生产级闭环/重定位仍需额外模块。数学模型到代码的对应关系3D Gaussian 在世界坐标中有均值mu和协方差Sigma R S S^T R^T。给定相机位姿和投影函数rasterizer 把 3D 高斯投到 2D 椭圆并按深度排序做 alpha blending。代码中你通常不手写完整 Jacobian而是依赖 CUDA rasterizer PyTorch autograd但你必须清楚变量流Gaussian params Camera pose - project / rasterize - rendered_rgb, rendered_depth, alpha - residual against observed image/depth - backward gradients - Adam updates pose or mapTracking residual 可写成r_rgb[p]I_obs[p]-I_render[p;T_cw,G]r_d[p]D_obs[p]-D_render[p;T_cw,G]losssum(mask[p]*rho(abs(r_rgb[p])))lambda_d*sum(valid[p]*rho(abs(r_d[p])))代码对应关系T_cw是优化变量时Gaussian 参数 detach地图优化时xyz/scaling/rotation/opacity/color是优化变量关键帧位姿可固定或少量联合优化rho可以先用 L1/Huber动态场景多时必须加入 mask 或鲁棒核深度监督不是必须但 RGB-D 模式显著降低初始化和尺度漂移难度。一个常见错误是把 alpha 很低的像素也纳入 photometric loss导致背景未建模区域把位姿拉偏。因此有效 mask 应结合 rendered alpha、观测深度、图像梯度和边界裁剪。关键创新点把 3D Gaussians 作为 SLAM 唯一地图表示不再同时维护稀疏点云、TSDF 或 NeRF MLPtracking 和 mapping 都通过同一 GaussianMap 完成。基于 3DGS 的直接相机跟踪通过可微渲染对当前相机位姿做 photometric alignment使原本依赖 SfM pose 的 3DGS 能在线闭环运行。面向单目在线建图的几何验证与地图管理解决新高斯插入、错误高斯抑制和漂浮物问题属于从离线 3DGS 到 SLAM 的关键工程改造。RGB-D / Stereo 可扩展性同一框架可用深度观测增强 residual 和初始化使工程复现可以先从有深度版本开始。实时交互式稠密渲染能力地图天然可渲染方便可视化、调试和下游 AR/机器人任务。实验与结果论文在多种室内 SLAM / novel-view synthesis 场景中验证包括 TUM RGB-D、Replica 等常见数据集并与传统 SLAM、NeRF-SLAM 或其他稠密重建方法比较。指标通常包括轨迹精度ATE / RPE渲染质量PSNR、SSIM、LPIPS运行效率tracking / mapping FPS、显存占用地图质量重建完整性和视觉伪影。原文表格中给出了具体数值本文不复述具体数值以免脱离论文版本产生误差。主要结论是该方法在保持在线运行的同时能获得比许多传统稠密 SLAM 更高质量的可渲染地图并展示了单目 3DGS SLAM 的可行性。复现路线从零写一个最小版本建议不要一上来复现完整单目 MonoGS而按以下 MVP 递进阶段 0环境和数据Ubuntu CUDA GPUWindows 上建议 WSL2 或 Linux 服务器。PyTorch、CUDA extension、diff-gaussian-rasterization-w-pose。数据集先选 Replica 或 TUM RGB-D保证有内参、时间戳和深度。阶段 1离线单帧 Gaussian 初始化读取 RGB-D 第一帧按深度反投影成点云每个采样点生成一个小 Gaussian用固定相机位姿渲染回原视角确认颜色和深度大致正确。验证日志Gaussian 数量、alpha 覆盖率、render FPS、rendered depth min/max。阶段 2只做 tracking固定地图读取下一帧优化se3位姿增量使渲染图对齐观测图与数据集 GT 比较相对位姿误差。最小 tracking optimizerxitorch.zeros(6,requires_gradTrue,devicecuda)opttorch.optim.Adam([xi],lr1e-3)foritinrange(50):Texp_se3(xi) T_init predrender(gaussians.detach(),T,K)lossmasked_l1(pred.rgb,image,pred.alpha0.5)opt.zero_grad();loss.backward();opt.step()阶段 3关键帧 mapping每隔固定帧数插入 keyframe对局部 keyframe 优化 Gaussian 颜色、opacity、scale、xyz加入 opacity pruning避免地图无限增长。阶段 4新增高斯对alpha threshold或 depth residual 大的像素反投影限制每帧新增数量例如随机采样 1k-5k 点对新高斯设置较小初始尺度和 opacity。阶段 5单目化用两帧初始化或预训练深度估计提供初始深度引入尺度一致性检查增加关键帧间几何验证。代码阅读指南官方仓库https://github.com/muskie82/MonoGS建议阅读顺序README.md安装、数据下载、运行 demo确认使用的是 CVPR 2024 对应主分支还是 speed-up 分支。slam.py通常是系统入口先看配置解析、进程/线程启动、主循环调度。configs/查看 mono、rgbd、stereo 不同模式的 tracking/mapping 迭代次数、学习率、关键帧阈值。gaussian_splatting/理解 GaussianModel、render 调用、optimizer 参数组。utils/通常包含相机、loss、数据集 reader、评估工具。gui/可最后看主要用于可视化不是算法主干。submodule 中的diff-gaussian-rasterization-w-pose如果 tracking 梯度异常必须深入看这里的 forward/backward 和相机 pose gradient。阅读时建议先跑gitclone https://github.com/muskie82/MonoGS.git--recursivecdMonoGS condaenvcreate-fenvironment.yml conda activate MonoGSbashscripts/download_tum.sh python slam.py--configconfigs/mono/tum/fr3_office.yaml若只是学习算法可以先在配置中降低分辨率、减少迭代次数并打开更多 loss / timing 日志。工程调参与踩坑CUDA 扩展编译PyTorch、CUDA、gcc 版本不匹配会导致 rasterizer 编译失败先严格按 README 推荐版本。位姿梯度不可用普通 3DGS rasterizer 不一定支持 camera pose gradient需要仓库指定 fork。显存增长新增高斯无上限会迅速 OOM必须有 pruning、keyframe window 和最大新增点数。尺度漂移单目模式下深度初始化和尺度约束不足会导致地图整体膨胀或收缩。曝光变化纯 RGB loss 对自动曝光敏感可加入 affine brightness correction 或更鲁棒的颜色归一化。动态物体人和移动物体会被写进高斯地图导致 tracking 偏移工程部署要接语义/运动 mask。低纹理区域photometric gradient 弱pose 优化不稳定可提高几何项权重或依赖 IMU/深度。关键帧太密mapping 变慢、重复高斯多太稀则新增区域少、跟踪容易丢。坐标系混乱OpenGL / OpenCV 相机坐标、列主序/行主序、T_wc/T_cw要统一写单元测试。实时性Python 主循环、GUI、rasterizer、optimizer 都可能成为瓶颈要记录 per-frame tracking time、mapping time、Gaussian count。局限性与改进方向闭环能力有限与 ORB-SLAM3 / DROID-SLAM 等相比生产级 place recognition、loop closure、global BA 仍需增强。单目初始化脆弱强依赖早期视差和场景纹理加入 IMU 或 learned depth 会更稳。动态场景处理不足需要语义分割、运动一致性或可变对象层表示。大场景扩展性全局 Gaussian 数量巨大时需 submap、空间哈希、LOD 或 out-of-core 管理。优化稳定性3DGS 参数多且耦合强学习率、densification、opacity reset 过激都会导致发散。机器人部署若要上车/上机需要时间同步、滚快门处理、在线标定、IMU/轮速融合和确定性实时调度。延伸阅读3D Gaussian Splatting for Real-Time Radiance Field RenderingKerbl et al., SIGGRAPH 2023理解 Gaussian 表示和 rasterizer 的基础。DROID-SLAMTeed and Deng, NeurIPS 2021学习 dense correspondence recurrent update 的高精度视觉 SLAM。NICE-SLAMZhu et al., CVPR 2022代表性 NeRF/隐式场 RGB-D SLAM可与 Gaussian SLAM 对比地图表示。SplaTAMKeetha et al., 2023/2024另一条 3DGS SLAM 路线适合理解 RGB-D Gaussian tracking/mapping。ORB-SLAM3Campos et al., T-RO 2021工程化 SLAM 系统的多地图、重定位、回环和 BA 设计参考。