篇目 73 · 单篇论文精读

一段单目视频在一座城市里开出去十几公里:地图要按需取用才省,回环之后还得能整体扳回来

这一篇要解决的是只用一段单目视频、把一座城市走十几公里这件事。室内那套高斯泼溅 SLAM 之所以能跑,靠的是场景小、边界已知;一到室外,两笔账同时找上门。第一笔是地图要多大:NeRF 那一类表示常常要预先框死场景边界,稠密体素网格又是立方复杂度,几千立方米以上就铺不开;显式高斯不设边界,但体量随场景线性涨,长序列下显存与算力一起崩。第二笔更麻烦:漂了怎么扳回来。室外长序列必然累积漂移,检测出一个回环之后,要动的是整张地图,而不是几个位姿;而既有的增量式梯度配准只适合「一帧一帧往前推」。前人两条路各撞一头:DROID-SLAM 那条链把 SLAM 做成全可微的联合优化,但因子图靠光流建边,室外长序列上共视矩阵退化成「每帧只连最近四五个邻居」,优化窗口被压得极小;MonoGS 那条链把 3DGS 的实时渲染搬进 SLAM,代价是跟踪直接由渲染损失驱动,位姿与渲染互为因果,室外尺度下这个正反馈环会自激。本篇换的是地图的组织方式:用层次稀疏体素当骨架,每个体素由一个小网络解码出 k 个高斯,并按相机距离分配细节层级(LoD),近处细、远处粗,于是「一帧要加载上亿个高斯」这件事从源头被掐掉;前端把尺度交给度量深度模型、把位姿交给几何(对极几何 + PnP + GRIC),后端补上 BoW 回环与 Sim(3) 优化,并为高斯地图专门设计了一套分批的整图刚体更新(省显存)。账面:KITTI 十一个序列的平均 ATE 从 16.440 m 压到 15.576 m,渲染侧 PSNR 24.22 dB / SSIM 0.95,显存从 22.46 GiB 压到 8.62 GiB。代价照写:回环在纹理稀薄处会漏、LoD 阈值靠手调、动态场景不支持。

Kai Deng、Yigong Zhang、Jian Yang、Jin Xie(南开大学,天津;南京大学苏州校区) arXiv:2503.08071v2 [cs.RO] · 2025-06-10(v1 2025-03-11)· 未标注会议或期刊 —— 纯预印本(源码用的是 ICCV 2025 投稿模板,但那只是模板,不是出处) 20 页(主文 p1–p10 + 参考文献 p10–p12 + 补充材料 p13–p20)· Letter 612.0×792.0 pt · 双栏 · 文字层 74,013 字符 原文有 32 条编号式(主文 (1)–(14) + 补充 (B.1)–(B.5) 与 (C.1)–(C.13),全部落块并逐步重推)· 原文图 14 张 · 原文表 6 张 · 伪码轨 0 块 · 许可:CC BY 4.0(PDF 内无权利块 + arXiv 摘要页同向),托管原文 PDF
14 章一级章节(按拆解点切)
32 式原文编号式三十二条(主文 14 + 补充 18,逐步重推)
20 图元原文 14 图 + 6 表(E 19 + S 1,自绘 0)
6 条边界与反例(两条局限 + 三处架构前提 + 一条伪真值口径)
图元-段配对表 14 图 + 6 表 = 20 件图元 · E 类 19 + S 类 1 · 自绘 0
图元原文角色档归属支撑的论断讲解层次状态
图 1-1Fig. 1E第 1 章teaser:多公里级室外序列上的位姿精度与渲染保真度①②图注 +③④正文原样引用 · 未修改
图 4-1Fig. 2S第 4 章总览:单目 RGB → 层次稀疏体素 → 大尺度室外地图①②图注 +③④正文原样引用 · 未修改
图 3-1Fig. A.1E第 3 章DROID-SLAM 在 KITTI/KITTI 360/Replica 上的共视矩阵对照①②图注 +③④正文原样引用 · 未修改
图 3-2Fig. A.2E第 3 章MonoGS 在 KITTI Seq. 00 上的逐步崩坏①②图注 +③④正文原样引用 · 未修改
图 7-1Fig. 3E第 7 章LoD 的效率与有效性:(左) 体素细化对近处的收益递减 (右) 长序列里的「撞车」①②图注 +③④正文原样引用 · 未修改
图 11-1Table 1E第 11 章KITTI 十一个序列上的 ATE RMSE,含 LC 开关与全部基线①②图注 +③④正文原样引用 · 未修改
图 11-2Fig. 4E第 11 章KITTI 06 序列上的渲染与几何质量(全局视图)①②图注 +③④正文原样引用 · 未修改
图 11-3Fig. 7E第 11 章(左) 各方法的轨迹估计对照 (右) 局部细节①②图注 +③④正文原样引用 · 未修改
图 12-1Table 2E第 12 章KITTI 360 与 4 Seasons 上的 ATE(含 OOM 标注)①②图注 +③④正文原样引用 · 未修改
图 12-2Fig. 8E第 12 章(左) KITTI 360 上的轨迹 (右) DROID SLAM 的失效对照①②图注 +③④正文原样引用 · 未修改
图 12-3Fig. C.1E第 12 章KITTI 数据集的相机轨迹可视化①②图注 +③④正文原样引用 · 未修改
图 12-4Fig. C.2E第 12 章KITTI 360 数据集的相机轨迹可视化①②图注 +③④正文原样引用 · 未修改
图 13-1Table 3E第 13 章KITTI 上的渲染性能(三个方法 × 三个指标)①②图注 +③④正文原样引用 · 未修改
图 13-2Table 4E第 13 章部件消融五行(MonoGS → +UniDepth → +LoD → ±LC)①②图注 +③④正文原样引用 · 未修改
图 13-3Table D.1E第 13 章各方法的平移与旋转漂移①②图注 +③④正文原样引用 · 未修改
图 13-4Table 5E第 13 章LoD 层数扫描五行(体素尺寸/距离分割/体素数/PSNR/显存)①②图注 +③④正文原样引用 · 未修改
图 13-5Fig. 5E第 13 章渲染效率对照,重点是 active 3D Gaussian ratio 的尖峰①②图注 +③④正文原样引用 · 未修改
图 13-6Fig. 6E第 13 章KITTI 上 MonoGS/Splat-SLAM/Ours 的渲染结果①②图注 +③④正文原样引用 · 未修改
图 13-7Fig. C.3E第 13 章KITTI Seq. 00–06 的渲染结果①②图注 +③④正文原样引用 · 未修改
图 13-8Fig. C.4E第 13 章KITTI Seq. 07–10 的渲染结果①②图注 +③④正文原样引用 · 未修改
角色档:本篇 20 件图元(14 图 + 6 表)登记为 E 类 19 件 + S 类 1 件。S 类只有 图 4-1(原文 Fig. 2,方法总览管道) 一件机制示意图;其余 19 件(12 张定性/定量图 + 6 张定量表 + 1 张补充消融表)承载可核对的读数或不可复现的原始输出。按分区裁决 E 类禁止自绘;S 类虽可自绘,但原文这张总览图本身即证据,重画反而失真,故本篇一律引用原图,自绘 0 张,与篇目 68/71/72 的处置一致。
式:原文有 32 条编号式(主文 (1)–(14) + 补充 (B.1)–(B.5) 与 (C.1)–(C.13)),本篇全部落块并逐步重推:(1)–(2) 在第 5 章(投影与合成的两份产物)、(3)–(4) 在第 6 章(解码与均值)、(5)–(6) 在第 7 章(体素化与 LoD 掩码)、(7)–(11) 在第 8 章(四条损失与异或哈希)、(B.1)–(B.5) 在第 9 章(对极几何、PnP 与 GRIC)、(12)–(14) 与 (C.1)–(C.13) 在第 10 章(回环的残差、Sim(3) 目标与整图刚体更新);未编号式 0 条。
无伪码轨:原文 Algorithm/ALGORITHM/Require: 0 命中,本篇是分区里少见的「零伪码」篇目。
许可:CC BY 4.0。所据 PDF 内没有任何权利块 —— Copyright/©/Permission/Creative Commons/CC BY/nonacm/All rights reserved/Not for redistribution/ISBN/ACM/DOI 全部 0 命中(IEEE 的 38 处全在参考文献里),首页只有 arXiv 戳、标题、作者与摘要;arXiv 摘要页的许可图标同向指向 creativecommons.org/licenses/by/4.0/。两处证据同向 ⇒ 取 CC BY 4.0,落点三件(index.html + 封面缩略图 + 托管原文 paper.pdf),卡片 chip 不带 warn;图件原样零加工引用 + 逐图四字段署名(图号/页码/版权/未修改)。这是本分区「PDF 内无权利块 + abs 页判 CC」型的第三例(前两例:篇目 60、68)—— 与篇目 70/71 同型却判了相反方向,所以这一型必须逐篇看。
三处必须自己核的取证事实:① 式 (5) 的两个定界符是下取整:导出的嵌入 Type1 字体 /Encoding 里,字形名直接是 floorleftbigg/floorrightbigg(同处外括号是 braceleftbigg/bracerightbigg);arXiv e-print 源码同向印证(\left\lfloor \right\rfloor)—— 判形因此从「肉眼」变成「读名字」;② 图的注在体下、表的注也在体下(六张表无一例外:注顶到末横线 7.2/8.96/11.1/7.2/11.1/50.2 pt)—— 阶段 1 凭 CVPR 体例经验预判的「注在上」是错的,两条轨道的扫描方向因此都改成「从注文向上」;③ 补充材料的图注是「居中短注」(宽 159–366 pt),而图体是通栏网格图 ⇒ 通栏判据必须补一条「注文中心落在页面中心 ±32 pt 且宽 ≥ 150 pt」。
另需记的:20 件纵横比 0.806–6.339;图 C.3(0.806)与图 C.4(0.992)虽纵横比 < 1,但框宽各占原文版心的 106.2%/100.7%,按 wide 落位(不走竖图限高容器),全篇 0 件 tall。所有图件的裁切都保证框内只含图内标签、不含正文或图注。本篇的逐格读数全部取自 Table 1–5 与 Table D.1 的逐格重建(tables-text.txt),没有从正文的叙述里抄数;32 条式的表达式以 arXiv e-print 的 LaTeX 源为权威底本。
原文摘要 Abstract, p.1(英文原样引用 · 照录自 arXiv 摘要页 · 原文未分小节)

Tracking and mapping in large-scale, unbounded outdoor environments using only monocular RGB input presents substantial challenges for existing SLAM systems. Traditional Neural Radiance Fields (NeRF) and 3D Gaussian Splatting (3DGS) SLAM methods are typically limited to small, bounded indoor settings. To overcome these challenges, we introduce GigaSLAM, the first RGB NeRF / 3DGS-based SLAM framework for kilometer-scale outdoor environments, as demonstrated on the KITTI, KITTI 360, 4 Seasons and A2D2 datasets. Our approach employs a hierarchical sparse voxel map representation, where Gaussians are decoded by neural networks at multiple levels of detail. This design enables efficient, scalable mapping and high-fidelity viewpoint rendering across expansive, unbounded scenes. For front-end tracking, GigaSLAM utilizes a metric depth model combined with epipolar geometry and PnP algorithms to accurately estimate poses, while incorporating a Bag-of-Words-based loop closure mechanism to maintain robust alignment over long trajectories. Consequently, GigaSLAM delivers high-precision tracking and visually faithful rendering on urban outdoor benchmarks, establishing a robust SLAM solution for large-scale, long-term scenarios, and significantly extending the applicability of Gaussian Splatting SLAM systems to unbounded outdoor environments.

这一篇要讲清的 14 件事
  • 一段单目视频要同时回答「我在哪」和「这里长什么样」,为什么这件事在室外长序列上会变成两笔互相拉扯的账。
  • 前人三条路(传统 SLAM / NeRF 系 / 3DGS 系)各自卡在哪一格。
  • 长序列上真正会塌的两样东西:共视矩阵退化成只连近邻,以及地图自己和自己撞车。
  • 地图骨架怎么搭:体素当锚点、一个小网络解码出 k 个高斯,以及一条投影式的账(式 (1) 与式 (2))。
  • 细节层级(LoD):近处细、远处粗,它同时解决「远处高斯贡献小却占算力」和「前后视角的高斯互相重叠」两个毛病(式 (5) 与式 (6))。
  • 地图怎么长:渲染损失、深度平滑、各向同性正则三条损失,以及它们的总账(式 (7)–(10))。
  • 地图怎么不重复长:一次异或哈希把重复体素在常数时间内去掉(式 (11))。
  • 前端凭什么定得住尺度:度量深度模型 + 对极几何 + PnP + GRIC(补充式 (B.1)–(B.5))。
  • 回环之后要动的是整张地图,而不是几个位姿,以及这件事为什么要分批做(式 (13) 与式 (14))。
  • 回环修正的完整推导链:从残差定义到列文伯格阻尼,13 条式一步不缺(补充式 (C.1)–(C.13))。
  • KITTI 上到底赢多少:平均 ATE 15.576 m,以及它为什么能赢过 13 个基线(图 11-1)。
  • 换两个数据集之后结论是否还成立:5 个序列 OOM 的 DROID-SLAM 说明了什么(图 12-1)。
  • 渲染性能与消融:LoD 值多少、深度先验值多少、回环值多少,以及层数取几层最划算(图 13-1–13-4)。
  • 代价与边界:手调的阈值、会漏检的回环、泛化到未见场景时的脆弱(补充 §E)。

1只给一段单目视频,车沿着路开出去几公里

1.1 这件事的难处不在「算得准」,在两笔账会互相抢

把一台车装上一个摄像头,让它沿着城市道路开出去十几公里:这件事听起来像是「把已经在室内做成的 SLAM 放大一点」,但它不是量的差别。

难的根源是这件事要同时交两份作业。第一份是位姿:车在每个时刻在哪里、朝向哪里,这件事必须准,否则后面所有东西都建在流沙上。第二份是地图:这段路长什么样,而且要求不只是「存下来」,原文要的是「能从任意视角重新渲染出画面」,也就是地图既是定位的参照物,又是一个可查询的辐射场。这两份作业在系统里是互相喂养的:位姿错一点,地图就糊一点;地图糊一点,下一帧的位姿就更难估。在室内、在短序列上,这个正反馈来不及自激就结束了;在室外长序列上,它有足够的时间把系统推垮。

于是「把室内方案放大」会撞上两笔性质不同的账,而它们要的东西正好相反。

账一是「地图该多大」,它要的是省。原文把这条账拆成两种表示各说了一遍:隐式表示(NeRF 那一类) 的问题在两头,一是它常常要预先框死场景边界,而室外的边界是定义不出来的;二是它常用的稠密体素网格是立方复杂度 O(n³),场景边长翻一倍、内存翻八倍,跑到几千立方米以上就不可付。显式表示(高斯泼溅那一类) 的问题换了个方向:它不设边界,但体量随场景一起长大,车往前开,高斯就一茬一茬地加,长序列下内存与算力是线性膨胀的。一句话:一个被边界卡住,一个被体量拖住[§1, p1]。

账二是「漂了怎么扳回来」,它要的是能动全图。室外长序列上累积漂移是必然的,检测出一个回环之后,要修的从来是整张地图的坐标系,不是「那两帧的位姿」,因为两段轨迹之间的所有位姿和高斯都得跟着挪。而既有的 NeRF/3DGS SLAM 用的是增量式的梯度配准,它的天性是「一帧一帧往前推」。原文对这条账的措辞很直白:这类方法依赖增量的梯度配准,不适合大尺度下的全局对齐,所以它们被限制在小尺度、有界的室内环境或短期室外场景上,而且常常要靠 RGB-D 数据才能稳健对齐[§1, p1]。

这两笔账的关系是本篇的题眼:要想省,就得让地图有层级、能按需取;要想能扳回全图,就得让地图有一个「可以被整体刚体变换」的骨架。而这恰好指向同一个东西,把高斯挂在一个稀疏的、分层的体素骨架上,而不是让高斯自己满地长。

1.2 账面:赢在哪、代价是什么

先看一张实拍的对照。

图 1-1:多公里级室外序列上:位姿要准,画面也要像(E 类 · 证据)· 原文 Fig. 1, p1
图 1-1 多公里级室外序列上:位姿要准,画面也要像(E 类 · 证据)· 原文 Fig. 1, p1 怎么读 ①图注:原文这张 teaser 要说明的是「在无界、多公里尺度的室外序列上,本篇同时保住了位姿估计与建图的精度,也保住了渲染保真度」[Fig. 1 图注, p1]。图上给了三处标注,每处一行 PSNR/SSIM/LPIPS:Render Image # 2474 是 PSNR 23.91 dB、SSIM 0.9464、LPIPS 0.3064;# 8501 是 24.95 dB、0.9638、0.2571;# 11638 是 24.69 dB、0.9558、0.2839。另有 Loop Closure 与 RTE: 0.12% 两处标注。 ②读法:这张图要看的是「两件事同时成立」,而不是某一处的画面细节。先看三行数字:它们在 23.9–25.0 dB 之间,说明渲染质量是稳定的;再看 RTE: 0.12%,相对轨迹误差的百分数,这个量级说明位姿也没有飘。把这两组数放在同一张 teaser 上,才是这张图的用法:单看画质,任何一张漂亮渲染都能做到;单看位姿,传统 SLAM 也能做到;要同时做到,才是本篇主张的那个联合。另外注意 Render Image # 后面的编号,那是序列里的帧号,从 2474 到 11638 意味着这条序列至少有一万一千多帧,这是「长序列」三个字的直接注脚。 来源:GigaSLAM: Large-Scale Monocular SLAM with Hierarchical Gaussian Splats, Fig. 1, p1 · arXiv:2503.08071v2(CC BY 4.0,© 2025 Kai Deng, Yigong Zhang, Jian Yang, Jin Xie) · 原样引用,未修改

③复算:这三行数字的横向比较要小心。# 8501 那一行看起来最好(PSNR 最高 24.95、SSIM 最高 0.9638、LPIPS 最低 0.2571),# 2474 最差(23.91 / 0.9464 / 0.3064)。三者的极差只有 1.04 dB,在这三段被挑出来展示的画面上,质量差异不到 5%。但这里必须说清一件事:这三行数字是「同一套方法在三个时刻的自比」,不是「与别人的比较」。它证明的是稳定性(长序列跑到一万多帧仍然没有塌),不证明「比谁好」。真正和基线比的那张账在后面的图 11-1 与图 13-1:图 11-1 比的是位姿(ATE),图 13-1 比的是渲染(PSNR/SSIM/LPIPS),两者都不在这张 teaser 上。

④边界:这张图只说明「同一场景、不同时刻、质量稳定」,它不说明任何关于「泛化」的事。三处渲染取自同一条序列,因此「换一条序列、换一座城市还成不成立」在图上是看不出来的,那要等第 12 章的图 12-1。另一个不在图上的前提是「尺度从哪来」:单目视频本身没有尺度,本篇所有以米为单位的读数(ATE 15.576 m、RTE 0.12%)都建立在外部度量深度模型给出的尺度之上(第 9 章会讲这条链),模型一换、尺度基准就换。这个前提在第 14 章会被再次提起,因为它是本篇不可迁移的那一部分。

账面是可以背下来的:KITTI 十一个序列的平均 ATE 从 16.440 m 压到 15.576 m,而两个最强的 3DGS 系基线,MonoGS 在六个序列上直接失败(failed)、Splat-SLAM 在五个序列上失败,两者都算不出平均值[表 1, p7];换到 KITTI 360 与 4 Seasons,本篇平均 47.107 m,而 DROID-SLAM 有五个序列直接 OOM[表 2, p9];渲染侧 PSNR 24.22 dB / SSIM 0.95,同时显存从 22.46 GiB 降到 8.62 GiB[表 3, p9;表 5, p10]。

代价也照写:回环检测用的是 DBoW 图像检索,纹理稀薄处会漏(原文自己在补充材料里承认过这一点);LoD 的体素尺寸与距离阈值是手调的 [表 5 第一列];动态场景目前不支持[补充 §E, p17]。这三条分别落在第 10、13、14 章。

2前人三条路,各自在哪一格上失灵

前人走过的路,按「地图怎么表示、位姿怎么求」这两件事的组合一摆,正好是三档。原文的相关工作只分了三小节,而三档各自的失灵点落在不同的格子上。

2.1 第一档:几何做后端,机器学习做前端

这一档是传统 SLAM(ORB-SLAM 那一系)。它的分工很清楚:前端从图像里抽特征点、做匹配,后端用光束法平差(BA)之类的几何优化去解位姿与地图点。原文把这一档的目标写成两句:追求准确的相机位姿跟踪,以及高质量的地图几何[§2, p2]。

它的强项是「硬」:几何约束是显式的,误差有明确的物理含义,回环与全局一致有成熟的做法。它的弱项是「薄」:地图里存的是一堆点或面片,只能用来定位与量距,不能用来渲染,从任意视角「看」这段路长什么样,这一档给不出来。

这一档在新问题上的失灵点是「地图的表达力」。本篇要的地图不只是几何,还要外观(能从任意视角渲染),而点云地图里没有外观这个概念。所以这一档被本篇当前端的一部分借走,不是被取代:本篇的跟踪模块正是从 DF-VO 这一支来的(对极几何 + PnP),只是把「尺度从哪来」换成了学习出来的度量深度(第 9 章)。

2.2 第二档:把地图换成可微的辐射场,但被边界框住

这一档是 NeRF 系的 SLAM(NICE-SLAM、GO-SLAM 等)。它换的是地图的表示:不再存点,而是存一个连续的可微辐射场,于是渲染这件事直接被写进了优化目标,位姿可以「通过让渲染结果与真图对齐」来求。原文对它的评价点在了要害上:这类方法把 SLAM 重新组织成「位姿与地图的联合优化」,因此能给出丰富的表观编码与自由视角渲染[§2, p2]。

它的失灵点有两层。第一层是「要预先框边界」:NeRF 的采样与积分通常建立在预先定义的场景包围盒之上,而室外环境的边界是定义不出来的(原文用的词是「动态的尺度与未定义的边界」)。第二层是「体积复杂度是立方的」:稠密体素网格 O(n³),场景一大就付不起[§1, p1]。

这一层失灵不是工程细节,它是表示本身的形状问题。要覆盖一条十几公里的路,你得先知道「十几公里」这个数;而 SLAM 的整段前提恰恰是「我事先不知道我在哪、要开多远」。原文在相关工作里把这句话写得更直接:NeRF 系系统一般需要预定义的场景边界,因此难以扩展到无界的室外环境[§2, p2]。

2.3 第三档:把地图换成显式高斯,但被「位姿靠渲染」反噬

这一档是 3DGS 系的 SLAM(MonoGS、Splat-SLAM 等)。它换的是「地图既显式又可微」:高斯的表示是显式的一堆椭球,渲染却是可微的、还很快。原文承认这一档的吸引人之处:高斯的表示能高效地渲染出平滑、连续可导的场景,因此只用单目 RGB 就能做到高保真的实时建图与跟踪[§2, p3]。

它的失灵点藏在「跟踪和渲染是同一件事」里。MonoGS 的位姿是由最小化渲染损失估出来的,要估得准,先得渲得像。在室内这没问题:场景小、结构简单、相机动得慢,3DGS 很快收敛,渲染早就「像」了。在室外长序列上这条链会反过来咬人:场景大、几何复杂,3DGS 的收敛明显变慢,于是跟踪常常是在一张「收敛到一半、或者根本不准」的地图上做的;位姿因此带误差,误差累积之后远处高斯的深度更不准,下一帧的跟踪更难,原文把这条称作一个反馈环:位姿不准拉坏地图,地图拉坏位姿,长序列上这个环最终把整个系统推垮[§2, p3]。

这一档还有一处「规模上的」失灵:高斯的数量随场景线性增长,车开得越远,一张帧要处理的高斯越多。原文点出了一条姊妹工作的上限作为对照:把 3R 重建(DUSt3R 那一类)与 3DGS 接起来的做法在百米级的室外短序列上能跑,但它的 Transformer 设计带来 O(n²) 的自注意力内存开销,因此扩不到公里级轨迹;并给了一句很重的判断,在此之前,没有任何方法在超过公里级空间尺度的序列上展示过稳健的性能[§1, p1]。

2.4 三档并排放在一起看

把三档的失灵点并排,本篇的位置就出来了。

档地图表示位姿怎么来失灵点换掉它与本项目的关系
传统 SLAM点/面片几何 BA地图没有外观,渲不出来本篇的前端几何从这一支借来(对极几何 + PnP)
NeRF 系隐式辐射场渲染损失(可微)要预先框边界 + O(n³) 网格本篇把「渲染可微」留下,把「隐式表示」换掉
3DGS 系显式高斯渲染损失(可微)位姿与渲染互为因果+体量随场景线性涨本篇把「显式高斯」留下,把「位姿靠渲染」这条依赖切断

这张表里最该带走的一行是第三档的失灵点:本篇最关键的改动是把「位姿怎么求」从渲染损失里挪出去,不是「把高斯组织得更好」,位姿改由几何(对极几何 + PnP + 度量深度)来定,渲染只负责建图与出图。这一步一挪,那个正反馈环就断了;剩下的问题只剩「地图怎么组织才省」,而那才是层次体素要解的题。

这个定位也解释了后面章节的顺序:第 3 章先讲「长序列上到底会塌哪两样」,第 4 章给总览,第 5–8 章都在讲地图怎么组织,前端的位姿被放到第 9 章单独讲,因为它是那个「切断」动作。

3长序列上真正会塌的是两样东西

3.1 共视矩阵:从「一张网」退化成「一条链」

第一样塌掉的东西在 DROID-SLAM 那条链上,而且塌的方式很具体:它的因子图变稀了。

把 DROID-SLAM 的做法压缩成一句话:它把 SLAM 重新写成位姿与地图的联合优化,用稠密光流在关键帧之间建立对应,再在因子图上做稠密光束法平差(DBA)去精修位姿。这套设计在室内有奇效,后来 GO-SLAM、NeRF-SLAM、Splat-SLAM 都建在它上面[补充 §A.1, p13]。

问题出在「边是靠光流建的」这件事上。光流只对画面重叠足够多的两帧之间有效;室外长序列上,相邻帧当然重叠,但隔得远的两帧几乎不重叠,于是因子图里几乎只剩「每帧连到它最近的四五个邻居」这种边。原文用的词是「共视矩阵在室外序列上边更少」,后果是「DBA 的优化窗口显著变小」[补充 §A.1, p13]。

优化窗口小为什么致命,值得多想一步:BA 的威力来自把很多帧的位姿联立起来一起解,联立的帧越多,一路累积的尺度误差越有机会在同一个方程组里被互相抵消。窗口一小,这个抵消机制就失效了,误差只能一代一代往下传。原文把这条因果关系写得很清楚:优化窗口变小会放大尺度漂移的累积,那些本来能靠「更大的一起优化的帧窗」纠正掉的误差,就此无人处理[补充 §A.1, p13]。

这件事有一张图直接展示了对照。

图 3-1:同一套 DROID-SLAM,室内是一张密网、室外只剩一条链(E 类 · 证据)· 原文 Fig. A.1, p14
图 3-1 同一套 DROID-SLAM,室内是一张密网、室外只剩一条链(E 类 · 证据)· 原文 Fig. A.1, p14 怎么读 ①图注:这张图的上下两行是同一套共视矩阵在两类数据上的对照。上行是 Replica 的五个室内场景(Indoor Scene 与其 Room 0、Room 2、Office 2、Office 3),下行是室外场景(Outdoor Scene 与 KITTI Seq. 00、KITTI Seq. 05 等序列)。②读法:要看的是非对角线上「点」的分布形状,不是矩阵的大小。每张子图都是一个共视矩阵,行列都是帧号,格子亮表示这两帧有共视边。室内那几张,亮点是一片散开的云:第 100 帧和第 800 帧之间有边,第 200 帧和第 1500 帧之间也有边,整张网是连通的,所以 BA 可以把它们联立。室外那几张,亮点挤成一条紧贴对角线的带:只有相邻的帧互相有边,整张网退化成一条链,于是「联立」这件事在物理上没有对象可联。判别的关键在「带有多宽」:原文实测室外序列里每帧主要只连它最近的 4 到 5 个邻居,而室内的连接密度显著更高[补充 §A.1, p13]。 来源:GigaSLAM: Large-Scale Monocular SLAM with Hierarchical Gaussian Splats, Fig. A.1, p14(补充材料 §A · DROID-SLAM based Methods) · arXiv:2503.08071v2(CC BY 4.0,© 2025 Kai Deng, Yigong Zhang, Jian Yang, Jin Xie) · 原样引用,未修改

③复算:「每帧连 4 到 5 个邻居」这个数可以直接换算成窗口长度。一条只有近邻边的链,联立方程组能覆盖的帧数就约等于「带宽 × 2 + 1」,带宽 4–5 意味着一次 BA 真正联立的帧大约在 9 到 11 帧之间。把它和一个「密网」的情形比:如果每帧平均连 30 帧,联立规模就是一个数量级以上的差别。这也解释了为什么这条链上的方法在室内排名很高、到室外就掉:不是求解器变差了,是喂给求解器的方程组变小了。另外注意:这一章的所有读数都来自补充材料,不在主文里,原文把这段论证放在附录,主文只用一句话带过「依赖增量梯度配准、不适合全局对齐」[§1, p1],两处说的是同一件事,粒度不同。

④边界:这张图只说明「共视结构在两类数据上形状不同」,它不说明「DROID-SLAM 一定失败」。原文同时点了另一半原因:即便因子图很小,在公里级序列上维持它并跑 DBA,计算代价也高得离谱;而且它的回环是通过帧间共视隐式完成的,在环少、且难检测的室外反而更无效[补充 §A.1, p13]。「共视变稀」是结构原因,「代价高 + 回环隐式」是另一条独立的原因,两者叠加才构成这一档的失灵。另一个边界是「室内五张图的选取」:它们来自 Replica 的五个具体房间,不能代表「所有室内场景」。

3.2 第二样:地图自己和自己撞车

第二样塌掉的东西不在求解器里,而在地图本身,而且它有一个很朴素的名字:撞车(collision)。

场景是这样的:车开出去很长一段,绕过街角、拐回来,新的观测落在了很久以前建过的那片区域上。理想情况是「同一块地方,两段视角给出的高斯互相印证、一起收敛」;实际发生的是「两段视角各自生成了一批高斯,它们在同一块空间里互相叠加」,而它们对同一片表面的深度估计未必一致(远距离高斯尤其不准)。这一堆互相矛盾的高斯会一起参与后面的渲染与位姿估计,于是近处本来建得好好的地方被搅糊。

原文把这件事的触发条件讲得更具体:它是在长序列上、前一帧视图与后续帧视图的高斯重叠时发生的,而且对位姿跟踪有负面影响[§3.2, p4]。注意这里有一个反直觉的因果方向:一般会以为「位姿不准导致地图糊」,但在这里,地图里多出来的那批高斯会主动去干扰位姿估计,因为它参与了渲染损失的梯度。这就把第 2 章那条「互为因果的环」补上了第二个入口。

MonoGS 正是被这个环推垮的现成样本。

图 3-2:MonoGS 在 KITTI Seq. 00 上的逐步崩坏(E 类 · 证据)· 原文 Fig. A.2, p15
图 3-2 MonoGS 在 KITTI Seq. 00 上的逐步崩坏(E 类 · 证据)· 原文 Fig. A.2, p15 怎么读 ①图注:这张图跟踪的是 MonoGS 在同一条 KITTI Seq. 00 上、随着序列推进的渲染结果。原文对它的描述分三段:序列开始的时候,虽然建图质量不理想,渲染出的场景仍然可以辨认,说明 3DGS 在最前面那些帧上是够用的;随着序列推进,累积的位姿误差与建图误差让渲染画面越来越扭曲;到第二个大转弯时,MonoGS 的跟踪模块被这些误差压垮,系统彻底崩溃,这一阶段的渲染结果已经完全不可辨认[补充 §A.2, p15]。②读法:这张图要看的是「崩坏的时间线」,而不是某一格的画质。它的读法是纵向的:从上往下(或按图中排列顺序)逐格看,问的是「从哪一格开始,画面的语义断了」,断掉的那一格就是跟踪失效的时刻。注意崩坏不是渐变到零,而是有一个加速段:前段只是「不够清晰」,后段突然变成完全无法辨认。这个「突然」才是图里最有信息量的地方:它说明系统过了一个临界点,误差超过了渲染损失还能提供有效梯度的范围,反馈环从「互相拉一点」变成「互相推倒」。判别的关键在「第二个大转弯」这个措辞:拐弯意味着相机快速大幅转动,那是位姿估计最难、也最容易把误差放大的一类动作。 来源:GigaSLAM: Large-Scale Monocular SLAM with Hierarchical Gaussian Splats, Fig. A.2, p15(补充材料 §A · MonoGS) · arXiv:2503.08071v2(CC BY 4.0,© 2025 Kai Deng, Yigong Zhang, Jian Yang, Jin Xie) · 原样引用,未修改

③复算:这张图没有数字,但它的结论能在图 11-1 里被量化。原文说 MonoGS「崩溃」,图 11-1 给出的形式是:MonoGS 在 KITTI 的十一个序列里,有六个直接标 failed(Seq. 00、02、03、06、08、09、10 里的多数;表中其余格子给出的是 20.75、137.22 这类量级完全失控的数)[表 1, p7]。「崩坏」这个词在图上是定性的、在表上是定量的:failed 的六个序列 + 数值失控的其余序列 = 平均列只能写一个 /(算不出来)。同一张表里 Splat-SLAM 的情况更差一档:它的失败数更多,且给出的数值后面带 ×(原文用这个记号标注该值不可信)。这两个记号(failed 与 ×)是读懂图 11-1 的关键,第 11 章会专门讲。

④边界:这张图只说明「MonoGS 在这条序列上崩了」,它不说明「3DGS 做 SLAM 不行」。原文自己把「MonoGS 的教训」与「3DGS 的价值」分得很清:MonoGS 的贡献(解析雅可比、各向同性形状正则、资源分配策略)被本篇直接继承(本篇的第 8 章会用到它的各向同性正则),本篇只是不再让位姿依赖渲染[补充 §A.2, p15]。另一个前提是「崩溃的触发条件是尺度与几何复杂度」:室内规模小、结构简单、相机动得慢,3DGS 收敛得快,这个环来不及自激,所以这张图严格来说是在质疑「把室内方案直接放大」,不是在质疑那条技术路线本身。

3.3 两样东西合起来,就是本篇要开的两刀

第 3.1 节与第 3.2 节讲的是两件不同的事:前者是「求解器的输入变小了」,后者是「地图的输入变脏了」。但它们指向同一个处置方向:

对前者(共视变稀、窗口变小),处置是「别再依赖帧间共视去维持一致性」:必须有一个显式的回环机制,把「隔了很远的帧」直接连起来。这是第 10 章那条 Sim(3) 链要干的事。顺带一提,这一刀同时也是「为什么本篇不用 DROID-SLAM 当骨架」的答案。

对后者(地图互相撞车),处置是「让远处的高斯更粗、并且按距离筛选」。 如果远处用粗体素,那么同一块远处区域在两段视角下生成的高斯会落在同一个粗网格里,从而被合并,而不是各自留一批互相矛盾的高斯。这一刀正是第 7 章的 LoD(细节层级),原文在讲 LoD 时,明确把「撞车」列成它的第二个收益[§3.2, p4]。

把这两刀与第 2 章的三档表接起来,本篇的四条贡献也就齐了:① 一个能无界扩张的高斯 SLAM 框架;② 一个用于动态生长与 LoD 渲染的层次地图表示;③ 一套适用于高斯地图的高效回环流程;④ 一条不依赖渲染的位姿前端(最后一条在原文的贡献列表里没有单列,但它正是第 2 章那张表里被切断的那条依赖)。这四件会分别落在第 4–8 章(地图)与第 9–10 章(前后端)上。

4方法的四个部件,以及它们怎么串起来

4.1 先把整条管道摆出来

单目 RGB 帧进去,一张能渲染的大尺度室外地图出来,中间串着四个部件,原文用一张总览图把这条管道画完整了。

图 4-1:单目 RGB 进来,层次稀疏体素出去(S 类 · 机制示意)· 原文 Fig. 2, p4
图 4-1 单目 RGB 进来,层次稀疏体素出去(S 类 · 机制示意)· 原文 Fig. 2, p4 怎么读 ①图注:原文对这一张的说明是:「GigaSLAM 处理单目 RGB 输入,用一个层次的稀疏体素结构去映射大尺度室外环境;正是靠这个结构,长距离室外场景这个难题才被解掉。」[Fig. 2 图注, p4]。②读法:这张图要看的是「层次」这两个字出现在哪一段,而不是把每一根箭头都背下来。读的顺序建议是从左到右、但只看三个节点:① 输入(单目 RGB,注意不是 RGB-D、也没有相机位姿输入);② 中间那个分层的结构(这是全篇的题眼,地图是一棵「按距离分层」的体素骨架,不是一堆平铺的高斯);③ 输出(大尺度室外地图,且这份地图是可渲染的)。看懂了「中间那层是按距离分层的」,这张图的目的就达到了,它的作用是给后面第 5–8 章画出一张「我要拆哪几块」的地图,而不是讲解每块的实现。 来源:GigaSLAM: Large-Scale Monocular SLAM with Hierarchical Gaussian Splats, Fig. 2, p4 · arXiv:2503.08071v2(CC BY 4.0,© 2025 Kai Deng, Yigong Zhang, Jian Yang, Jin Xie) · 原样引用,未修改

③复算:这张图没有数字,但它把全篇的「部件数」定死了。按原文的四节结构,部件是四个:① 表示(体素 + 解码出高斯,第 5–6 章);② 建图(LoD、地图更新、地图扩张,第 7–8 章);③ 跟踪(度量深度 + 对极几何 + PnP,第 9 章);④ 回环(BoW 检测 + Sim(3) 优化 + 整图刚体更新,第 10 章)。这四个部件在本页的行文里被拆成十章,比例是 4 : 2 : 1 : 1(表示与建图占六章,跟踪与回环各一章),这个比例的由来是原文的式集中在哪里,不是篇幅偏好:32 条编号式里,表示与建图占 11 条、跟踪占 5 条、回环占 16 条(含补充材料的 13 条推导链)。「跟踪」这一部件虽然概念上最重(它承载了「切断渲染依赖」这个关键决定),公式上却最轻,因为它的做法全部借自既有工作(DF-VO + UniDepth + LightGlue),本篇自己发明的部分集中在「地图怎么组织」与「回环之后怎么改地图」两头。

④边界:这张图不承担任何「证明」的功能,它是机制示意,因此不能拿它来断言任何性能结论。另一个要留意的边界是「图上没有画的东西」:这张总览图里没有画前端跟踪模块,也没有画回环模块,它们在第 9、10 章才出现。读这类总览图时,把「图上没画什么」也当成信息:它会告诉你作者认为哪些部分是「主干」、哪些是「可替换的配件」。本篇的取舍很明确:主干是地图表示(体素 + LoD),配件是跟踪(可换成任何可靠的几何前端)与回环(可换成任何可信的检测器)。

4.2 四个部件各自解决第 3 章留下的哪一笔账

把第 3 章的两笔账与本篇的四个部件对起来看,结构就清楚了。

部件原文位置解决第 3 章的哪一笔用到哪几条式 / 哪几件图元
表示:层次稀疏体素 + 解码高斯§3.1(p3–p4)账一(地图该多大)—— 让地图按需取用式 (1)–(4)
建图:LoD + 四条损失 + 空间哈希§3.2(p4–p6)账一 + 第 3.2 节的撞车式 (5)–(11)|图 7-1
跟踪:度量深度 + 对极几何 + PnP§3.3 + 补充 §B切断「位姿靠渲染」那条依赖式 (B.1)–(B.5)
回环:BoW + Sim(3) + 整图刚体更新§3.4 + 补充 §C账二(漂了怎么扳回来)式 (12)–(14) + (C.1)–(C.13)

这张表里最值得记住的是「跟踪」那一行的最后一列与「回环」那一行的最后一列:它们分别占了 5 条与 16 条式,本页的式密度分布不是均匀的,它精确地反映了「哪一部分是本篇自己的发明」。

4.3 一句可以背下来的判断

全篇的方法可以压成一句:把高斯挂在一棵「按距离分层的稀疏体素树」上,让位姿回到几何手里,再为这棵树单独设计一套回环后的整图更新。

这句话里的三个动作对应三处最容易被忽略的取舍,先说在这里,后面各章会逐一兑现:

取舍一:地图的骨架用体素,但它自己不是地图。体素只存锚点位置、一个 32 维特征、一个缩放因子、k 个偏移量;真正的高斯是每次渲染时由小网络现算出来的(第 6 章)。这个取舍的代价是每帧要跑一次网络解码,换来的是显存能降一个档。

取舍二:LoD 是「按相机距离」而不是「按重要性」分的。距离是一个不需要学习、不需要额外存储、随时可算的量(第 7 章)。代价是它对手调的阈值敏感(第 13 章图 13-4 的消融会暴露这一点)。

取舍三:回环之后的整图更新是「分批做的刚体变换」,不是重新优化。这是一个工程上很硬的决定:它放弃了「用新位姿重新优化整张图」这种更精确的做法,换来的是在公里级体量上能真的把更新跑完(第 10 章)。

5先把 3DGS 那三笔账算清

5.1 一个高斯是五个量,一条管道是四步

3DGS 的全部开销,都从「一个高斯五个量」与「一条管道四步」这两件事里长出来,因为后面所有改动都建立在这笔账上。

一个高斯图元由五个量定义:颜色 c(三维)、尺度 s(三维)、不透明度 α(一个标量)、均值 μ(三维)、协方差 Σ。原文里把它们写成一个五元组 G = (c, s, α, μ, Σ),并给了一句关键的定位:这里的 Σ 是一个对角协方差矩阵,它表示这个高斯在三维空间里的「椭球形状与位置」[§3.1, p3]。

注意这里有一个容易被读过去的词:对角。一般化的 3DGS 允许协方差是满矩阵(用旋转 + 缩放两段来表达任意朝向的椭球)。本篇的地图表示用了对角形式,原因是本篇的高斯由体素的锚点 + 偏移量算出来,不是自由长出来的(第 6 章的式 (4)),所以「朝向」这件事被体素骨架承担了。这一处取舍在原文里没有展开论证,但它在后面的显存账里会显形(第 13 章图 13-4 的显存从 22.46 GiB 一路降到 8.62 GiB,其中一部分就来自「地图里不再需要为每个高斯存旋转」。

一条 3DGS 管道走四步:① 投影(把三维高斯投到图像平面)、② 排序(按到相机的距离,让后面的混合顺序正确)、③ 混合(alpha compositing)、④ 出图(颜色与深度)。本篇对第 ① 与第 ③ 步有改动:第 ① 步的输入被换成了「体素解码出来的高斯」(第 6 章),第 ③ 步的执行顺序被换成了「按视点重排后的子像素顺序」,后者不属于本篇(那是篇目 72 的事),本篇在第 ③ 步上保持原样。

5.2 式 (1):投影这一步要产出两样东西,而其中一样带着相机位姿

原文把投影那一步的结果写成两行[§3.1, p3]:

(1) μ_I = −π(ξ · μ), Σ_I = J R Σ R^T J^T,(原文式 1 · §3.1, p3)

逐项读:μ_I 与 Σ_I 是投影之后、图像平面上的二维高斯的均值与协方差;π(·) 是投影函数;ξ ∈ SE(3) 是相机位姿;μ 是三维均值、Σ 是三维协方差;J 是投影的雅可比;R 是相机旋转矩阵[§3.1, p3]。

这两行里有三件事值得停下来看。

第一,投影是「先转、再投」。ξ · μ 是把世界坐标里的均值乘上相机位姿(把它搬到相机坐标系里),π(·) 再把它投到像平面。那个负号(−π(ξ·μ))对应图像坐标系的 y 轴朝向,原文没有解释这个负号的来历,本页也不替原文补,只把符号照录。

第二,协方差的投影走的是「夹心」形式。J R Σ R^T J^T 这个形状是仿射变换下协方差传播的标准写法:R 是旋转、J 是投影的非线性部分在均值处的线性化,两头的转置保证结果仍然是一个半正定矩阵。它是一个近似,只在均值附近线性化成立,高斯摊得很大或者离相机很近时这个近似会走样,这是 3DGS 本身的已知特性,不是本篇引入的。

第三,也是全篇最要紧的一件:这一行里有 ξ。均值与协方差的投影都必须知道相机位姿。这就是「位姿靠渲染」那条依赖的数学出处,只要你的地图是「投影出来的高斯的集合」,那么渲染就绕不开位姿;反过来,如果你要拿渲染损失去求位姿,你就是在用「对位姿的投影」去猜位姿本身。原文在这一段末尾点明了它的另一面:这套设置保证了 3DGS 的端到端可微性[§3.1, p3]。可微是它的价值,也是它的枷锁:可微才让「用渲染损失求位姿」在数学上可行,而正是这个可行把系统带进了第 2 章那个反馈环。本篇第 9 章要做的事,就是把位姿从这一行里「请出去」。

5.3 式 (2):颜色与深度是同一个求和公式的两份产物

第二步的账是混合[§3.1, p3]:

(2) C_p = Σ_{i=1}^{|G_t|} c_i α_i Π_{j=1}^{i−1}(1 − α_j), D_p^GS = Σ_{i=1}^{|G_t|} z_i α_i Π_{j=1}^{i−1}(1 − α_j),(原文式 2 · §3.1, p3)

逐项读:C_p 是像素 p = (u, v) 处的颜色,|G_t| 是时刻 t 的高斯总数,c_i 与 α_i 是第 i 个高斯的颜色与不透明度,Π_{j=1}^{i−1}(1 − α_j) 是它前面所有高斯的「透光率」乘积(也就是到它为止还剩下多少比例的光没被挡住);D_p^GS 是同一像素处的深度,z_i 是第 i 个高斯到相机的距离[§3.1, p3]。

这个公式里有三个可以直接看出的事实。

事实一:颜色与深度共用同一套权重。把两行并排看,唯一的差别是 c_i 换成了 z_i。这是个很省的设计:混色和混深度是同一个循环里的事,不需要为深度再走一遍排序。它的代价也很直接:深度的质量完全绑在颜色那一套权重上,如果某个高斯的颜色权重算歪了(比如不透明度估计错),深度会跟着一起歪,而且你不会立刻看出来,因为出图这一步只显示颜色。这一点在第 9 章会变成一个实际的麻烦:前端要靠深度来定尺度,而深度是由建图那一套权重顺带产出的。

事实二:这个求和是「按不透明度加权的、顺序相关的」。Π(1 − α_j) 这个连乘意味着顺序不能乱,把两个高斯的先后换一下,结果会变。所以第 ② 步「按距离排序」是正确性的前提,不是可选的优化。原文对这一点的表述是「图元按到相机的距离排序,然后施加 alpha 合成」[§3.1, p3]。在长序列的大地图上,「排序」这件事的规模会随高斯总数涨,这是第 2 章「体量随场景线性长大」那条账在实现层的落点之一。

事实三:|G_t|(高斯总数)是这两个求和的上界,而这个上界在长序列上会一直长大。这一句是全篇从「表示」走向「LoD」的直接动机:求和项数越多,每帧的计算越贵;而长序列意味着 |G_t| 只增不减(除非有机制把它压下去)。第 7 章的 LoD 与第 8 章的「无界扩张 + 去重」合起来,就是为了不让引擎每帧都去遍历一个一直在长大的集合。

5.4 三笔账合起来:本篇要动的是哪一步

把 5.2 与 5.3 合起来,3DGS 的账可以写成三句:① 投影要位姿;② 混合要排序,而排序的规模随高斯总数涨;③ 高斯总数在长序列上只增不减。

三句里,本篇动了两句:

对 ③,本篇换掉了「高斯怎么存」。不再把所有高斯平铺在内存里,而是只存体素锚点 + 一个特征向量 + k 个偏移量,高斯在渲染时由一个小网络现算(第 6 章的式 (3)(4))。这一换让「内存里有多少东西」与「这一帧要用多少高斯」解耦,内存里是体素,要用的是体素解出来的高斯,而用哪些体素由第 7 章的 LoD 按距离筛。

对 ①,本篇换掉了「位姿从哪来」。投影这一行里的 ξ 不再反过来由渲染损失去求,而是由前端几何(对极几何 + PnP)独立给出(第 9 章)。注意这不是把 3DGS 换成别的表示,式 (1) 与式 (2) 原样保留,改的只是谁提供 ξ。

对 ②,本篇没有动。排序与 alpha 合成照旧,因此本节的事实二(顺序相关、规模随总数涨)在本篇里仍然成立,只是被 ③ 的处置间接缓解了:每帧实际参与排序的高斯数,从「全图」变成了「LoD 筛出来的那一部分」。这句话是本篇「快」这个结果的技术落点,第 13 章图 13-4 会用「平均视锥体素数从 411,612 降到 8,616」把它量化。

6一个体素解出 k 个高斯:从锚点到椭球

6.1 地图里存的不是高斯,是「能长出高斯的种子」

第 5 章把账算到了「高斯总数只增不减」这一步。本篇对这一笔的处置是第一件反直觉的事:地图里根本不存高斯。

原文的表示是这么组织的:场景被切成稀疏体素;每个体素的中心位置叫「锚点」,所有锚点组成一张表 V ∈ R^{N×3};每个锚点旁边挂三样东西,一个 32 维的上下文特征向量 f̂_v、一个缩放因子 l_v ∈ R³、以及 k 个偏移量 O_v ∈ R^{k×3};每个体素由一组共享的多层感知机(MLP)解码出 k 个高斯[§3.1, p3]。

这套设计是从 Scaffold-GS 借来的,原文也明说了这一点,并给了它三条被选中的理由:渲染快、收敛快、内存效率高;另外还有一条机制上的好处,多个点如果映射到同一个体素,会被合并成一个体素表示,冗余因此被压掉[§3.1, p3]。

「地图里存体素、高斯现算」这句话要拆成两半来感受。

一半是省:内存里躺着的是 N 个体素,每个体素带 32 维特征 + 3 维缩放 + k 个 3 维偏移。另一半是「能按需取用」:一帧要用多少高斯,取决于你解码了多少个体素,只要你只挑视锥体内、且离相机够近的那部分体素去解码,帧成本就与全图规模脱钩。这一步是后面所有效率收益的地基;第 7 章的 LoD 就是「挑哪些体素」这件事的具体规则。

6.2 式 (3):解码的输入里带着相机距离与视线方向

解码这一步的公式很短[§3.1, p3]:

(3) {α_i}_{i=1}^k = F_α(f̂_v, δ, d⃗_vc),(原文式 3 · §3.1, p3)

逐项读:{α_i}_{i=1}^k 是这 k 个高斯的不透明度(注意是一个 k 维的向量,一次出一组);F_α 是其中一个小网络(原文一共列了四个:F_α、F_color、F_quan、F_scaling,分别管不透明度、颜色、量化、缩放);f̂_v 是这个体素的 32 维上下文特征;δ = ‖x_v − x_c‖₂ 是体素到相机的距离;d⃗_vc = (x_v − x_c)/δ 是从相机指向体素的视线方向[§3.1, p3]。

三个输入项各有分工,其中第三项最值得说。

f̂_v 承担「这里长什么样」。它是从体素上学到的特征,与视角无关:同一个体素、不管从哪个方向看,这份特征都是同一份。这是「省」的来源,也是「糊」的来源:视角无关的特征没法表达「从这边看是红的、从那边看是暗的」,所以真正的视角相关变化必须靠后面 d⃗_vc 补。

δ 承担「离得多远」。把它显式喂进网络,而非让网络自己从坐标里推,是一个很实在的取舍:在公里级的坐标尺度上,让网络自己学会「远处该粗一点」需要大量数据;直接把距离当输入,等于把这个先验手工喂进去。这也解释了第 13 章那个消融结论(LoD 的收益随层数递减)为什么会成立,距离这个信号一旦给了,粗粒度的信息就已经在特征里了。

d⃗_vc 承担「从哪个方向看」,而「方向」在这篇里是唯一一个「必须逐视角不同」的量。这一点是理解式 (3) 与式 (4) 的关键:解码的输出里,哪些量可以跨视角共享、哪些必须逐视角算,是后面「复用」这件事的源头(篇目 72 的同名概念在本篇里的落点不同,本篇的复用发生在体素层而不是属性层)。

同一段原文还给了一句容易漏掉的话:c_i、Σ_i、s_i 用「类似的方式」得到[§3.1, p3]。式 (3) 只写了四个网络里的一个,另外三个的形式原文没有逐条列出。本页按这个口径处理:不替原文补写另外三条式,而是在正文里说清「颜色、协方差、缩放各有一个对应的解码网络,形式与式 (3) 同构」。

6.3 式 (4):均值是「锚点 + 偏移 × 缩放」

第二个解码公式是均值的算法[§3.1, p3]:

(4) {μ_i}_{i=1}^k = x_v + {O_{v,i}}_{i=1}^k · l_v,(原文式 4 · §3.1, p3)

逐项读:x_v 是体素锚点(也就是体素中心的世界坐标);{O_{v,i}} 是 k 个偏移量(网络输出或存的偏移);l_v 是缩放因子;{μ_i} 就是这 k 个高斯的三维均值[§3.1, p3]。

这一行是整个表示里最「物理」的一行,因为它把「体素」和「高斯」的几何关系写死了:每个高斯的中心 = 体素中心 + 一个被缩放因子放大过的偏移。

由此可以读出三件约束:

约束一:一个体素里的 k 个高斯是「成簇」的,而且这个簇的形状由 l_v 统一缩放。l_v 是一个三维向量 ⇒ 三个方向的缩放可以不同 ⇒ 一个体素可以长出一簇「斜着摊开」的高斯。这解释了为什么协方差可以用对角形式(第 5.1 节留下的那个问题):空间朝向主要由偏移量的分布和 l_v 的各向异性承担,不必再让每个高斯的 Σ 带旋转。

约束二:O_{v,i} 是「相对坐标」,所以它可以被压得很小。在公里级的绝对坐标里,一个高斯的坐标可能大到 10⁴ 量级;而写成锚点 + 偏移之后,偏移只在体素尺度内变化。这一点在数值上很重要,它让「用低精度存偏移」成为可能(这也是原文四个网络里专门有一个 F_quan 管量化的原因)。本页在精度一节里不再展开,但那句「量化」的存在本身就是这个约束的旁证。

约束三:体素的尺寸直接决定了「一个体素内最细能表达多细的结构」。l_v 再大,也只能在体素尺度内把高斯摊开;要在更细的尺度上表达结构,唯一的办法是把体素切小。这句话就是第 7 章 LoD 的全部动机,体素尺寸是「表达力」与「成本」之间的那个旋钮。

6.4 把这一章的取舍与代价摆平

本章的取舍可以写成一句:用「体素 + 解码」换掉了「高斯平铺」,代价是每帧要跑一次解码。

这句话有三处代价,逐条摆平。

代价一:每帧多了一次网络前向。这是显式的开销。原文没有给出解码本身的耗时占比(图 13-4 的耗时分解是按阶段给的,不含网络前向),本页因此不给这个数。能说的是:这次前向的规模与「这一帧解码了多少体素」成正比,而解码量由 LoD 筛(第 7 章),所以第 7 章的「省」是与第 6 章的「贵」直接对的。

代价二:视角无关的特征装不下强视角相关的表观。f̂_v 是视角无关的,强镜面、强高光这类表观只能靠 d⃗_vc 去补,而式 (3) 里那个网络能不能补得住,取决于它见过的数据。这一条在第 13 章的定性图里会以「远处/边缘区域渲染偏糊」的形式出现(图 13-6 与图 13-7、13-8)。

代价三:体素尺寸一旦选错,要么糊、要么贵。这一条是本章最实际的代价,也是第 13 章图 13-4 的存在理由:原文专门做了一张「层数从 1 扫到 5」的消融表,测的就是这个旋钮。先记下结论的形状:层数增加,视锥体内的体素数从 411,612 一路降到 8,616(少了 48 倍),显存从 22.46 GiB 降到 8.62 GiB,但 PSNR 并不是单调上升的(1 层 24.29 dB、2 层 24.64 dB 最高、3 层 24.05 dB 最低、4 层 24.21、5 层 24.17)[表 5, p10]。这个旋钮不是「越细越好」。原因要到第 7 章讲完 LoD 的分层规则才能说清。

7近处用细体素、远处用粗体素

7.1 一个「距离的收益递减」现象

第 6 章的旋钮只有一档:体素切多大。把体素继续切细,收益会开始递减,而这个能直接看见的现象,就是多档的依据。

原文的描述是:体素细化(把体素切细)需要更多计算资源,但对远处的元素(比如楼房、天空)带来的改进很有限[§3.2, p4]。这句话里有两半:「更贵」是确定的(体素数按体积的立方关系涨),「对远处没用」是可以理解的(远处的表面在图像上占的像素本来就少,细化它买不到多少画面)。

由此推出表示该长成什么样:近处用细体素、远处用粗体素[§3.2, p4]。这就是 LoD。

但本章真正有意思的是原文紧接着给出的第二个理由:LoD 还顺带解决了「撞车」问题,在长序列上,前面视角的高斯会与后面帧的高斯重叠,这对相机位姿跟踪有负面影响;用粗的细节处理远处高斯,可以保证近处重建保持清晰[§3.2, p4]。

把这句话与第 3.2 节接起来看,它是本篇里最漂亮的一处「一石二鸟」:同一件事(把远处变粗)既是省算力,又是治病(撞车)。它之所以能同时成立,是因为「撞车」在物理上主要发生在远处,近处的表面在两段视角下都能被看清、深度也准,所以近处的高斯容易互相印证;远处的深度本来就不准,两批高斯就容易各说各话。粗体素把「远处的争议」用一个更粗的格子盖住,于是两段视角生成的高斯被合并到同一个粗网格里(第 6.1 节那条「映射到同一个体素会被合并」的机制在这里生效)。

7.2 式 (5):体素化是一个「下取整 + 回乘」

分层的规则写成一个集合[§3.2, p4]:

(5) V = { ⌊P / ϵ_l⌋ · ϵ_l | ϵ_l ∈ {ϵ_1, …, ϵ_m} },(原文式 5 · §3.2, p4)

逐项读:P ∈ R³ 是点云位置;ϵ_l 是第 l 层的体素尺寸,由相机距离决定;⌊·⌋ 是逐分量的下取整(原文用的就是下取整符号 ⌊ ⌋);{ϵ_1, …, ϵ_m} 是 m 层体素尺寸的集合;V 是结果体素的集合[§3.2, p4]。

这一行值得逐字拆,因为它把「量化」这件事写得非常干净:

第一步 P / ϵ_l:把世界坐标按这一层的格子尺寸归一化,除以格子大小之后,坐标的整数部分就是「第几号格子」。

第二步 ⌊P / ϵ_l⌋:取整数部分,也就是把这个点吸附到格子的编号上。

第三步 · ϵ_l:乘回去,得到这个格子的中心在世界坐标里的位置。

三步合起来就是一件事:把连续的点云「吸附」到 ϵl 尺寸的网格上。注意输出是一个「集合」(外面那对大括号),同一格里落了多个点,就只留一个格子位置,这正是第 6.1 节那条「合并」的机制在公式里的样子。

第二步那个下取整的形状,本页已经用字体取证核过:它在 PDF 文字层里是伸长字体 CMEX9 的码位 U+0016/U+0017,字形名分别是 floorleftbigg/floorrightbigg,就是下取整 ⌊ ⌋(同一处式子里的外括号是 braceleftbigg/bracerightbigg,即花括号 { })[阶段 1 取证:嵌入 Type1 字体的 /Encoding 字形名]。「这里是下取整不是花括号」这件事是读字体读出来的,不是靠眼睛猜的。

这一行还有一处原文没说、但可以从式子里读出来的性质:ϵ_l 是「由相机距离决定的」,但式 (5) 本身没有出现相机。也就是说,式 (5) 只管「怎么吸附」,「该用哪一层」是下一步的事,那一步就是式 (6) 的掩码。

7.3 式 (6):用一张掩码决定「哪些体素这一帧要用」

选体素的规则分三条 + 一张掩码[§3.2, p4]。原文的口径是:先算体素到相机的欧氏距离 d_v = ‖x_v − x_c‖₂;对每一层 l,体素被选中要同时满足三条,① 落在该层的距离区间 [r_{l−1}, r_l) 内;② 它的层标签 L(x_v) 与当前层 l 相符;③ 从相机看得见。掩码写成[§3.2, p4]:

(6) mask′_i = 1,若 d_v < r_1 且 L_i == 1;= 1,若 r_{l−1} ≤ d_v < r_l 且 L_i == l;= 1,若 d_v ≥ r_{m−1} 且 L_i == m;= 0,否则;  mask_i = mask′_i & visible(x_v),(原文式 6 · §3.2, p4)

逐项读:mask′_i 是「距离 + 层标签」两件事都满足的初判;r_1, …, r_{m−1} 是分层阈值(m 层只有 m − 1 个阈值,因为它们把数轴切成 m 段);L_i 是第 i 个体素的层标签;visible(·) 是可见性判断;mask_i 是最终是否采用[§3.2, p4]。

这张掩码有三处要读懂的地方。

第一,四段分支其实只写了三段「1」+ 一段兜底。三段分别覆盖:最近的(d_v < r_1)、中间的(r_{l−1} ≤ d_v < r_l)、最远的(d_v ≥ r_{m−1})。注意第三段的写法:它用 L_i == m(标签等于最粗的第 m 层)而不是「距离大于某个上限」,意思是「最远那一档不再设上限,全部归到最粗的层」,这是「无界」这个要求在这一行里的落点:开出去再远,都会被最粗的那层接住,不会出现「没有层管我」的空洞。

第二,& 是「与」,不是集合运算。原文用的是 &(在补充材料里写作 \,\&\,),所以第三层筛选(可见性)是与前两层的结果再做一次「与」。这一行的写法是两张掩码相乘(或逐位与),而不是「先按距离筛、再对结果做可见性测试」这种流程描述,两种写法在结果上等价,但对实现的要求不同:写成掩码与,意味着可见性测试必须在同一批体素上完成。

第三,这里说的 visible 只是「从相机看得见」的最粗一档判断,原文没有给它的具体做法。本页按原文的粒度处理:说出它存在、指出它是掩码的第三项,不替原文补写可见性算法的实现。

7.4 这个旋钮不是「越细越好」:两次收敛的读数

第 6.4 节留下的那个疑问(层数增加、PSNR 却不是单调上升)现在可以答了。

先看一层与两层。原文的消融表给出:1 层(体素尺寸 [0.1]、无距离分割)→ 视锥体内平均体素 411,612,PSNR 24.29 dB,显存 22.46 GiB;2 层([0.1, 0.25],阈值 [20])→ 223,627,24.64 dB,15.82 GiB[表 5, p10]。从 1 层到 2 层,体素数砍了一半、显存降了三成、PSNR 反而涨了 0.35 dB,这一段是三赢,也是 LoD 收益最大的一档。

再看三层。3 层([0.1, 0.25, 1],阈值 [20, 40])→ 116,639,PSNR 24.05 dB,11.77 GiB[表 5, p10]。体素数又砍了一半、显存再降到 11.77 GiB,但 PSNR 掉了 0.59 dB,从这里开始,省下来的东西开始要用画质付。

再看四层与五层。4 层([0.1, 0.25, 1, 5],[20, 40, 80])→ 34,721,24.21 dB,9.46 GiB;5 层([…, 25],[20, 40, 80, 160])→ 21,342,24.17 dB,8.62 GiB[表 5, p10]。这两档的显存继续降(9.46 → 8.62 GiB),PSNR 也回来了(24.05 → 24.21 → 24.17),但都低于 2 层的 24.64 dB。

把这五个点连起来看,形状是「先升后降、然后在一个低位平台上来回震」。本页的读法是:最优在 2 层;3 层之所以掉得最狠,是因为最粗的那一层(尺寸 1,即 1 米)已经开始把真实的几何差异抹掉了;4、5 层之所以「回来了」,是因为它们把最粗层(5、25 米)放到更远的地方,同时用更多中间层把 1 米那一档的伤害摊薄了,但摊薄不等于消除,所以天花板仍然低于 2 层。

这段推读有一个直接的旁证:原文自己选的是 2 层(后面所有主结果都建立在 2 层上)。所以「层数」这个旋钮的答案不是「越多越好」,而是「刚好够用」;再多加层只是把显存往下压,买不到画质。这也是本篇「手调阈值」这个代价的具体形态:[0.1, 0.25, 1, 5, 25] 与 [20, 40, 80, 160] 这些数是选的,不是学出来的(第 14 章会把它列成一条前提)。

7.5 图 3 给的是「两侧的账」

上面所有读数来自图 13-4,而图 13-4 只回答了「旋钮怎么调」。LoD 为什么成立、以及它治的那个「撞车」长什么样,由一张图给出。

图 7-1:LoD 的两笔账:左图说「细化对远处不划算」,右图说「远处会撞车」(E 类 · 证据)· 原文 Fig. 3, p5
图 7-1 LoD 的两笔账:左图说「细化对远处不划算」,右图说「远处会撞车」(E 类 · 证据)· 原文 Fig. 3, p5 怎么读 ①图注:原文对这张图的说明分两半:(左)体素细化改进了近处物体的重建,而对远处的收益递减,一个层次的 3DGS 方法在粗体素与细体素之间取得平衡;(右)「撞车」问题:在长序列中,来自远处视角的高斯与后续帧里那些高斯重叠[Fig. 3 图注, p5]。②读法:这张图的左右两半要连着读,它们是一件事的两面。先读左:横轴是「体素细化程度」一类的量、纵轴是「重建收益」,要看的形状是曲线在某一处开始变平,变平的那一点就是「再细化也没用」的边界,也就是 2 层与 3 层之间该切的位置。再读右:它画的是两段不同时期的视角在同一片远处空间里各自生成高斯,要看的是「它们都在那里」,不是哪一批高斯更对,同一块远处空间被两批高斯占据,而它们参与的是同一套渲染与排序。把左右连起来,结论就是:远处既「不值得细化」(左),又「细化之后会互相干扰」(右) ⇒ 对远处做粗,是唯一同时对付两边的动作。 来源:GigaSLAM: Large-Scale Monocular SLAM with Hierarchical Gaussian Splats, Fig. 3, p5 · arXiv:2503.08071v2(CC BY 4.0,© 2025 Kai Deng, Yigong Zhang, Jian Yang, Jin Xie) · 原样引用,未修改

③复算:这张图的两个趋势都能在图 13-4 里找到数字印证。左图说的「收益递减」,图 13-4 的 PSNR 一列给出了完整的形状:1 → 2 层 +0.35 dB,2 → 3 层 −0.59 dB,3 → 4 层 +0.16 dB,4 → 5 层 −0.04 dB[表 5, p10],第二段(2 层以后)的波动幅度整体小于第一段的提升,这就是「收益递减」的量化版本。右图说的「撞车」,图 11-1 里有一个独立旁证:Splat-SLAM 在 KITTI 多个长序列上都给出了带 × 的数值(原文用 × 标注该值不可信)[表 1, p7],而本篇自己在图 13-5 里也把「active 3D Gaussian ratio 在两次大转弯之后冲到近 80%」记成了一个尖峰,高斯数量在转弯之后暴涨,正是「新视角生成的高斯叠在旧地图上」这件事的直接读数。

④边界:这张图只说明「远处细化的边际收益低、且远处会有撞车」,它不说明「粗化一定安全」。图 13-4 的 3 层那一行就是反例:粗化过了头(把 1 米这一档也交给最粗层),PSNR 会掉 0.59 dB。右图说的是「粗的那一档要放对地方」,而不是「越粗越好」,这正是 7.4 节那五个点为什么不是单调的原因。另一个前提是「距离」这个量的可算性:LoD 的全部判断都建立在 d_v = ‖x_v − x_c‖₂ 上,而 x_c(相机位置)在前端跟踪收敛之前是不知道的,所以 LoD 与前端是一个先有鸡还是先有蛋的关系:本篇的处置是用前端的几何结果给出相机位置,再拿它去筛体素(第 9 章),这也又一次说明「位姿不能靠渲染」这件事是整套设计的支点。

8地图怎么长:四条损失,加一次异或哈希

8.1 地图要优化什么:四笔,合成一笔

表示定完了(第 6–7 章)。每来一帧,地图都要更新一次。原文在这里给的是一套损失函数,而且它是一个很典型的「继承 + 叠加」结构:主损失沿用 3DGS 的做法(L1 颜色距离 + SSIM),另外两笔分别借自两个既有工作(深度平滑来自一篇关于稀疏单目深度的工作,各向同性正则来自 MonoGS),最后由一笔总损失把它们按权重加起来[§3.2 Map Update, p4–p5]。

先说主损失:

(7) L_render = Σ_{m=1}^{M} λ_1 ‖I_m^GS − I_m^gt‖_1 + λ_2 SSIM(I_m^GS, I_m^gt),(原文式 7 · §3.2, p5)

逐项读:L_render 是渲染损失;m 遍历当前图像的像素;I_m^GS 是渲染出来的彩色图;I_m^gt 是真值彩色图;SSIM(·,·) 是原文所称的 D-SSIM 项;λ_1、λ_2 是两个超参数[§3.2, p5]。

这一行的形状是标准写法,但有两处值得点出来。第一,原文把 m 说成「当前图像的像素坐标」,而求和上限写作 M,它其实是在整幅图上求和。第二,‖·‖_1 与 SSIM 这一对是互补的:L1 管像素级的绝对误差(对结构不敏感),SSIM 管结构相似度(对亮度不敏感)。两者加权相加是 3DGS 一系的标准配方,本篇没有改动。

第二笔是深度平滑,它借自一篇稀疏单目深度的工作:

(8) L_smooth = Σ_{d_j ∈ Adj(d_i)} 1_ne(d_i, d_j) |d_i − d_j|²,(原文式 8 · §3.2, p5)

逐项读:L_smooth 是平滑损失;Adj(d_i) 是 d_i 的邻点集合;1_ne(d_i, d_j) 是一个指示函数,判断 d_i 与 d_j 之间是否构成「几何边缘」;|d_i − d_j|² 是两点的欧氏距离平方;边缘是用 Canny 算子抽出来的[§3.2, p5]。

这一行的巧妙处在那个指示函数上:它把「平滑」限制在「非边缘」的地方,1_ne 为 0(是边缘)时,这一项不加约束,深度在边缘处允许跳变;1_ne 为 1(不是边缘)时,两点的深度被要求尽量接近。它做的是「在没有几何边缘的地方把深度抹匀」,不是「把深度糊平」。原文明确说了这条的动机:提升三维高斯深度渲染的几何精度,抑制稀疏单目输入下的过拟合[§3.2, p5]。

第三笔借自 MonoGS,管高斯的形状:

(9) L_iso = Σ_{i=1}^{|G|} ‖s_i − s̄_i · 1‖_1,(原文式 9 · §3.2, p5)

逐项读:L_iso 是各向同性损失;|G| 是正在被优化的高斯数;s_i 是第 i 个高斯的缩放(三维);s̄_i 是它的平均缩放(一个标量);1 是全 1 向量;‖·‖_1 是 L1 范数[§3.2, p5]。

这一行的语义是「惩罚长条」:如果 s_i 的三个分量相等(各向同性),s_i − s̄_i · 1 = 0,损失为 0;如果某个方向特别长、另两个特别短(高长宽比),损失就大。原文的措辞是「惩罚高长宽比的本原」[§3.2, p5]。这条损失在 SLAM 场景下有很实际的用途:单目输入下,一个被拉得很长的椭球可以「斜着」同时去拟合两片离得不近的表观,在监督稀疏的地方它很容易变成一根针;L_iso 就是在按住这件事。

不过这条损失在本篇里有一处内部张力,值得摆出来:第 6.3 节刚刚论证过「一个体素里 l_v 的三个方向可以不同、一个体素能长出一簇斜着摊开的高斯」,而 L_iso 又在惩罚各向异性。两者并不矛盾(L_iso 约束的是单个高斯的 Σ/s 的各向异性,l_v 控制的是簇的排布),但它们确实在同一个方向上互相拉扯。原文没有讨论这层关系,本页指出这一点,不替原文下判断。

最后一笔是把三样加起来:

(10) L_total = L_render + λ_i L_iso + λ_s L_smooth,(原文式 10 · §3.2, p5)

逐项读:L_total 是总损失;λ_i、λ_s 是两个权重超参数[§3.2, p5]。

这一行只有三个加项,而且是「主损失 + 两个正则」的形状,它说明本篇把「深度平滑」与「各向同性」都当成了正则项(也就是「锦上添花但不可缺」的那一类),不是当成主要目标。这个层级关系在图 13-2 的消融里会显形(第 13 章)。

8.2 地图怎么不重复长:一次异或哈希

优化管的是「已有的体素长得好不好」;扩张管的是「新的体素要不要加」。后者要解决的是一个很朴素但很致命的问题:重复。

原文把问题的形状说得很清楚:长序列上新的体素会和已有的重叠;由于相邻视角之间视觉上有大量重叠,很多「新建」的体素其实地图里已经有了,车往前开一米,可能有一大半「新体素」是白建的[§3.2 Map Expansion, p5]。

处置是一次空间哈希:

(11) h(x) = (⊕_{i=1}^{d} x_i π_i) mod T,(原文式 11 · §3.2, p5)

逐项读:x = (x_1, x_2, x_3) 是锚点的三维坐标;⊕ 是按位异或的累加(原文用的就是那个大号的圈加符号,在 PDF 里由 CMEX10 字体的 circleplusdisplay 字形承载);π_i 是三个素数常量,原文明确给出了取值:π_1 = 1、π_2 = 2654435761、π_3 = 805459861(并说明这是沿用某篇 Instant-NGP 系工作的设置);T = 2^{63};mod T 是取模[§3.2, p5]。

这一行要读三件事。

第一,它是「异或」(⊕)而不是「相加」。异或的好处是对称且可逆:同一组坐标必然得到同一个哈希值,因此「这个体素在不在」变成一次查表。原文把代价与收益都写明了:这套空间哈希让去重可以在常数时间内完成,从而保证地图里只留下唯一的体素[§3.2, p5]。

第二,π_i 的形状就是学界熟知的「三素数」配方。π_1 = 1、另外两个是 31 位/30 位的奇数大素数,这套取值的用途是把三维坐标映射到一维而不产生系统性的碰撞(相邻格不会映到相邻槽)。注意 π_2 与 π_3 都是奇数、且都不是 2 的幂,这正是为了让异或的各位互相混淆。

第三,T = 2^{63} 是一个「大到不会真的取模」的模数。在 π_2 = 2654435761 ≈ 2^{31.3}、π_3 ≈ 2^{29.6} 的尺度下,两个坐标分量的乘积就已经到 2^{60} 量级,T = 2^{63} 意味着这个模运算在绝大多数实际坐标范围内不会触发,它是一个「形式上保证有界」的封顶,而不是一个实际参与哈希的有效模数。本页把它如实点出来:这一处写法在实际执行时更接近「不做取模」,取模只在坐标极大时才起作用。

这一处处置与第 3 章那两笔账的关系要说清:它治的是「重复」,不是「撞车」。「撞车」是两批不同位置的高斯互相干扰(第 3.2 节,靠 LoD 治);「重复」是同一位置被建了两遍(本节,靠哈希治)。原文在同一节里把两件事分开处理,本页也分开记。

8.3 地图的「生长」在实现上是什么样

把本章三件事按执行顺序摆一遍,就是地图的生长过程:① 前端给出相机位姿 ξ;② 用 ξ 把度量深度转成点云;③ 按距离做层次体素化(式 (5));④ 用空间哈希去重(式 (11));⑤ 把新体素送进损失里优化(式 (7)–(10))[§3.2, p5]。

这个过程里有三处「原文没有给数」的地方,本页照实标注:

其一,体素是在什么条件下被「新建」的,原文没有给判据。原文只说新体素由「估计相机位姿、把度量深度转成点云、按距离层次体素化」产生[§3.2, p5]。至于「哪些新点值得建体素、哪些该丢弃」,本页不给推测。

其二,λ_1、λ_2、λ_i、λ_s 四个权重的取值,原文没有给。式 (7) 与式 (10) 把它们写成超参数,但正文与补充材料都没有列出具体数值。本页因此不写「权重设为多少」这类表述。

其三,解码网络的四个 MLP(F_α、F_color、F_quan、F_scaling)的结构与层数,原文没有给。唯一可知的是「共享 MLP」这一点(同一个体素的所有高斯共用同一组网络)[§3.1, p3]。这一条在复现意义上是个缺口,第 14 章的边界一节会再提一次。

本章的取舍可以压成一句:地图的「长」被拆成两件互不干扰的事,用损失决定「已有的长得好不好」,用哈希决定「新的该不该加」,两者之间只通过位姿耦合。这句拆法本身是本章最可迁移的一点:它让「去重」从一个需要持续维护的过程(比如维护一棵八叉树)变成了一次常数时间的查表,原文在式 (5) 之后专门说了一句「体素化过程与 Octree-GS 类似,但我们不维护八叉树」[§3.2, p4]。这句话是本章那句取舍的原文版本。

9前端跟踪:深度给出尺度,几何给出姿势

9.1 这一章要切断的是那根线

投影那一行里的相机位姿 ξ,不再由渲染损失反求,改由几何独立给出:尺度交给一个度量深度模型,姿势交给对极几何与 PnP。第 5.2 节留下的那根线在这里剪断,所以这一章只有五条式,却是整套设计的支点。

先说清楚「切断」这件事为什么必须做,而且是本篇最不像「新方法」的一处改动。它有两条理由,一条是数值的、一条是结构的。

数值的那条:渲染损失对位姿的梯度,要求地图已经收敛到「渲得像」。在室内这没问题(场景小、收敛快);在室外长序列上,跟踪常常是在一张没收敛完的地图上做的,这时渲染损失给出的梯度指向的是一个「还没成形的地图认为对」的位姿,而不是物理上对的位姿。原文把这条写成了那个反馈环[§2, p3]。

结构的那条更彻底:如果位姿依赖渲染,那么「换一个位姿」就等于「换一次渲染」,而渲染的规模随高斯总数涨,于是位姿估计的成本也随场景规模涨。这在大尺度上是个死循环:地图越大 → 单次位姿估计越贵 → 每帧能做的迭代越少 → 位姿越不准 → 地图越脏。把位姿改成几何求,这条链就断了:几何前端的成本只与图像分辨率有关,与地图规模无关。

本篇的几何前端是「三段拼起来」的:① 特征,用 DISK 网络抽特征、用 LightGlue 做匹配;② 几何,用对极几何从 2D-2D 对应解出相机运动,不可靠时切 PnP;③ 尺度,用度量深度模型 UniDepth 把「尺度未知」这件事补上。原文对第 ③ 段的定位很清楚:Depth Anything、DPT、Monodepth 这一类深度网络在短序列上表现不错,但存在度量歧义,会拖垮 SLAM 的表现;UniDepth 通过标准化相机空间变换缓解了这个歧义,让系统可以在跟踪之前先恢复出度量深度[§3.3, p5]。

9.2 式 (B.1) 与 (B.2):对极几何那两步

前两步是教科书式的,但它们的形状里有信息[补充 §B, p15]:

(12) F = K^{−T} E K^{−1}, E = [t]_× R。(原文式 B.1 · 补充 §B, p15)
(13) p_j^T K^{−T} E K^{−1} p_i = 0。(原文式 B.2 · 补充 §B, p15)

逐项读:F 是基础矩阵;E 是本征矩阵;K 是相机内参;[t]_× 是由平移向量 t 构成的反对称矩阵(也就是「叉乘矩阵」);R 是旋转;p_i、p_j 是两幅图里对应点的齐次坐标,写作 p = [u, v, 1]^T,其中 (u, v) 是像素坐标[补充 §B, p15]。

式 (B.1) 的第一行是一句「拆解」:F 不是独立的东西,它等于「内参夹住 E」:基础矩阵里混着相机内参,而本征矩阵里只有运动与旋转。这一行的实际用途是:只要你有了 K,就可以把估计出来的 F 换算成 E,再从 E 里提出纯运动。第二行 E = [t]_× R 把这件事讲得更狠:本征矩阵完全由「平移的叉乘」与「旋转」拼成,而平移只以「方向」的形式出现,注意这里没有 ‖t‖。

这就直接给出了本章第三个子问题(尺度)的出处:从 E 里分解出来的 t 是单位长度的方向向量,不是真实的位移。单目对极几何在原理上就量不出尺度,这不是实现的缺陷,是几何性质。原文在 4.2 节的说法是「本征矩阵固有的尺度歧义」[补充 §B, p15]。

式 (B.2) 是那条约束本身。中间那串 K^{−T} E K^{−1} 就是 F,所以它等价于 p_j^T F p_i = 0,两幅图里任意一对正确匹配的点,都落在这条约束上。它的用法是反过来的:给定一堆匹配点,找一个 F 让所有点对都尽量满足这条式子(这就是经典的八点法与它的鲁棒版本在做的事)。原文在这一段之后给了一句关键的过渡:相机运动 [R, t] 是通过分解 F 或 E 恢复的[补充 §B, p15]。

同时原文也点出了这条路的两个已知失效条件:运动退化(比如纯旋转),以及本征矩阵固有的尺度歧义[补充 §B, p15]。这两条是后面 GRIC 存在的直接理由。

9.3 式 (B.3):切到 PnP 时,代价函数换了个形状

对极几何靠不住时,本篇切到 PnP,而PnP 的代价函数与对极几何完全不同[补充 §B, p15]:

(14) e = Σ ‖K(R X_i + t) − p_j‖²。(原文式 B.3 · 补充 §B, p15)

逐项读:X_i 是三维点(世界坐标);R、t 是待求的相机运动;K(R X_i + t) 是把这个三维点投到图像平面上的像素位置;p_j 是它在图像里的观测位置;e 就是重投影误差的平方和[补充 §B, p15]。

这一行与式 (B.2) 的差别值得停下来看,因为它解释了为什么 PnP 能救场:

式 (B.2) 用的是「2D 与 2D」:两幅图里的一对像素,靠一条代数约束(p_j^T F p_i = 0)相连。它不需要三维信息,代价是「只能定出方向、定不出尺度」,而且对运动退化敏感。

式 (B.3) 用的是「3D 与 2D」:把已知的三维点投出去,与观测的像素比。这一换,尺度问题就没有了,因为三维点 X_i 本身带着绝对尺度。而 X_i 从哪来?原文给了答案:三维信息来自 UniDepth 抽出的稠密深度图[补充 §B, p15]。

这就是「深度给出尺度」这句话的全部含义:单目视频自己量不出尺度,一旦给它一个度量深度图,尺度就被外部注入进来了,式 (B.3) 就是把这份外部尺度用起来的地方。代价也很明确:位姿的绝对精度从此绑在深度模型的精度上(第 14 章的边界一节会再提一次)。

9.4 式 (B.4) 与 (B.5):什么时候该切,由一条信息准则来判

「什么时候用对极几何、什么时候切 PnP」这件事,本篇交给了 GRIC[补充 §B, p15]:

(15) GRIC = Σ ρ(e_i²) + log(4) d n + log(4 n) k,(原文式 B.4 · 补充 §B, p15)
(16) ρ(e_i²) = min( e_i² / (2 (r − d) σ²) , 1 )。(原文式 B.5 · 补充 §B, p15)

逐项读:d 是结构维数;n 是匹配特征数;k 是运动模型参数个数;σ 是测量误差的标准差;ρ(·) 是一个截断型的损失(式 (B.5) 给出的就是它的定义)[补充 §B, p15]。

这两条式的结构是本篇里最「经济学」的一处:它算的是一笔「拟合得好不好」与「模型有多复杂」之间的汇率。

式 (B.4) 有三项:第一项 Σ ρ(e_i²) 是「拟合误差」,残差越小这一项越小;第二、三项 log(4) d n 与 log(4 n) k 是「复杂度惩罚」,n(匹配数)乘上 d(结构维数)是「这个模型的自由度规模」,k 是运动模型的参数量。换句话说:模型越复杂、数据越多,你要为「复杂度」付的钱越多;只有拟合误差降下来的收益能盖住这笔钱,这个模型才划算。

式 (B.5) 是那个 ρ 的定义,而它的形状很值得看:它是一个「上限为 1」的截断,残差 e_i² 小的时候它线性增长(e_i² / (2(r−d)σ²)),大到某个程度就被截到 1 不再增长。这个截断的作用是「把离谱的点当外点处理」,一个误差极大的匹配不会因为它的残差平方而独占整个求和,这正是「鲁棒」两个字的实现方式。分母里的 σ² 也很关键:它把残差按测量噪声归一化,噪声大的场景下同样的残差被算得更小,这是有统计意义的写法。

原文给了切换规则:当 GRIC_F 超过 GRIC_H 时,切到 PnP(F 指基础矩阵模型,H 指单应模型)[补充 §B, p15]。这一句里有个容易读错的地方:它比较的是「基础矩阵模型」与「单应模型」两个假设,而不是「对极几何」与「PnP」。也就是说,GRIC 在原文献里的作用是「判断场景是平面还是非平面、以及运动是否退化」,本篇借用它来回答「当前的几何配置是不是已经退化到不可用」,一旦判定退化,就切到不依赖「对极约束」的 PnP。本页按原文的措辞如实标注这一点,不替它扩大 GRIC 的适用范围。

9.5 这条链的代价,以及它为什么值

本章的处置可以压成一句:把「尺度」这个单目视频天生缺的量,用外部度量深度补进来;再把「位姿」这件事从渲染损失里挪到几何里。

它换来的东西是结构性的:位姿估计的成本与地图规模解耦,第 5.2 节那根「投影要位姿、位姿靠渲染」的环被剪断,第 2 章那张三档表里第三档的失灵点也就此消失。

它付出的代价有三条,其中两条原文自己承认了:

代价一:精度上限被深度模型锁住。式 (B.3) 的三维点全部来自 UniDepth,所以位姿的绝对精度不可能超过深度的绝对精度。原文对这条的表述是「UniDepth 通过标准化相机空间变换缓解了度量歧义」[§3.3, p5],「缓解」这个词是它自己的口径。为了压住帧间的尺度抖动,本篇还加了一步:用 RANSAC 校正帧间的尺度误差(做法沿用 DF-VO)[§3.3, p5]。

代价二:特征与匹配的质量成为单点故障。DISK + LightGlue 这一对是整条链的入口,纹理稀薄、视角剧变的地方它们会给出更少的匹配,而匹配数 n 恰好是 GRIC 的输入之一(式 (B.4)),也就是说「匹配少」会同时降低几何解的可用性和判据的可靠性。这一条与第 10 章回环检测用的是同一类信息(图像检索/特征),所以两个模块在同样的场景下会一起变弱。

代价三:这条链在原文里被整体放在了补充材料。五条式全部在补充 §B,主文只用一段话带过[§3.3, p5]。这个「放置位置」本身是一条信息:作者把「几何前端」当成可替换的配件(第 4.1 节那张总览图上也没画它),而把「地图怎么组织」与「回环后怎么改地图」当成主干。读这一章时,把「它没被当成贡献」这件事记住,第 14 章讲边界时,它恰好是最脆弱的一环。

10回环修正:把漂了的整张地图扳回来

10.1 这一章要动的是整张地图,不是几个位姿

第 3.1 节留下的那笔账要在这里还:共视变稀 ⇒ 优化窗口变小 ⇒ 尺度漂移累积。本篇对这一笔的处置是「另起一条显式的回环链」,而这条链的难点不在「检测到回环」,在「检测到之后要动什么」。

先把「要动什么」说清楚。车开出去十公里、绕回来了,现在告诉系统「你第 200 帧和第 11000 帧看的是同一个街角」。要修的东西包括:① 这两个关键帧之间所有关键帧的位姿(它们构成了一条需要被整体「掰」回来的链);② 整张地图的坐标系,因为地图里所有高斯都是挂在体素锚点上的,而锚点是用相机位姿从深度图里反投出来的,位姿一变,锚点的世界坐标就全错了。

第 ② 件是本篇与「传统 SLAM」分道扬镳的地方。传统 SLAM 回环之后只需要更新位姿与地图点(点是可以重投的);而本篇的地图里躺着的是几百万个体素锚点,它们每一个都必须被搬到新的坐标系里,这是本章后半(10.8 节)要解决的问题,也是本篇自称的第三条贡献(「适用于高斯地图的高效回环流程」)的落点。

前半(10.2–10.7 节)是这条链的数学,它是一套标准的 Sim(3) 优化,原文自己明确说了这一点:这套回环修正方法「紧密沿用」了某两篇既有工作,「是过去十五年被应用到各种 SLAM 方法上的经典 Sim(3) 优化」[补充 §C, p16]。换句话说:前半不是本篇的发明,后半才是。读这一章时要带着这个分工。

10.2 检测:BoW 检索 + ORB 特征,另开一个线程

检测这一段的做法不变,但原文给了三个工程细节[补充 §C, p16]。

第一,用 DBoW2 做图像检索:在每一帧上抽 ORB 特征,用它们去找「看起来像同一个地方」的候选图像对[补充 §C, p16]。

第二,这些操作放在另一个线程里并发执行,原文的理由是「把运行时开销压到最小」[补充 §C, p16]。这一点值得记:回环检测是「不做也不影响当前帧」的事,所以它是唯一可以整段挪出主循环的模块。

第三,加了非极大值抑制(NMS)防止检测得过于频繁,做法沿用了另一篇工作[补充 §C, p16]。这一条对应的是一个很实际的问题:如果一个地方被反复检测成回环,同一段轨迹会被反复优化,既费算力,也可能让优化在几个互相冲突的约束之间来回震荡。

主文对这一段的口径略有不同:主文说的是「基于邻近性的回环检测 + 一个传统 SLAM 后端」,检测用 DBoW2 的图像检索,随后做带平滑项与回环约束的 Sim(3) 优化[§3.4, p6]。两处说的是同一件事,补充材料多给了「另开线程」与「NMS」两个实现细节。

10.3 残差怎么定义:两条式子,一条管回环、一条管相邻

优化要有一个残差,本篇用了两条[补充 §C, p16]:

(17) r_jk = log_{Sim(3)}( ΔS_jk^loop · S_j^{−1} · S_k )。(原文式 C.1 · 补充 §C, p16)
(18) r_i = log_{Sim(3)}( ΔS_{i,i+1}^{−1} · S_i^{−1} · S_{i+1} )。(原文式 C.2 · 补充 §C, p16)

逐项读:S_i = (t_i, R_i, s_i) ∈ Sim(3) 是关键帧 i 的相似变换(注意它比 SE(3) 多一个尺度 s_i);ΔS 是两个关键帧之间的相对相似变换(上标 loop 表示「来自回环的那一份」);log_{Sim(3)}(·) 是把相似变换映射回李代数(也就是把这个「变换」变成误差空间里的一个「向量」)[补充 §C, p16]。

这两条式子的结构完全同构,只差一件事:ΔS 在 (C.1) 里是带 loop 上标的回环相对变换,在 (C.2) 里是相邻帧之间的相对变换。写成这个形状的意思是「测量的残差 = 预测的相对变换 与 我们的估计之间的差」,S_j^{−1} · S_k 是「用当前估计算出来的、从 j 到 k 的相对变换」,ΔS_jk^loop 是「回环检测给出的、应该等于它的那个量」,两者一比就是残差。

注意那个 log。残差是在李代数里算的,不是在变换矩阵里算的,变换矩阵不能直接相减(它们是一个群,不是向量空间),所以要先取对数把它拉到切空间里,才能做加减法、才能定义「平方和」。这一步是李群优化的标准动作,本篇原样沿用。

另外 S_i 是 Sim(3) 而不是 SE(3),这一点很关键:单目 SLAM 的漂移里有一大半是「尺度漂移」(第 9.2 节讲过,单目本身量不出尺度),所以回环优化必须把尺度当作一个可优化的量,否则「把漂移扳回来」这件事根本做不到。原文对此的表述是把相似变换显式定义成三元组 (t_i, R_i, s_i)[补充 §C, p16]。

10.4 代价函数:把两类残差平方加起来

两条残差接上各自的求和,就是目标函数。主文先给出完整形式[§3.4, p6]:

(19) arg min_{S_1,…,S_N} Σ_{i}^{N} ‖log_{Sim(3)}( ΔS_{i,i+1}^{−1} · S_i^{−1} · S_{i+1} )‖²_2 + Σ_{(j,k)}^{L} ‖log_{Sim(3)}( ΔS_jk^loop · S_j^{−1} · S_k )‖²_2。(原文式 12 · §3.4, p6)

补充材料把它分两步再写一遍:先写缩写形式[补充 §C, p16]:

(20) arg min_{S_1,…,S_N} Σ_{i}^{N} ‖r_i‖²_2 + Σ_{(j,k)}^{L} ‖r_jk‖²_2。(原文式 C.3 · 补充 §C, p16)

展开之后写成完整形式[补充 §C, p16]:

(21) arg min_{S_1,…,S_N} Σ_{i}^{N} ‖log_{Sim(3)}( ΔS_{i,i+1}^{−1} · S_i^{−1} · S_{i+1} )‖²_2 + Σ_{(j,k)}^{L} ‖log_{Sim(3)}( ΔS_jk^loop · S_j^{−1} · S_k )‖²_2。(原文式 C.4 · 补充 §C, p16)

逐项读:N 是关键帧数;L 是回环约束的条数;第一项覆盖所有相邻关键帧(i 从 1 到 N),第二项覆盖所有被检测到的回环对((j, k))[补充 §C, p16]。

这个结构就是一句话:既要相邻帧之间保持连贯(第一项),又要被检测到的回环对回到同一个地方(第二项)。 原文把第一项叫平滑项、第二项叫回环项[§3.4, p6]。

这里有一处必须点出来的重复:同一段原文在主文里写成式 (12)、在补充材料里展开成 (C.3) 与 (C.4),而主文式 (12) 与补充式 (C.4) 的表达式完全一致,同一套优化被主文和补充材料各写了一遍,编号不同。本页按「两处都照录」处理:主文的式 (12) 落在本章 10.4 节,补充的三条式落在本节与下一节。这是「主文给结论、补充给过程」这种常见组织方式的副产物,不是原文的错误;读者若逐篇核对编号,需要知道有这件事。

10.5 化简:只留回环项,把相对变换当常数

完整的目标函数在实现上不好直接解,原文给了一套两步化简[补充 §C, p16–p17]。

第一步,只优化回环项:

(22) min ‖r(S)‖² → min ‖log_{Sim(3)}( ΔS_jk^loop · S_j^{−1} · S_k )‖²。(原文式 C.5 · 补充 §C, p17)

第二步,把相对变换冻结成一个常数:「在每一步优化里,相对变换 ΔS_jk^loop 先被算出来、随后被当成常数 C」[补充 §C, p17]:

(23) r = ‖log_{Sim(3)}( C · S_j^{−1} · S_k )‖²。(原文式 C.6 · 补充 §C, p17)

这两步要一起读,因为它们是一件事的两面。

式 (C.5) 的「只留回环项」是一次取舍:平滑项被暂时丢掉了。丢掉的代价是「相邻帧的连贯不再被显式约束」,它能成立的前提是「回环项本身已经把整条链拉到了一致的位置上」,也就是说,把 j 与 k 对齐之后,中间那一段只要跟着 j 走就行。原文没有论证这个前提,本页把它标成一处未展开的简化。

式 (C.6) 的「取常数」是雅可比能算出来的前提:要求残差对 S_j、S_k 的导数,就必须让「残差里除了 S_j、S_k 之外的量都不动」。把 ΔS_jk^loop 冻成 C 之后,残差里只剩两个未知量 ⇒ 可以照常求导。代价是「这一步更新的方向是相对于当前的 C 算的」 ⇒ 需要迭代:每个外层迭代更新一次 C,内层用冻结的 C 解一次线性方程。原文的措辞是「在每一次优化步里先算出相对变换、再把它当常数」,这正是「外层更新常数、内层解方程」这种交替结构的写法[补充 §C, p17]。

10.6 从雅可比到正规方程:六条式的推导链

下面六条式是标准的高斯-牛顿链,本页逐条给出它的语义[补充 §C, p17]。

式 (C.7) 定义雅可比:

(24) J_j = ∂r/∂S_j, J_k = ∂r/∂S_k, J = [J_j, J_k]。(原文式 C.7 · 补充 §C, p17)

逐项读:J_j 与 J_k 是残差分别对两个待优化量的偏导,J 是把它们横向拼起来的总雅可比。注意更新增量 ΔS = [ΔS_j, ΔS_k] 也是拼起来的,也就是说这一步只解两个关键帧的增量,其余关键帧不动。

式 (C.8) 是一阶泰勒近似:

(25) r ≈ r + J ΔS。(原文式 C.8 · 补充 §C, p17)

这一行是「把非线性问题局部线性化」的那一步。它成立的半径取决于残差函数有多非线性,这也是后面为什么要加阻尼的原因(式 (C.12))。

式 (C.9) 与 (C.10) 把「最小化残差」展开成一个二次型:

(26) ΔS = arg min ‖r + J ΔS‖² = arg min (r + J ΔS)^⊤ (r + J ΔS)。(原文式 C.9 · 补充 §C, p17)
(27) ΔS = arg min ( ‖r‖² + ΔS^⊤ J^⊤ J ΔS + 2 ΔS^⊤ J^⊤ r )。(原文式 C.10 · 补充 §C, p17)

式 (C.10) 就是把式 (C.9) 那个平方展开的结果。这里可以顺手做一个常被跳过的说明:展开式里的三项,‖r‖² 与 ΔS 无关,所以对最小化没影响,可以直接丢掉;剩下两项里 ΔS^⊤ J^⊤ J ΔS 是二次项、2 ΔS^⊤ J^⊤ r 是一次项。丢掉常数项之后,这是一个标准的二次型最小化问题,它的解就是把梯度置零。

式 (C.11) 就是置零的结果,也就是正规方程:

(28) J^⊤ J ΔS = − J^⊤ r。(原文式 C.11 · 补充 §C, p17)

这一行是全篇最「可以背下来」的一行:左边是「雅可比的格拉姆矩阵」乘上增量,右边是「雅可比转置乘残差」,任何学过最小二乘的人都能立刻认出这个形状。它的实际含义是:解一个线性方程组就能拿到这一步的增量。

式 (C.12) 给这个方程组加了阻尼:

(29) ( J^⊤ J + λ diag(J^⊤ J) + ε I ) ΔS = − J^⊤ r。(原文式 C.12 · 补充 §C, p17)

逐项读:λ 是阻尼系数;diag(J^⊤ J) 是取格拉姆矩阵的对角部分;ε I 是一个极小的单位阵项(用来保证矩阵可逆)[补充 §C, p17]。

这一行是列文伯格-马尔夸特(LM)法的标志性写法,而它有两种常用的阻尼形式:一种加 λ I(列文伯格式),一种加 λ diag(J^⊤ J)(马尔夸特式)。本篇用的是第二种,这一点值得记,因为两种形式的行为不同:λ I 的阻尼对所有方向一视同仁,而 λ diag(J⊤J) 对每个方向按它自己的曲率缩放 ⇒ 在参数尺度差异很大时(比如这里三个平移分量与一个尺度分量、还有旋转)后者更稳。ε I 那一项则是纯数值的保险(防止某个方向的曲率为零导致奇异)。

式 (C.13) 把整件事收成一行:

(30) A Δx = b。(原文式 C.13 · 补充 §C, p17)

这一行不是新的数学,它是「把上面那个方程组命名一下」。原文本节到这一行为止,推导链闭合,从残差定义 (C.1)(C.2),到代价函数 (C.3)(C.4),到化简 (C.5)(C.6),到雅可比与线性化 (C.7)–(C.10),到正规方程与阻尼 (C.11)(C.12),最后写成线性方程组 (C.13)。这是本页 32 条式里唯一一条完整的推导链,也是本系列此前各篇里最长的一条。

10.7 优化完之后:位姿怎么落地

原文对这一步只给了一句话:优化之后,用更新过的相似变换 S_i 去更新全局位姿,G_i ← (t_i, R_i)[补充 §C, p16]。

这一行里的「取 (t_i, R_i)、丢掉 s_i」是个关键动作:S_i 是一个相似变换(含尺度),而系统最终要给出去的位姿是一个 SE(3)(不含尺度)。所以尺度分量被用来「修改整段轨迹的尺度」,但不进入任何一个位姿,这是「尺度漂移被纠正」这句话在实现层的精确含义。本页把它点出来,因为它是「Sim(3) 优化」与「位姿更新」之间那道常被忽略的缝。

10.8 位姿变了,地图也得跟着搬:式 (13) 与式 (14)

现在回到 10.1 节那第 ② 件事:地图里的体素锚点是用「旧位姿 + 深度」反投出来的,位姿变了之后,它们的世界坐标必须跟着改。本篇的做法是给每个锚点做一次刚体变换[§3.4, p6]:

(31) p_i^new = T_new^{(j)} · ( T_old^{(j)} )^{−1} · [ p_i ; 1 ]。(原文式 13 · §3.4, p6)

逐项读:p_i ∈ R³ 是第 i 个锚点,它原本属于第 j 个相机位姿;T_old^{(j)} ∈ SE(3) 是它的旧位姿;T_new^{(j)} 是优化后的新位姿;[p_i ; 1] 是把三维点写成齐次坐标(补一个 1),为的是能参与 4×4 的变换[§3.4, p6]。

这一行的语义非常干净:「把锚点从旧坐标系搬回相机坐标系、再搬到新坐标系」,(T_old)^{−1} 卸掉旧位姿,T_new 装上即位姿,中间那个 p_i 就是它在相机坐标系里的位置(而它在相机坐标系里的位置不该变,因为相机看到的还是同一块地方)。这就是「整图刚体更新」这个说法在公式里的样子。

但这一行在公里级体量上有个致命问题:它要遍历所有锚点。原文的处置是分批[§3.4, p6]:

(32) ∀ p ∈ B_m, p^new = T_new^{(π(p))} · ( T_old^{(π(p))} )^{−1} · [ p ; 1 ]。(原文式 14 · §3.4, p6)

逐项读:整个锚点集 P = {p_1, …, p_N} 被切成 M 个互不相交的子集 B_1, …, B_M,每个子集的规模 B ≪ N;π(p) 是把点 p 映射到「它所属的那个相机位姿的下标」的函数;在每个批次 B_m 内部,更新规则与式 (13) 一致,只是局限在本地做[§3.4, p6]。

式 (14) 与式 (13) 唯一的差别就是那个 π(p),式 (13) 里位姿的下标 j 是固定的(「这个锚点属于第 j 个位姿」),式 (14) 里它由 π(p) 现查。写成这样就允许「一个批次里混着属于不同位姿的锚点」,这是分批能成立的前提:如果必须按位姿分组才能分批,批次边界就会被位姿边界绑住,切不出均匀的块。

原文对分批的理由只给了一句:减少大规模体素的内存消耗[§3.4, p6]。它没有给 M 或 B 的具体取值,本页如实标注这一点(这与第 8.3 节那几处「原文没给数」是同一种情况)。

最后还有一步:更新完之后需要重新做一次体素化(式 (5)),让地图结构跟着适配;而回环引入的那些新体素,靠空间哈希(式 (11))做快速查找[§3.4, p6]。注意这里绕回去了:第 8 章的式 (5) 与式 (11) 在第 10 章被再次调用,也就是说,回环修正这套流程是「复用了建图那一套工具」的,它没有引入新的表示机制。这一点是本篇「设计与实现一致」的一处证据,也是第 10.1 节那句「前半不是发明、后半才是」的具体所指:发明的那部分(整图分批刚体更新 + 复用体素化与哈希)恰好落在式 (13)(14) 与它们前后那两句话里。

11实验怎么搭,以及 KITTI 上到底赢多少

11.1 实验是怎么搭的:四个数据集、两块机器、一条 480 像素

四个数据集、两块机器、渲染一律固定在 480 像素宽,本篇的每一个读数都建立在这三条边界上[§4.1, p6]。

数据集是四个:KITTI(主数据集,公里级长序列)、KITTI 360、4 Seasons、A2D2。原文对为什么选 KITTI 当主场给的理由是「它的公里级长序列」[§4.1.1, p6]。

指标分两族。跟踪侧用 ATE(绝对轨迹误差),报的是关键帧上的值;地图侧用渲染的三大指标:PSNR、SSIM、LPIPS(覆盖像素级与感知级两种差异)。这里有一条重要的口径:A2D2 数据集没有真值位姿矩阵,因此算不了 ATE,对本篇来说这并没有损失,它反而是唯一一个「没有真值也能上线」的检验:原文的做法是把轨迹投影到 Google Map 上做可视化核对[§4.1.1, p6]。

算力配置是两块机器:大多数实验在一块 RTX 4090(24 GB 显存)上跑;而 KITTI 与 KITTI 360 里那些超过 4,000 帧的超长序列,换到一台 48 GB 显存的 L20 上,配 128 GB 内存[§4.1.2, p6]。这条信息比它看起来重要:它说明「公里级」这件事在当前硬件上仍然需要比消费级更高的显存档位,这与第 1 章账一(地图体量)是同一件事的两个说法。原文对系统形态的描述是:管道建在 MonoGS 的 PyTorch 代码结构上,用 CUDA 加速泼溅操作,并且用多进程把「跟踪、建图、回环」三件事拆开跑[§4.1.2, p6]。

最后是一条会影响所有画质读数的设置:渲染分辨率固定为宽 480 像素(高度按比例),评估时再用双三次插值放大回原分辨率。原文对这条的说明很坦诚,而且留了一个明确的口子:「如果用基于深度学习的超分算法,可能得到比本节所报更高的重建质量」[§4.1.2, p6]。这句话要记住,它意味着图 13-1 的 PSNR/SSIM/LPIPS 是在「低分辨率渲染 + 双三次放大」这条路径下量出来的,换一条更贵的放大路径,数字会变。

11.2 表 1:十三行基线、两个开关、两种失败记号

主表是 KITTI 十一个序列上的 ATE。

图 11-1:一张 4,000 帧、5,067 米的最难序列上,别人消失了、本篇还在(E 类 · 证据)· 原文 Table 1, p7
图 11-1 一张 4,000 帧、5,067 米的最难序列上,别人消失了、本篇还在(E 类 · 证据)· 原文 Table 1, p7 怎么读 ①图注:这张表的表头有 14 列,Methods、LC(是否用回环)、Render(是否能渲染)、Avg.(十一个序列的平均)、以及 00 到 10 十一个序列各自一列。表头之下先有三行灰色的元信息:seq. frames(各序列的帧数,最长的是 Seq. 01 的 4542 帧)、seq. length (m)(各序列的行驶长度,最长的是 Seq. 02 的 5067.23 米)、contains loop(该序列是否含回环)。Avg. 一列给出的是各方法的平均值,这一列是排序依据[Table 1, p7]。 ②读法:读这张表要按三个层次看,顺序不能反。第一层看「谁算得出来」:MonoGS 与 Splat-SLAM 两行的 Avg. 都是 /(算不出来),因为它们的格子里大量是 failed(原文用灰斜体标出)或带 × 上标的数。× 有专门的说明:它表示 Splat-SLAM 在建图模式下崩溃、这个数是在「只跟踪模式」下取到的,这些数字不是同一套配置下的结果。第二层看 Avg. 列的量级:本篇 w/ LC 是 15.576、w/o LC 是 16.437,次好的是 DF-VO 的 16.440,再往下跳一个档到 LDSO 22.425、DPV-SLAM++ 25.749,其余都在 53 到 100 之间。第三层才看单序列的胜负:在最长最难的那些序列上(02、06、09),本篇是加粗的那个(11.30、2.11、3.94),而在 00 与 01 上第一名分别是 ORB-SLAM2 w/ LC 的 6.03 与 DPV-SLAM 的 11.50,也就是说本篇不是每一格都赢,赢的是「平均」与「长序列」。 来源:GigaSLAM: Large-Scale Monocular SLAM with Hierarchical Gaussian Splats, Table 1, p7 · arXiv:2503.08071v2(CC BY 4.0,© 2025 Kai Deng, Yigong Zhang, Jian Yang, Jin Xie) · 原样引用,未修改

③复算:这张表里最值得当场算的是「本篇与 DF-VO 的差距有多小」。15.576 对 16.440,差 0.864 m,相对差 5.3%,平均值上只赢 5.3%。但把这两个数放到单序列上就完全是另一幅图:在 Seq. 02(5,067 米,全表最长)上,本篇 11.30、DF-VO 19.69,赢了 8.39 m,相对 42.6%;在 Seq. 06(1,232.88 米)上,本篇 2.11、DF-VO 3.20,赢了 1.09 m,相对 34.1%;在 Seq. 09(1,705.05 米)上,本篇 3.94、DF-VO 8.36,赢了 4.42 m,相对 52.9%。反过来在短序列上本篇是输的:Seq. 04 只有 271 帧、393.65 米,DF-VO 是 1.39、DPVO 是 0.68(全表最好),本篇是 1.88。把这几个数连起来看,结论是:「平均上小胜、长序列上大胜、短序列上小负」,这个形状与第 3 章那套论证完全一致(共视变稀与漂移累积都是长序列才发作的病)。另一个可以复算的是「回环值多少」:本篇 w/o LC 16.437 → w/ LC 15.576,平均改善 0.861 m,相对 5.2%;同一对在 Seq. 08 上是 9.48 → 7.04(改善 25.7%)、在 Seq. 06 上是 2.61 → 2.11(19.2%),回环的收益同样集中在长序列上。

④边界:这张表有三处必须交代的口径边界,否则会被误读。

第一,13 行里有两行的数字不可比。MonoGS 与 Splat-SLAM 的很多格子是 failed 或带 ×,而表注里写明了:DROID-SLAM 与 Splat-SLAM 用的是「通过位姿因子图做隐式回环检测」,这在室内有效、在大尺度室外失效[Table 1 图注, p7]。也就是说它们的失败源于「那条机制在这一档场景上不成立」,不是「实现没调好」,这与第 3.1 节的共视矩阵论证是同一件事。

第二,Render 这一列是这张表真正的筛选条件。表注的最后一句话是本篇的自我定位:「我们的方法是唯一一个既能从当前视角做高保真渲染、又能在长序列室外数据集上保持较强跟踪性能的方法」[Table 1 图注, p7]。把 Render 列竖着看:能渲染的只有 MonoGS、Splat-SLAM 与本篇三家,而前两家都算不出平均值,这句「唯一一个」是这么成立的,它不是「跟踪最准」,而是「两种能力都还在」。

第三,LC 列的 - 与 w/o LC 不是一回事。DROID-SLAM 与 Splat-SLAM 的 LC 列是 -(它们没有显式的回环开关,只有隐式的因子图回环),而 DF-VO、DPVO、DROID-VO 这些是「本来就没有回环」,表里用一个叉号标出。读表时不要把 - 当成「关闭」。

11.3 图 4:把三种重建摆在同一张图上比

图 11-1 量的是位姿,图 11-2 量的是地图。

图 11-2:同一段 KITTI 06,三种重建摆在一起(E 类 · 证据)· 原文 Fig. 4, p7
图 11-2 同一段 KITTI 06,三种重建摆在一起(E 类 · 证据)· 原文 Fig. 4, p7 怎么读 ①图注:这张图在 KITTI 06 上做定性对照,「从左到右依次是:全局重建、真值点云与轨迹、以及局部几何的放大视图」;参评的三家是本篇(标作 Ours LoD 0)、MonoGS 与 Splat SLAM[Fig. 4 图注, p7]。②读法:这张图的读法是「横向看列、纵向看行」。先纵向:同一列(比如左列的全局重建)竖着比三家,MonoGS 那一行给出的是「稀疏且有噪声的地图,细节大量丢失」;Splat SLAM 那一行「抓到了更多结构,但因为回环失败而出现严重的尺度不一致」;本篇那一行「在整条序列上重建出更一致的几何,即使在远处也更好地保住了场景细节」[§4.2, p7]。再横向:最后一列的放大视图是判据所在,原文说放大视图「凸显了本方法在捕捉细结构、避免过度泼溅上的优势」[§4.2, p7]。所以这张图真正要比的是「细结构」与「过泼溅」这两件事,前三列只是给它们提供上下文。判别的关键在「尺度不一致」这个词:它是可以从图上直接看出来的,如果同一条路上的物体在序列不同位置呈现出的尺度对不上,那就是尺度漂移的可视化形态。 来源:GigaSLAM: Large-Scale Monocular SLAM with Hierarchical Gaussian Splats, Fig. 4, p7 · arXiv:2503.08071v2(CC BY 4.0,© 2025 Kai Deng, Yigong Zhang, Jian Yang, Jin Xie) · 原样引用,未修改

③复算:这张图的三个判断都能在表里找到数字。「MonoGS 稀疏且有噪声」:图 11-1 里 MonoGS 在 Seq. 06 上是 137.22 m(同序列本篇 2.11 m),差 65 倍,这就是「稀疏且有噪声」在数值上的样子[表 1, p7]。「Splat SLAM 尺度不一致」:图 11-1 里它在 Seq. 06 上给的是 130.75 m,且多个序列带 ×[表 1, p7]。「本篇保住远处细节」:图 13-1 里本篇在 Seq. 06 上的 PSNR 是 24.17、SSIM 0.96、LPIPS 0.30,而 Splat-SLAM 是 17.90 / 0.61 / 0.66[表 3, p9],PSNR 差 6.27 dB,LPIPS 差 0.36。把这两组数放在一起:位姿差 60 倍、画质差 6 dB,两者是同一件事的两个量,位姿错了,重建的几何就错,渲染自然对不上。

④边界:这张图只展示了一条序列(KITTI 06),而且是「被挑出来展示」的一条,它在图 11-1 的 contains loop 行里标着「含回环」,也就是说这条序列是对本篇有利的一类(回环能起作用)。不能把这张图当成「任意序列上都这样」的证据。另一个边界是「真值点云那一列」:KITTI 的真值来自激光雷达点云与位姿,它自己也有配准误差,所以「贴不贴真值」这件事本身带噪声;本页在讲这一列时只引用原文的定性表述,不替它做定量判读。

11.4 图 7:轨迹图上的两种失败

最后一张与 KITTI 有关的图,把「别人怎么失败」画成了轨迹。

图 11-3:同一段轨迹上,DROID-SLAM 飘了、MonoGS 直接崩了(E 类 · 证据)· 原文 Fig. 7, p8
图 11-3 同一段轨迹上,DROID-SLAM 飘了、MonoGS 直接崩了(E 类 · 证据)· 原文 Fig. 7, p8 怎么读 ①图注:(左)是 KITTI 00 序列上各方法的轨迹估计;(右)是本篇在 4 Seasons 数据集上的结果[Fig. 7 图注, p8]。②读法:左半边的读法是「与真值比形状」。原文对这一段给了两个具体判断:本篇「在长室外场景上表现出稳定的跟踪」;DROID-SLAM「在长距离数据上呈现明显的尺度漂移」;MonoGS「在处理几百帧之后就崩溃、无法继续跟踪」[§4.2, p7]。图上要看的正是这三种形态:稳定 = 与真值缠绕在一起;尺度漂移 = 轨迹整体被拉伸或压缩,形状对但尺度不对;崩溃 = 轨迹在中途断掉。右半边的读法不同,它不是在比方法,而是在证明「换一个数据集也成」:4 Seasons 是另一套采集(不同季节、不同光照),它的序列形态与 KITTI 不同[Fig. 7 图注, p8]。 来源:GigaSLAM: Large-Scale Monocular SLAM with Hierarchical Gaussian Splats, Fig. 7, p8 · arXiv:2503.08071v2(CC BY 4.0,© 2025 Kai Deng, Yigong Zhang, Jian Yang, Jin Xie) · 原样引用,未修改

③复算:这张图上的三种形态都能在图 11-1 与图 13-3 里被量化。「DROID-SLAM 尺度漂移」:图 11-1 里它在 KITTI 的平均是 100.278 m(全表最差之一),单看 Seq. 01 更是 344.60 m,而同一序列 DF-VO 是 117.40、DPV-SLAM 是 11.50[表 1, p7],在 Seq. 01 上,最好的方法比 DROID-SLAM 好 30 倍。「MonoGS 几百帧后崩溃」:图 13-3 的漂移表里,MonoGS 那一行有七个序列是 /(没有值),只在 Seq. 01(99.4 / 27.02)与 Seq. 04(7.34 / 3.57)与 Seq. 06(101.73 / 10.82)留下了数[表 D.1, p17],「只留下三个序列的数」正是「跑到中途就断了」在表里的形态。「本篇稳定」:图 13-3 里本篇 w/o LC 在十一个序列上全有值,平移漂移在 1.05 到 41.08 之间[表 D.1, p17]。

④边界:这张图不承担任何「精度」上的论证,它没有刻度、没有数值,只能看形态;真正的数字在图 11-1 与图 13-3 里。另一个边界在右半边:4 Seasons 上「结果正常」这件事,在图上只是一条轨迹,而 A2D2 那个「没有真值」的数据集连这样的订正都做不了(只能投到地图上看)[§4.1.1, p6]。所以「换数据集还成立」这个结论,本篇给出的是三条强度不同的证据:KITTI 360 与 4 Seasons 有 ATE 数字(图 12-1 与图 13-3)> A2D2 只有可视化。

12换两个数据集:KITTI 360 与 4 Seasons

12.1 为什么要换:一条序列上的好可能只是运气

第 11 章的全部读数来自 KITTI 一个数据集。换数据集的目的是检验「这套机制是不是绑在 KITTI 的采集方式上」,而本篇选的这两个换法各有一层针对性:KITTI 360 是同一座城市但不同传感器与更长的轨迹(序列帧数最高到 14,607 帧,是 KITTI 最长序列的三倍以上),4 Seasons 是同一辆车在不同季节、不同光照下重复采集同一条路。

12.2 表 2:DROID-SLAM 在五个序列上 OOM

结果先摆出来:本篇在 KITTI 360 与 4 Seasons 上的平均 ATE 是 47.107 m(w/ LC)与 61.402 m(w/o LC),而 DROID-SLAM 的 Avg. 一列是 /。把这两个数据集并排放,就能看出「换数据集」考验的到底是什么。

图 12-1:换到两个数据集,别人的格子直接写 OOM(E 类 · 证据)· 原文 Table 2, p9
图 12-1 换到两个数据集,别人的格子直接写 OOM(E 类 · 证据)· 原文 Table 2, p9 怎么读 ①图注:这张表把两个数据集并排:左半是 KITTI 360(表头一行写 KITTI 360 Dataset),列为 Avg. 与 0000、0002、0003、0004、0005、0006、0007、0009、0010;右半是 4 Seasons(表头写 4 Seasons Dataset),列为 Avg. 与 Business Campus、Office Loop、Old Town、Neighborhood、City Loop。参评只有三家:DROID-SLAM、本篇 w/o LC、本篇 w/ LC[Table 2, p9]。 ②读法:这张表只有一个真正的读数要点:DROID-SLAM 那一行的右半是 OOM。原文在表注里写明了 OOM 的含义(out of memory),而它在 4 Seasons 的五个场景里出现了四次(Business Campus、Office Loop、Old Town、City Loop),第五个 Neighborhood 给出的是 158.19。在 KITTI 360 那一侧,它的平均列写的是 /,但单序列有值(110.07、233.87、10.79、169.11、139.02、113.81、577.39、165.34、220.36)。把这半边与表 1 对照:同一个方法在 KITTI 上是 100.278 的平均、在 KITTI 360 上是 /、在 4 Seasons 上是四个 OOM,换到更长、更密的采集上,它连「算完」都做不到。 来源:GigaSLAM: Large-Scale Monocular SLAM with Hierarchical Gaussian Splats, Table 2, p9 · arXiv:2503.08071v2(CC BY 4.0,© 2025 Kai Deng, Yigong Zhang, Jian Yang, Jin Xie) · 原样引用,未修改

③复算:这张表最值得算的是「4 Seasons 上的 372.64」这个异常值。本篇 w/o LC 在 City Loop 上是 372.64、w/ LC 是 362.13,而同表其余格子在 6.28 到 203.02 之间,372.64 是全表最大的正常值(不算 OOM)。原文没有对这个格子做解释,本页只把它标出来,不替原文归因。另一个可算的是回环的收益换数据集后是否还在:KITTI 360 侧,w/o LC 61.402 → w/ LC 47.107,改善 23.3%;4 Seasons 侧,99.098 → 92.950,改善 6.2%,两处都还在,而且 KITTI 360 上的收益(23.3%)比 KITTI 上的(5.2%)大得多。把这三个数并排看:5.2% / 23.3% / 6.2%,回环的收益不稳定,它取决于该数据集里「环」有多密、有多难检测(第 10.2 节讲的 BoW 检索的强弱)。

④边界:这张表只有两家方法可比(DROID-SLAM 与本篇),因此它不构成「比其他所有方法都好」的证据,MonoGS 与 Splat-SLAM 根本不在这张表里,原因可以推出来(它们在 KITTI 上已经大面积失败)。另一个边界是「OOM 的归因」:原文只写了 OOM 这个事实,没有说它是因为什么爆的;按第 3.1 节的论证可以推测是「因子图 + 稠密 BA 在超长序列上的代价」,但这是本页的推测,不是原文的陈述。

12.3 图 8 与图 C.1/C.2:把轨迹画出来

图 12-1 给的是数,接下来两张图给的是「那些数长在什么轨迹上」。先看 KITTI 360 上本篇与 DROID SLAM 的轨迹对照。

图 12-2:KITTI 360 上:本篇与 DROID SLAM 的轨迹对照(E 类 · 证据)· 原文 Fig. 8, p9
图 12-2 KITTI 360 上:本篇与 DROID SLAM 的轨迹对照(E 类 · 证据)· 原文 Fig. 8, p9 怎么读 ①图注:(左)是 KITTI 360 上的相机轨迹;原文对它的说明是「与因为尺度与计算问题而失效的 DROID SLAM 相比,本方法即使在长序列上也保持了稳定跟踪」[Fig. 8 图注, p9]。②读法:这张图的读法与图 11-3 的左半边一样,看两条轨迹是否缠绕、以及有没有中途断掉。它与图 11-3 的差别是「换了数据集」:KITTI 360 的轨迹更长、环更多,所以这张图检验的是「机制在更长的尺度上是否还成立」。注意 KITTI 360 这个数据集的一个重要性质:它的序列帧数在表 2 里最高到 14,607 帧(0002),而 KITTI 上最长的是 4,542 帧,三倍以上的长度。 来源:GigaSLAM: Large-Scale Monocular SLAM with Hierarchical Gaussian Splats, Fig. 8, p9 · arXiv:2503.08071v2(CC BY 4.0,© 2025 Kai Deng, Yigong Zhang, Jian Yang, Jin Xie) · 原样引用,未修改

③复算:14,607 帧这个数可以和图 12-1 里的距离一起算出一件事:0002 的序列长度是 11,501.28 米,也就是说平均每帧走了约 0.79 米,这是一个典型的车载采集速度(约 30 km/h 下每帧 0.8 米)。把这个数与本篇的显存账放在一起:14,607 帧、11.5 公里,而图 13-4 里 LoD 5 层时的显存是 8.62 GiB,这正是「公里级 × 消费级显存」这句话的由来。另一处可算的是 4 Seasons 的规模:City Loop 是 28,424 帧、10,352.74 米,全表最长的一条,而它恰好就是出现 372.64 那个异常值的序列。两个事实并排放,读者可以自己判断这两件事是否相关;本页不替原文下结论。

④边界:这张图与图 12-1 的 OOM 是同一件事的两个视角,图上只画了本篇与 DROID-SLAM 的轨迹,所以它不能用来比较「谁更准」(DROID-SLAM 在部分序列上根本没有值)。另一个边界是「KITTI 360 与 KITTI 的关系」:它们来自同一座城市(KITTI 360 是 KITTI 的扩展采集),所以「换数据集」这一层检验的强度有限,真正的跨域检验要靠 4 Seasons 与 A2D2。

补充材料里另有两张把 KITTI 与 KITTI 360 的全序列轨迹摊开画的图。

图 12-3:KITTI 全序列的轨迹摊开看(E 类 · 证据)· 原文 Fig. C.1, p18
图 12-3 KITTI 全序列的轨迹摊开看(E 类 · 证据)· 原文 Fig. C.1, p18 怎么读 ①图注:原文只有一句:「KITTI 数据集的相机轨迹可视化」[Fig. C.1 图注, p18]。②读法:这张图是「附录式的证据」,它把 KITTI 的序列逐个摊开画,用途是让读者自己核验「第 11 章那张表里的数是在哪些轨迹上量出来的」。看它的顺序是「先找序列号、再看轨迹形状」:注意图中的序列标记(Seq. 00、Seq. 02、Seq. 03、Seq. 05、Seq. 06、Seq. 07、Seq. 08、Seq. 09)。判定这张图看懂了没有的办法很简单:能不能把它与表 1 的列对上,表 1 有 00 到 10 十一个序列,而这张图只画了其中一部分,少掉的那几个是没有可视化的(本页不做推测)。 来源:GigaSLAM: Large-Scale Monocular SLAM with Hierarchical Gaussian Splats, Fig. C.1, p18(补充材料 §D) · arXiv:2503.08071v2(CC BY 4.0,© 2025 Kai Deng, Yigong Zhang, Jian Yang, Jin Xie) · 原样引用,未修改

③复算:这张图本身没有数字,能与它配对的定量读数是图 11-1 的十一个序列列[表 1, p7],以及图 13-3 的漂移表(那张表里序列列同样是 00 到 10)[表 D.1, p17]。三处的序列编号体系是一致的,这一点可以核:图 11-1 的列、图 13-3 的列、以及图 12-3 的标签,用的都是同两个数字的序列号(带前导零或不带),注意原文在这一点上并不严格:图 11-1 写作 00、01,而图 12-3 写作 Seq. 00、Seq. 02,图 12-4 里又变成四位数的 Seq. 0000(那是 KITTI 360 的编号体系)。记录这处不严格,是为了避免读者把两种编号当成同一套。

④边界:这张图不承担任何定量论证,它没有真值叠画、没有误差标注,只是轨迹形状。另一个边界是「它属于补充材料」:主文没有引用它,所以它的作用限于「给愿意核对的读者留一份原始材料」。

图 12-4:KITTI 360 的轨迹摊开看:注意序列编号换了一套(E 类 · 证据)· 原文 Fig. C.2, p18
图 12-4 KITTI 360 的轨迹摊开看:注意序列编号换了一套(E 类 · 证据)· 原文 Fig. C.2, p18 怎么读 ①图注:原文一句:「KITTI 360 数据集的相机轨迹可视化」[Fig. C.2 图注, p18]。②读法:它和图 12-3 是同一种图,但有一个必须注意的差别:序列编号换了体系。图 12-3 里的标签是两位数的 Seq. 00、Seq. 02,而这张图里是四位数的 Seq. 0000、Seq. 0002、Seq. 0003……,这不是同一批序列,前者是 KITTI 的序列号,后者是 KITTI 360 的序列号,两者只共享「同属一座城市」这一点。读它的顺序与图 12-3 相同:先找序列号,再看轨迹形状;判据是「轨迹有没有出现回折或断裂」(回折意味着回环被检测到并被修正,断裂意味着跟踪中断)。 来源:GigaSLAM: Large-Scale Monocular SLAM with Hierarchical Gaussian Splats, Fig. C.2, p18(补充材料 §D) · arXiv:2503.08071v2(CC BY 4.0,© 2025 Kai Deng, Yigong Zhang, Jian Yang, Jin Xie) · 原样引用,未修改

③复算:这张图里的序列号可以与图 12-1 的列逐个对上。图 12-1 的 KITTI 360 一侧列的正是 0000、0002、0003、0004、0005、0006、0007、0009、0010 九个序列[表 2, p9],与本图的标签体系完全一致。顺带可以算一下这九个序列的规模:帧数从 1,031(0003)到 14,607(0002),里程从 1,378.73 米(0003)到 11,501.28 米(0002)[表 2, p9],最短的一条只有 1,031 帧、最长的一条 14,607 帧,跨度超过 14 倍。这个跨度说明图 12-1 的平均值不是「同一量级的平均」,读那一列时要意识到它混合了差别很大的序列。

④边界:同图 12-3,补充材料、无真值叠画、只作核对用。另外提醒一处:本图与图 12-3 之间的关系是「同一座城市的两次采集」,因此「两张图都正常」并不构成跨域证据,真正的跨域证据在图 12-1 的 4 Seasons 那一半,以及 A2D2 的可视化(第 11.1 节已说明 A2D2 没有真值位姿、算不了 ATE)。

13渲染性能与消融:LoD 和各部件各值多少

13.1 表 3:渲染这一侧,本篇是唯一有数的

第 11 章与第 12 章量的是位姿;本章第一张表量的是画面。

图 13-1:渲染这一侧:两家给不出平均,本篇每格都有数(E 类 · 证据)· 原文 Table 3, p9
图 13-1 渲染这一侧:两家给不出平均,本篇每格都有数(E 类 · 证据)· 原文 Table 3, p9 怎么读 ①图注:这张表的结构是「三个方法 × 三个指标」:每家占三行,分别是 PSNR ↑、SSIM ↑、LPIPS ↓(箭头表示越大越好还是越小越好);列是 Avg. 与 00 到 10 十一个序列;参评三家是 MonoGS (RGB)、Splat-SLAM (RGB)、Ours (RGB)[Table 3, p9]。②读法:先看谁有平均值,再看数。MonoGS 那一组的 Avg. 列是 11.09 / 0.38 / 0.79,它有一个平均值,但这个平均的分母是残缺的:十一个序列格子里有五个 failed(Seq. 02、03、05、07、08 等);Splat-SLAM 那一组的 Avg. 是三行 /,连平均值都算不出来,格子里大量 failed;只有 Ours 那一组是三行完整数字:PSNR 平均 24.22、SSIM 平均 0.95、LPIPS 平均 0.31。这就是本节最要紧的一件事:「渲染性能」这一栏,本篇是唯一一家能把十一个序列都跑完并给出平均的。再看数本身:本篇的 PSNR 单序列在 22.71 到 25.22 之间(Seq. 05 最高 25.22,Seq. 02 最低 22.71),SSIM 在 0.94 到 0.97 之间,LPIPS 在 0.25 到 0.35 之间,十一格几乎是一条平线,这是「稳定」的读数形态。 来源:GigaSLAM: Large-Scale Monocular SLAM with Hierarchical Gaussian Splats, Table 3, p9 · arXiv:2503.08071v2(CC BY 4.0,© 2025 Kai Deng, Yigong Zhang, Jian Yang, Jin Xie) · 原样引用,未修改

③复算:这张表最该算的是「那一列 × 意味着什么」。Splat-SLAM 与 MonoGS 的部分格子带 × 或写着 failed,而图 11-1 的图注已经解释过 ×:那是在「只跟踪模式」下取到的值[表 1 图注, p7]。把它与图 13-1 并读,可以推出一件事:这两家「渲染性能」的读数,有一部分并不是「建图模式下的渲染」,也就是说,图 13-1 里那两组的数字与 Ours 那一组在配置上并不完全同源。这一点原文没有在图 13-1 的表注里重复说明,它写在图 11-1 的表注里,读跨表比较时,把两处表注一起看才不会误读。第二个可算的是「本篇内部的一致性好到什么程度」:PSNR 的平均 24.22、最低 22.71、最高 25.22,极差 2.51 dB;而 MonoGS 那一行可见的值(16.40、17.43、12.66、10.09 等)极差远大于此,「稳定」这件事在数字上的形状就是「极差小」。

④边界:这张表不能用来做「跨方法画质对比」,因为至少有一组的读数取在另一种模式下(见上)。能做的比较是「本篇自己稳不稳」与「谁跑完了」。另一个边界是 11.1 节那条渲染分辨率:所有数字都建立在「480 像素宽渲染 + 双三次放大」之上,原文自己说「换用超分算法可能拿到更高的质量」[§4.1.2, p6],所以图 13-1 是一组下界性质的读数,不是这套方法的画质上限。

13.2 表 4 与表 D.1:四个部件,各值多少

消融这一节回答的是「四个部件里,哪个真的在起作用」。

图 13-2:把部件一个一个加上去,看 ATE 掉多少(E 类 · 证据)· 原文 Table 4, p9
图 13-2 把部件一个一个加上去,看 ATE 掉多少(E 类 · 证据)· 原文 Table 4, p9 怎么读 ①图注:这张表只有两列,Method 与 ATE [m],五行依次是:MonoGS(137.22)、MonoGS + UniDepth(100.03)、Ours w/ LoD GS only(47.33)、Ours w/o LC(2.61)、Ours w/ LC(2.11)[Table 4, p9]。注意它的序列是 KITTI Seq. 06(原文的表注与正文都点了这一条)[§4.4, p10]。②读法:这是一张「加法的表」,读法是逐行相减。它把「从 MonoGS 走到本篇」拆成四步:① 先只加深度先验(MonoGS → MonoGS + UniDepth);② 再只加 LoD 的高斯表示(Ours w/ LoD GS only);③ 再加回环以外的全部(Ours w/o LC);④ 最后加上回环(Ours w/ LC)。判别的关键在「哪一步掉得最多」:从 137.22 到 100.03(第一步,掉 37.19)、从 100.03 到 47.33(第二步,掉 52.70)、从 47.33 到 2.61(第三步,掉 44.72)、从 2.61 到 2.11(第四步,掉 0.50)。 来源:GigaSLAM: Large-Scale Monocular SLAM with Hierarchical Gaussian Splats, Table 4, p9 · arXiv:2503.08071v2(CC BY 4.0,© 2025 Kai Deng, Yigong Zhang, Jian Yang, Jin Xie) · 原样引用,未修改

③复算:四次相减的绝对量与相对量一起算,形状就出来了。第一步 137.22 → 100.03,降 27.1%;第二步 100.03 → 47.33,降 52.7%;第三步 47.33 → 2.61,降 94.5%;第四步 2.61 → 2.11,降 19.2%。相对量最大的是第三步(94.5%),但它的绝对量与第二步相当(44.72 对 52.70),这说明第三步之所以「百分比巨大」,是因为分母已经不大了。从绝对量看:52.70(第二步)> 44.72(第三步)> 37.19(第一步)> 0.50(第四步)。这里有一个必须点出来的读法问题:这张表的五行不是「逐个开关」的正交消融,第二步(Ours w/ LoD GS only)与第三步(Ours w/o LC)之间还夹着「其余部件」,而表里没有把「其余」列出来。换句话说,第二到第三步之间那 44.72 m 的改善,不能归给某一个具体部件。本页把它标成一处「消融粒度到此为止」的地方,不替原文拆分。

④边界:这张表只用了一条序列(KITTI 06),而 137.22 这个起点是一个「失败值」(MonoGS 在这条序列上崩溃,第 11.3 节已经讲过),在一个失败值上做消融,得到的相对比例会被放大。另一个边界是「Ours w/ LoD GS only 这一行的含义需要靠原文的措辞来定」:表里没有解释这个词组,本页按字面理解为「只保留 LoD 高斯表示的本篇变体」,并如实标注这是字面理解。

另一张补充材料里的消融表是同一件事在「漂移」这个指标上的版本。

图 13-3:换两个指标再看一遍:漂移表上的 <code>MonoGS</code> 只剩三格有数(E 类 · 证据)· 原文 Table D.1, p17
图 13-3 换两个指标再看一遍:漂移表上的 MonoGS 只剩三格有数(E 类 · 证据)· 原文 Table D.1, p17 怎么读 ①图注:这张表的列是 00 到 10 十一个序列,行是五个方法各占两行:每条方法给两个指标,terr(平移误差)与 rerr(旋转误差);参评是 ORB SLAM w/o LC、DF-VO、MonoGS、Splat-SLAM、Ours w/o LC[Table D.1, p17]。②读法:这张表的用法是「看同一个方法在两个指标上是否一致」。判据是「平移漂移大、旋转漂移也大吗」,如果某个方法的 terr 大而 rerr 正常,说明它是「位置飘了但朝向没错」(典型的尺度漂移);如果两个都大,说明位姿整体失控。另一个用法是「看空格的形状」:空格的分布本身就是证据,MonoGS 那一行只有 Seq. 01、04、06 三格有值,其余全是 /,这正是第 11.4 节讲的「跑到中途就断了」在漂移表里的形态。 来源:GigaSLAM: Large-Scale Monocular SLAM with Hierarchical Gaussian Splats, Table D.1, p17(补充材料 §D) · arXiv:2503.08071v2(CC BY 4.0,© 2025 Kai Deng, Yigong Zhang, Jian Yang, Jin Xie) · 原样引用,未修改

③复算:拿「平移/旋转」这一对做一个交叉检验,能看出一件有意思的事:MonoGS 在 Seq. 01 上是 terr 99.4 / rerr 27.02,平移误差接近 100 米、旋转误差 27 度,两个都失控;ORB SLAM w/o LC 在 Seq. 01 上是 107.57 / 0.89,平移漂了 107 米,而旋转只有 0.89 度。这两个例子正好是上面那两条判据的教科书形态:ORB SLAM 是「位置飘了、朝向没错」,MonoGS 是「整段位姿失控」。再看本篇 w/o LC 的那两行:terr 在 1.05 到 41.08 之间,rerr 在 0.19 到 2.27 之间[Table D.1, p17],平移的最大值 41.08 出现在 Seq. 01(对,就是 ORB SLAM 飘 107 米、MonoGS 飘 99.4 米的那一条),而同一序列的旋转只有 0.92 度 ⇒ 本篇在那条难序列上的形态也是「位置飘、朝向稳」,只是绝对量小一个数量级。

④边界:这张表是补充材料,主文没有引用它,它提供的是「主结论的另一种指标下的复现」,不引入新结论。另一个边界是它比的是 Ours w/o LC,所以这张表里没有回环的贡献(回环的贡献在图 13-2 的最后一行)。

13.3 表 5:那个旋钮扫了五档

第 7 章已经用过这张表,这里补上它作为一张图的读法。

图 13-4:层数从 1 扫到 5:体素数掉 48 倍,PSNR 不是单调的(E 类 · 证据)· 原文 Table 5, p10
图 13-4 层数从 1 扫到 5:体素数掉 48 倍,PSNR 不是单调的(E 类 · 证据)· 原文 Table 5, p10 怎么读 ①图注:这张表六列,Level(s) Num.(层数)、Voxel Size(各层体素尺寸)、Distance Partition(距离分割阈值)、Avg. Frustum Vox. Num.(视锥体内平均体素数)、PSNR、GPU MEM(显存占用);行为 1 层到 5 层[Table 5, p10]。②读法:这张表要同时盯三列:体素数、PSNR、显存。它的读法是「看体素数与 PSNR 是否同步下降」,如果两列一起降,说明「省下来的每一点都付了画质」;如果体素数大降而 PSNR 不掉,那就是纯赚。五行的三列读数依次是:1 层 411,612 / 24.29 dB / 22.46 GiB;2 层 223,627 / 24.64 / 15.82;3 层 116,639 / 24.05 / 11.77;4 层 34,721 / 24.21 / 9.46;5 层 21,342 / 24.17 / 8.62。另外注意 Distance Partition 这一列的分段结构:2 层只有 [20] 一个阈值,5 层是 [20, 40, 80, 160] 四个,阈值个数 = 层数 − 1,这与式 (6) 里 {r_1, …, r_{m−1}} 只有 m − 1 个是一致的。 来源:GigaSLAM: Large-Scale Monocular SLAM with Hierarchical Gaussian Splats, Table 5, p10 · arXiv:2503.08071v2(CC BY 4.0,© 2025 Kai Deng, Yigong Zhang, Jian Yang, Jin Xie) · 原样引用,未修改

③复算:三个可算的量,一起能看出这张表的「甜点」在哪。

第一,体素数的压缩比:1 层 411,612 → 5 层 21,342,压缩 19.3 倍;其中 1→2 层就砍到一半(0.543 倍)。

第二,显存的压缩比:22.46 → 8.62 GiB,降到 38.4%;同样 1→2 层降幅最大(22.46 → 15.82,降 29.6%)。

第三,PSNR 的代价:1→2 层涨 0.35 dB(纯赚);2→3 层掉 0.59 dB;3→4 层涨 0.16 dB;4→5 层掉 0.04 dB。把这四个变化量按大小排序:−0.59 > +0.35 > +0.16 > −0.04,唯一一次明显下滑发生在 2→3 层这一步。把三件事合起来,结论是「2 层是这张表上的甜点」:它在体素数上已经砍掉一半、显存降了近三成,同时 PSNR 是五档里最高的。原文后面所有主结果用的也是 2 层(13.1 与 13.2 两张表的配置)。

④边界:这张表只在 KITTI 06 一条序列上扫,所以「2 层最优」这个结论是「在这一条序列上最优」;换一条序列、换一座城市,最优层数可能不同(这是「手调阈值」这个代价的表现形式,第 14 章会列成一条前提)。另一个边界是 Avg. Frustum Vox. Num. 的含义:它是「视锥体内平均体素数」,不是「全图体素数」,两者不可混用:LoD 改变的正是「这一帧要看多少体素」,而全图的体素总数并不因此减少(地图该有多大还是多大)。这一点在读「省了多少」时特别容易搞错:本篇省的是「每帧的渲染负载」,不是「地图的存储总量」。

13.4 图 5、图 6 与图 C.3/C.4:画质这一侧的四张图

前三节是表,本节是图。

图 13-5:两次大转弯处,Splat-SLAM 掉下去了(E 类 · 证据)· 原文 Fig. 5, p7
图 13-5 两次大转弯处,Splat-SLAM 掉下去了(E 类 · 证据)· 原文 Fig. 5, p7 怎么读 ①图注:原文的说明是:「Splat-SLAM 与本方法在 KITTI-06 上渲染效率的对照。Splat-SLAM 因为可见高斯过多而在 U 形转弯处效率下降、影响远处细节,而本方法保持稳定。」[Fig. 5 图注, p7]。②读法:这张图的横轴是序列进度、纵轴是效率类指标,读法是「找尖峰」,U 形转弯在图上对应的是曲线的一次突刺;判据是「尖峰有多高、以及它之后能不能回落」:Splat-SLAM 的尖峰之后效率没有回到原位(或者回落得很慢),而本篇的曲线是一条平线。注意正文里对这条曲线有一条很具体的读数:「在 KITTI-06 序列里,Splat-SLAM 的 active 3D Gaussian ratio 在两次 U 形转弯之后冲到接近 80%,导致不稳定的计算」[§4.3, p9]。这个「接近 80%」是本章唯一一个可以直接引用的百分数。 来源:GigaSLAM: Large-Scale Monocular SLAM with Hierarchical Gaussian Splats, Fig. 5, p7 · arXiv:2503.08071v2(CC BY 4.0,© 2025 Kai Deng, Yigong Zhang, Jian Yang, Jin Xie) · 原样引用,未修改

③复算:「接近 80%」这个数可以和图 13-4 的第一行对照着算。第 7.4 节讲过,本篇把视锥体内的平均体素数从 411,612 压到 8,616 那一档(5 层),本篇的主结果是 2 层,所以主配置下的视锥体素数是 223,627。无论取哪一档,「一帧要看的东西」都被压在了十万量级或更低;而 Splat-SLAM 在转弯处让 active 高斯的占比冲到 80% ⇒ 两者不是同一个量级的负载。这里要小心一处口径:「active Gaussian ratio」是「活跃高斯占全部高斯的比例」,而图 13-4 给的是「视锥体内体素数」,两个量不是同一量纲,不能直接相除。本页只把它们并排呈现,不做跨量纲的换算。

④边界:这张图只画了 KITTI-06 一条序列,而且它是被专门挑出来展示「转弯」的(因为转弯是最不利的形态)。它不说明「本篇在任何轨迹形态上都稳」,例如自由漫游、频繁跳变的轨迹,本篇没有在图上给出对照。另一个边界是图注里那句「影响远处细节」:这是原文的定性判断,图 13-5 本身没有给出「远处细节」的定量指标,那个指标在图 13-1(PSNR/SSIM/LPIPS 的整序列平均)里,两者不能互相替代。

图 13-6:四条序列的渲染对照:本篇稳、两家不稳(E 类 · 证据)· 原文 Fig. 6, p8
图 13-6 四条序列的渲染对照:本篇稳、两家不稳(E 类 · 证据)· 原文 Fig. 6, p8 怎么读 ①图注:「KITTI 数据集上 MonoGS(RGB 输入)、Splat-SLAM 与本方法的渲染结果;本方法在延长的室外序列上保持了稳定渲染,而 MonoGS 与 Splat-SLAM 在这个场景上很吃力。」[Fig. 6 图注, p8]图内分成两组:Sequence 07 & 08 与 Sequence 09 & 10。②读法:这张图的读法是「横扫一行、竖看一列」。竖看一列(同一段路、不同方法):问的是「哪一家的画面里,路面、栏杆、远处的建筑还在」;横扫一行(同一方法、不同序列):问的是「这家在第 7-8 条序列上还行,到第 9-10 条是不是就崩了」。原文给的判据是「稳定 vs 吃力」,这是一句定性判断,所以这张图的用法是「印证前四张表的结论」,不是「给出新结论」。 来源:GigaSLAM: Large-Scale Monocular SLAM with Hierarchical Gaussian Splats, Fig. 6, p8 · arXiv:2503.08071v2(CC BY 4.0,© 2025 Kai Deng, Yigong Zhang, Jian Yang, Jin Xie) · 原样引用,未修改

③复算:这张图覆盖的序列是 07、08、09、10 四条,把它与图 11-1 的对应列配起来算:本篇在这四条上的 ATE 分别是 2.12、7.04、3.94、2.18(w/ LC),Splat-SLAM 是 14.35、52.07×、27.42×、63.55,MonoGS 四个全是 failed[表 1, p7]。四条序列上,本篇的最大 ATE 是 7.04 m、其余三条在 2–4 m 之间;而 Splat-SLAM 只有在 Seq. 07 上给出了 14.35(就是它唯一一个不带 × 的长序列值)。「稳定渲染」这句话在数上的形态就是「ATE 都小且相近」。

④边界:这张图是「被挑出来展示」的四条序列,它们的共同点是「都含回环」或「都较长」(图 11-1 的 contains loop 行里,07、08、09 都标含回环)。不能把这张图读成「所有序列都这样」。另一个边界与本篇的渲染分辨率有关:480 像素宽的渲染在放大回原分辨率之后,观感上的差异会被放大(缩放引入的模糊会掩盖或放大某些瑕疵),所以这类定性图的判读,比图 13-1 的数字更容易受展示方式影响。

补充材料里另有两条把 KITTI 的渲染结果整段摊开画的图。

图 13-7:KITTI Seq. 00–06 的渲染结果全摊开(E 类 · 证据)· 原文 Fig. C.3, p19
图 13-7 KITTI Seq. 00–06 的渲染结果全摊开(E 类 · 证据)· 原文 Fig. C.3, p19 怎么读 ①图注:原文一句:「KITTI 数据集 Seq. 00 到 06 的渲染结果」[Fig. C.3 图注, p19]。②读法:这是「附录式的证据」,它把前七条序列的渲染结果逐格摊开,用途是让读者核对「表 3 里那些 PSNR 数字是从什么样的画面上量出来的」。看它的顺序是按序列号逐格扫,问的是「有没有哪一格里路面或结构明显塌了」。判据与图 13-6 相同,只是样本量更大。注意这张图的纵横比是 0.806(宽 525.6 pt × 高 652.3 pt),它几乎占满一整页,是本篇 20 件图元里最高的一件(第 5.3 节的位置档表已把它列入 wide 覆写集)。 来源:GigaSLAM: Large-Scale Monocular SLAM with Hierarchical Gaussian Splats, Fig. C.3, p19(补充材料 §D) · arXiv:2503.08071v2(CC BY 4.0,© 2025 Kai Deng, Yigong Zhang, Jian Yang, Jin Xie) · 原样引用,未修改

③复算:这张图覆盖七条序列,图 13-1 的 PSNR 一列在同样七条上是:Seq. 00 24.14、01 24.91、02 22.71、03 24.40、04 25.22、05 24.92、06 24.17[表 3, p9]。七格里有六格在 24.1 以上,唯一明显低的是 Seq. 02 的 22.71,而 Seq. 02 恰好是图 11-1 里全长最长的一条(5,067.23 米)。两个事实并排放:最长的一条序列画质最低、且它的 ATE(11.30)仍是全序列最好的那一档,也就是说长序列上本篇「位置准、画面略糊」,而不是「两项一起崩」。

④边界:这张图属于补充材料、主文未引用,且不含真值对照(只是渲染结果),因此不能用来做误差归因。另一个边界是它与图 13-8 的分界:两张图按序列号切开(00–06 与 07–10),读者若要核对某一条序列,需要先确认它在哪一张上。

图 13-8:KITTI Seq. 07–10 的渲染结果(E 类 · 证据)· 原文 Fig. C.4, p20
图 13-8 KITTI Seq. 07–10 的渲染结果(E 类 · 证据)· 原文 Fig. C.4, p20 怎么读 ①图注:原文一句:「KITTI 数据集 Seq. 07 到 10 的渲染结果」[Fig. C.4 图注, p20]。②读法:与图 13-7 同法,但它的样本特性不同:表 1 的 contains loop 行里,07、08、09 三条都含回环,10 不含 ⇒ 这张图里混着「回环能帮上忙」与「回环帮不上」两类序列,从画面上未必分得出。这一点值得记住:定性图不携带「这条序列含不含回环」这个信息,必须回表 1 查。注意这张图的纵横比是 0.992、框宽 498.5 pt(版心的 100.7%),也是 wide 覆写集里的一件。 来源:GigaSLAM: Large-Scale Monocular SLAM with Hierarchical Gaussian Splats, Fig. C.4, p20(补充材料 §D) · arXiv:2503.08071v2(CC BY 4.0,© 2025 Kai Deng, Yigong Zhang, Jian Yang, Jin Xie) · 原样引用,未修改

③复算:这四条序列在图 13-1 里的 PSNR 是:Seq. 07 24.88、08 23.42、09 23.03、10 24.09[表 3, p9]。四条的平均是 23.855,比 00–06 那七条的平均(约 24.35)低约 0.5 dB。把它与 ATE 一起看:本篇在这四条上的 ATE 是 2.12、7.04、3.94、2.18(w/ LC)[表 1, p7],ATE 与 PSNR 都劣于前七条。也就是说「后四条更难」这件事在位姿与画质两侧是一致的,这比单看一侧更有说服力。

④边界:同图 13-7,补充材料、无真值、只作核对用。另外要提醒一处:这两张补充图的标签体系与图 11-1 不同(图里写 Seq. 07 到 Seq. 10,而 KITTI 360 的图里写四位数 Seq. 0000),读跨图时不要混。

14它要什么前提,又在哪儿会失手

14.1 原文自己列了两条局限

它在三种情形下会失手:阈值靠手调、回环在纹理稀薄处会漏、换到没见过的场景会变脆。而这些交代绝大部分写在补充材料 §E,不在主文的结论段:主文的第 5 章只有三句话(把方法复述一遍 + 说它扩展了高斯泼溅 SLAM 的适用范围),真正的局限段在附录[§5, p10;补充 §E, p17]。

局限一:动态场景不支持。原文的措辞是把「扩展静态假设」列为未来工作[补充 §E, p17]。这条局限在本篇的架构里是根上的:整套机制建立在「体素锚点 + 偏移量」这个静态骨架之上,而体素的层次划分(式 (5))与去重(式 (11))都假定「同一块空间只有一份内容」;场景一旦动起来,同一个体素在不同时刻该表达不同的东西,而地图里没有「时刻」这个维度。

局限二:Sim(3) 优化的泛化性有限。原文承认这套回环修正「紧密沿用既有工作,可能无法泛化到未见场景」[补充 §E, p17]。这条说的是:它不是一个「学会了怎么回环」的模块,而是一段手写的、建立在几个假设之上的优化,那些假设(比如「回环对之间的相对变换可以先冻结成常数」,第 10.5 节)在没见过的场景形态下未必成立。

14.2 除了原文列的两条,本篇还有三处「架构上的前提」

下面三条不是原文自称的局限,而是本页从它的机制里读出来的前提,区分这一点很重要(前者是作者的自我判断,后者是读者的推读)。

前提一:尺度必须从外部来。第 9 章整条前端都建在 UniDepth 给出的度量深度上(式 (B.3) 的三维点全部来自它)[§3.3, p5]。后果是:「以米为单位」的所有读数(ATE 15.576 m、47.107 m 这些)都是「在某个特定深度模型下」的读数。换一个深度模型、或者换一批与 KITTI 风格差异更大的数据,尺度基准就变了,而原文没有做深度模型的替换消融(图 12-1 与本篇的所有实验都固定用 UniDepth)。

前提二:LoD 的阈值是手调的,且没有自适应机制。图 13-4 那五个配置里的 [0.1, 0.25, 1, 5, 25] 与 [20, 40, 80, 160] 是选的,不是算的[表 5, p10]。原文没有给「换一个场景该怎么选」的规则,也没有做「阈值扰动下的敏感性分析」。第 7.4 节那个「2→3 层掉 0.59 dB」的读数已经是能拿到的最近似敏感性证据,但它只有一个点的粒度。

前提三:回环检测依赖图像检索,纹理稀薄处会漏。第 10.2 节的 DBoW2 + ORB 是整条回环链的入口,而它在白墙、夜空、大面积同质纹理上会给出很弱的匹配。原文对这一点的表述出现在讨论其它方法的失败时:「Splat-SLAM 因为回环失败而出现严重的尺度不一致」[§4.2, p7],作者知道「回环失败」是什么样的病,但本页没有找到它对本篇自己在弱纹理场景下漏检的定量评估。本页因此把它列为一条未量化的前提,不写成「已知缺陷」。

14.3 三处「代价」照写

代价一:超长序列需要更大的显存档位。原文的实验配置里写着:超过 4,000 帧的序列换到 48 GB 显存的 L20 上[§4.1.2, p6]。这与第 1 章账一(地图体量随场景线性增长)是同一件事,LoD 压掉的是「每帧的渲染负载」,不是「地图的总存储量」(第 13.3 节的边界里已经点过这一处口径)。这条路并没有把「体量」这件事从根上消掉,它只是把「每帧要用多少」与「总共存了多少」解耦了。

代价二:渲染是在 480 像素宽下做的。原文自己承认「换用超分算法可能拿到更高的质量」[§4.1.2, p6]。这意味着图 13-1 那组 PSNR 是一组「低成本路径下的读数」,它既是诚实的(没有把超分的好处算进去)、也是保守的。

代价三:回环的收益不稳定。第 12.2 节算过三个数据集上的回环改善:KITTI 5.2%、KITTI 360 23.3%、4 Seasons 6.2%[表 1, p7;表 2, p9]。同一个机制在不同数据上的收益差了四倍以上,而原文没有解释这个差异的成因,它取决于该数据集里「环」的密度与检测难度(第 10.2 节讲的 BoW 检索强度),但这是本页的推测。

14.4 把整篇压成一段话

这一篇要解决的问题是「只用一段单目视频,把一座城市走十几公里」。它的难点不在「算得准」,而在两笔互相拉扯的账:地图要省(否则铺不开),但漂了之后要能动全图(否则长序列上一定歪)。

它的处置有四个动作,其中两个是关键:把高斯挂在一棵按相机距离分层的稀疏体素树上(第 6–7 章),于是每帧要看的东西与全图规模解耦(视锥体内平均体素数从 411,612 压到 223,627,2 层配置下显存从 22.46 降到 15.82 GiB);把位姿从渲染损失里挪到几何里(第 9 章),于是「位姿与渲染互为因果」那个正反馈环被剪断;再补上一条显式的 Sim(3) 回环链(第 10 章),并专门为高斯地图设计了一套分批的整图刚体更新(式 (13)(14))。

账面:KITTI 平均 ATE 15.576 m(对次好的 DF-VO 是 16.440,平均只赢 5.3%,但在最长的 Seq. 02 上赢 42.6%);KITTI 360 与 4 Seasons 上 47.107 m,而 DROID-SLAM 在 4 Seasons 的五个场景里有四个直接 OOM;渲染侧 PSNR 24.22 dB / SSIM 0.95,而且它是唯一一家能把十一个序列都跑完并给出平均的。

它最值得带走的一句判断是:这套方法省下来的不是「算了多少次」,而是「每帧要从地图里取多少东西」,地图该多大还是多大,但一帧只碰其中一层。这句话也标出了它的天花板:LoD 是一个按距离切的、手调阈值的分层,它不学习、也不自适应;再加上尺度来自外部深度模型、回环靠图像检索、动态场景不支持这三条前提,它解的是「静态、已知屏级尺度、纹理足够」这一类室外长序列,而不是所有室外场景。

这一篇的交接到此为止:32 条编号式、20 件原文图元、6 条边界与前提都已逐条落到章节里。回看整篇,有一条线值得带走:在公里级的室外长序列上,真正会把人拖死的是两笔互相拉扯的账,地图要省、但漂了之后要能动全图。本篇的两处处置刚好各接一笔:层次稀疏体素把「每帧要用多少」与「全图有多少」解耦(视锥体内平均体素数从 411,612 压到 223,627,显存从 22.46 GiB 降到 15.82 GiB),几何前端把位姿从渲染损失里挪出去、剪断了那个正反馈环(KITTI 平均 ATE 15.576 m,最长的 Seq. 02 上比次好的 DF-VO 低 42.6%)。而它的代价也很具体:LoD 的阈值是手调的、尺度要从外部深度模型借、回环靠图像检索会在弱纹理处漏、动态场景目前不支持。

出处与许可。本篇是 arXiv 预印本(arXiv:2503.08071v2,2025-06-10;v1 2025-03-11),没有标注会议或期刊;源码用的是 ICCV 2025 投稿模板(\def\paperID{7355}、\def\confName{ICCV}、\def\confYear{2025}),但那只是模板、不是出处[所据版本;源码 main.tex]。作者四人:Kai Deng、Yigong Zhang、Jian Yang、Jin Xie,分属南开大学(天津)与南京大学苏州校区(源码里还有一行被注释掉的第三家单位,本页不把它算进作者单位);代码地址写在摘要末尾:https://github.com/DengKaiCQ/GigaSLAM[摘要]。许可判定登记在 选簇与台账.md §二:所据 PDF 内没有任何权利块(Copyright/©/Permission/license(d)/Creative Commons/CC BY/nonacm/All rights reserved/Not for redistribution/owner/author/ISBN/978-/ACM/DOI 全部 0 命中;IEEE 的 38 处全在参考文献),以 arXiv 摘要页为唯一证据源,该页许可图标指向 creativecommons.org/licenses/by/4.0/ ⇒ 取 CC BY 4.0,落点三件(index.html + 封面缩略图 + 托管原文 paper.pdf)、卡片 chip 不带 warn、图件原样零加工引用 + 逐图四字段署名(图号/页码/版权/未修改;版权栏写 © 2025 Kai Deng, Yigong Zhang, Jian Yang, Jin Xie,本篇 PDF 内没有任何版权声明,按 arXiv 预印本的实际著作权人署名)。

三处必须自己核过的取证事实。第一,32 条编号式的数与位置。批次清单记「式 11」,实测主文就是 14 条,其中 (2) 与 (7) 是「行内编号式」(编号与式子同行、右缘对齐栏右缘),按「整行等于 (N)」的普查会漏;反过来,∈SE(3) 这类右端恰好以 (3) 结尾的行会被误判成编号式(p6 y=522.3 实测一例),判据是「编号右缘是否与栏右缘对齐」(本篇独立成行者右缘 553.5/303.0,误判那行停在 294.8)。再加补充材料的 (B.1)–(B.5) 与 (C.1)–(C.13) 共 18 条 ⇒ 全篇 32 条。第二,本篇的公式有权威底本,判形不必靠肉眼。arXiv 的 e-print 源码可直接下载(https://arxiv.org/e-print/2503.08071,10.4 MB,含 main.tex/sec/*.tex/preamble.tex),32 条编号式的 LaTeX 源逐条在库;式 (5) 那两个「伸长定界符」的判形因此有两条独立证据链:嵌入 Type1 字体的 /Encoding 字形名是 floorleftbigg/floorrightbigg(即下取整 ⌊ ⌋),源码写的是 \left\lfloor \right\rfloor,两条互相印证。顺带记一处源码与 PDF 的差异:源码里两节附录(Replica Dataset 与 Detailed Rendering Performance on the Replica Dataset)被注释掉了,所以 PDF 的附录只有 A–E 五节;读者若在别处看到 Replica 的渲染性能表,要知道它没有进这一版。第三,图注与表注都在体下方。阶段 1 曾按 CVPR 惯例先写「表注在表体上方」,阶段 2 实测六张表全部相反(注顶到末横线 7.2/8.96/11.1/7.2/11.1/50.2 pt),判据只能实测,不能凭体例经验(这一条已记入 backlog-batch01.md §二十)。

最后交代一下本篇在系列中的读法。它是一篇「机理 + 系统」型的论文,而且式的分布极不均匀:32 条编号式里 23 条集中在两章(第 9 章的 (B.1)–(B.5) 与第 10 章的 (12)(13)(14) + (C.1)–(C.13)),20 件图元里 18 件压在后三章(第 11–13 章),而中间那七章(第 2、5–10 章)一件图元都没有,那七章全靠式撑着。读它的顺序建议是:先读第 3 章(长序列上会塌哪两样,全篇的靶子都在那里),再读第 5 到第 7 章(体素、LoD 与那三笔账,这是本篇自己的发明),最后回到第 9 与第 10 章(一个是被借来当配件的前端、一个是主文与补充各写一遍的后端);第 11 到第 13 章那五张表可以留到最后当核对用,因为它们的每一行都在回答前面某一条论断。

本页完