☰
Spirula Studio 增量式 Mapper vs Bottom-up 重建:3D 高斯泼溅 SfM 两种调度策略硬核对比
2026/9/28 21:14:07 网站建设 项目流程

Spirula Studio 增量式 Mapper vs Bottom-up 重建:3D 高斯泼溅 SfM 两种调度策略硬核对比

【免费下载链接】spirula-studioCross-vendor 3D Gaussian Splatting trainer - video to splat to mesh, Vulkan or CUDA.项目地址: https://gitcode.com/GitHub_Trending/sp/spirula-studio

Spirula Studio 是一款跨厂商的3D Gaussian Splatting(3D 高斯泼溅)训练器,支持"视频 → Splat → Mesh"的完整流程,可运行在 Vulkan 或 CUDA 后端。其内置的 SfM(运动恢复结构)模块提供了两种相机位姿重建调度策略:flat(增量式 Mapper,默认)与bottom-up(自底向上原子合并)。本文将从原理、成本、并行度三个维度,帮你在跑 3DGS 训练数据前搞清楚这两者的区别与选择方法。

先搞懂背景:重建阶段在整个流水线里的位置

Spirula Studio 的 SfM 模块(src/sfm/README.md)是一条独立管线:

images/ → extract → match → map → assemble → sparse/0..N → 训练

其中map这一步就是"Mapper"的舞台。两种调度策略的区别不在算法本身——每个模型仍然由同一个 Mapper 按同样的规则构建,也用同一个 Sim(3) 合并器拼接——而在"成本和风险放在哪里"(设计决策 D55,见 docs/notes/sfm-design.md)。

两种调度策略是什么

flat:一次增量重建搞定整段拍摄 🧱

默认策略。一个 Mapper 对整段拍摄做一次增量重建:从种子对出发,注册一张图、三角化一点、每隔若干倍增长做一次全局 BA(Bundle Adjustment),直到整段拍摄变成一个(或几个)大模型。

它的痛点在 src/sfm/map/Bottomup.h 的头部注释里说得很直白:

增量式 Mapper 先构建一个大模型,然后才去发现它够不到的地方——于是所有昂贵的大模型级遍历(全局 BA、重三角化、滤波)都在满尺寸上运行,每一次修复也在满尺寸上运行。

bottom-up:切成"原子",逐层向上合并 🧬

--mapper bottom-up把调度反过来(src/sfm/map/Bottomup.h):

  1. 切:已验证的视图图用归一化割切成若干"原子",每个约48 张图(src/sfm/map/Partition.h);
  2. 建:每个原子由自己的 Mapper 在自己的子数据库上独立重建,且全部并发执行(src/sfm/map/Atoms.h,决策 D59)——48 张图的原子,其全局遍历几乎零成本,失败模式也是局部化的;
  3. 合:原子之间按层向上合并,每层每个模型最多吸收一个其他模型;没合并上的模型靠 PnP 增长补图,层与层之间做一次覆盖全部模型的联合 BA(src/sfm/map/Assemble.h,决策 D63)。

三个关键差异深挖

差异 1:成本发生在什么时候

两种策略的大部分时间都花在 Bundle Adjustment 上,而且大多数解算是"临时"的——一次增长精化后还有一轮增长。flat 策略里这些临时解算都在大模型上跑;bottom-up 里它们发生在 48 图的小模型上,"一个小原子的整模型遍历根本不算什么开销"(src/sfm/README.md 原话)。

差异 2:并行度与故障隔离

原子之间构造上互相独立,所以可以并行。Atoms.h 的做法很聪明:给每个原子一个"自己的 Mapper + 自己的子数据库"(局部重新编号),这样:

  • 无需任何加锁——私有对象天然线程安全;
  • 唯一的共享资源是 Vulkan 上下文,每个工作线程创建一个复用到该线程的所有原子(创建上下文比重建一个原子还贵);
  • 实测:一次 5402 张图拍摄中,原子阶段从"单核串行 721 秒"变为多线程并发完成,而原子数量上限默认 8(每个上下文映射两块 64 MB staging buffer,再多的并发改是抢同一块 GPU)。

差异 3:共享内参 + 构造性重叠,合并为什么可靠

小原子有两个"先天缺陷",bottom-up 用两个机制根治:

  • 40 张图的原子定不准自己的焦距。所以整个数据库先统一 bootstrap 一次内参,所有原子继承;且飞行中所有模型按相机组共享内参联合 BA(决策 D57)——"合并时没有任何东西需要平均,因为没有任何东西偏离过";
  • 两个没有公共内容的原子只能靠增长(慢路径)拼接。所以相邻原子按--bup-overlap(默认 12 张)互相借用图像,Sim(3) 对齐正是锚定在这些重叠图像上。

48 还是 96?文档不敢写的"踩坑数字"

Bottomup.h 的注释里藏着一段珍贵的实测记录——原子尺寸为什么是 48:

原子尺寸实测表现
48(默认)图像槽位开销 2.1–2.4×,约占总耗时 40%,但 1322 图拍摄只产出 1 个大模型
96(试过)快 1.2–2.1×,但 798 图拍摄中半个场景偏移了半个场景宽度(折叠故障,且"注册图像更多、中位旋转误差更好"——折叠的典型签名);1322 图拍摄留下 6 个碎片

更扎心的是:更严的合并阈值、更紧的树 BA、先切原子——全都没拦住这个故障,交叉接缝测试 15 次合并只拦下 1 次。--bup-atom-size因此保留给"能自己验证结果的拍摄"用。

如何开启 Bottom-up 模式:3 步上手

  1. 构建:bash build_develop.bash -DSS_BACKEND=vulkan(SfM 模块仅 Vulkan,无 CUDA 路径);
  2. CLI 运行:spirula sfm auto IMAGES/ -o ws/ --mapper bottom-up,可选--bup-atom-size 48 --bup-overlap 12微调原子;
  3. GUI 运行:在 SfM 选项编辑器的 Mapper 字段选择 bottom-up,中文帮助即"把视图图切成小原子分别重建再逐层向上合并"(src/i18n/catalog/SfmFields.h)。

选择建议:官方刻意没有按图像数量自动切换策略——flat 对任何拍摄都是默认值,因为 bottom-up 尚未在足够多的拍摄上测量过,"在你某个图像数量处悄悄换策略,会让任何两次运行的对比都变成疑问"(src/sfm/SfmConfig.h)。新手请安心用 flat 默认值;只有当大拍摄的 map 阶段明显耗时,且你具备验证重建结果的条件时,再尝试 bottom-up。

相关文件导航

  • SfM 模块总览与阶段图:src/sfm/README.md
  • 自底向上调度主体:src/sfm/map/Bottomup.h
  • 原子并发重建:src/sfm/map/Atoms.h
  • 视图图归一化割切:src/sfm/map/Partition.h
  • 两策略共享的收尾调度:src/sfm/map/Assemble.h
  • 设计决策日志(D55/D57/D59/D63):docs/notes/sfm-design.md
  • SfM 移植计划:docs/notes/sfm-port-plan.md
  • 项目主文档:docs/README.md、docs/architecture.md

总结

  • flat:简单可靠,所有临时解算都在满尺寸模型上跑,默认之选;
  • bottom-up:小原子 + 并发 + 共享内参 + 构造性重叠,把成本降到局部、把故障关进笼子,代价是约 40% 的调度开销和对原子尺寸的敏感性;
  • 两者殊途同归:都汇入同一个 Assemble 收尾调度,回归问题不会与几何算法本身混淆——这正是"调度"而非"算法"的设计价值所在。

【免费下载链接】spirula-studioCross-vendor 3D Gaussian Splatting trainer - video to splat to mesh, Vulkan or CUDA.项目地址: https://gitcode.com/GitHub_Trending/sp/spirula-studio

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询