Part III · 第 12 章 三维表示与配准 · 12.4

NeRF 与 3D Gaussian Splatting

照片是三维世界的二维投影。辐射场反过来做:把场景写成一个可以被渲染的函数(NeRF 的神经网络)或一团可以被渲染的高斯(3D Gaussian Splatting),渲染过程处处可微,于是让梯度下降去调场景参数,直到渲染出的图和已知位姿的照片一致。本节把体渲染、位置编码、协方差投影和泼溅混合都放进真正在页面里运行的优化实验。

约 40 分钟 前置:2.3 积分 · 3.3 雅可比 · 4.5 不确定性传播 · 6.3 梯度下降 · 10.3 相机 · 11.6 束调整 · 12.3 渲染管线 5 个交互

    1为什么机器人需要它

    第 11 章的 SfM 与 MVS 给出稀疏点云或网格,拿来定位、避障已经够用,但有两个老毛病:玻璃、反光面、细线、树叶和头发几乎重建不出来;贴上纹理的网格看上去也不像照片,因为外观会随视角变(高光、折射、半透明)。辐射场(radiance field)换了一个问法:不去求"表面在哪",只问"站在这里、朝这个方向看,会看到什么颜色"。

    关键在于让渲染本身可微。如果从场景参数到像素颜色的每一步都有导数,就能把"渲染图与照片的差"当成损失,对场景参数做梯度下降(6.3、6.4 节),其中相机位姿由 SfM / 束调整(11.6 节)事先给出。2020 年的 NeRF 用一个小神经网络当场景,2023 年的 3D Gaussian Splatting(3DGS)用几十万到几百万个半透明的三维高斯椭球当场景。机器人用它们做:

    • 场景重建与 real2sim:手机绕物体拍一圈,得到可以真实感渲染、可以导入仿真的资产和数字孪生。
    • 杂乱场景里的操作:透明、反光物体的几何;把抓取规划放进辐射场里做(Dex-NeRF、GraspNeRF 等,见第 6 节)。
    • 建图与 SLAM:地图本身可渲染,相机位姿可以靠"渲染误差最小"来跟踪(iMAP、NICE-SLAM、SplaTAM 等)。
    • 数据与世界模型:新视角合成做数据增强;它也是"机器人脑中的世界长什么样"的一个候选表示(第七部分)。

    本节沿着这条线走:先看渲染一个像素到底在算什么(FIG 1),再用"泼溅 + 混合"在 2D 里亲手把一张图拟合出来(FIG 2,核心实验),然后看 NeRF 为什么需要位置编码(FIG 3),以及三维椭球怎样变成屏幕上的二维椭圆(FIG 4),最后比较两者的开销(FIG 5)。

    2直觉:一个像素 = 沿光线对"雾"的积分

    把场景想成一团带颜色的雾。一条相机光线穿过雾:每走一小段 \(\mathrm{d}t\),它有 \(\sigma(t)\,\mathrm{d}t\) 的概率"撞上"什么并带着那里的颜色停下来,\(\sigma\) 叫体密度(单位 1/米)。走到 \(t\) 还没被拦下的概率是透射率 \(T(t)=\exp\!\big(-\!\int_0^t\sigma\big)\);于是"恰好在 \(t\) 处停下"的概率密度是 \(T(t)\sigma(t)\),像素颜色就是停下位置颜色的期望:

    $$ C(\mathbf r)=\int_{t_n}^{t_f}\hl{T}{T(t)}\,\sigma(\mathbf r(t))\,\mathbf c(\mathbf r(t),\mathbf d)\,\mathrm{d}t,\qquad T(t)=\exp\!\Big(-\!\int_{t_n}^{t}\sigma(\mathbf r(s))\,\mathrm{d}s\Big). $$

    实心墙是一层 \(\sigma\) 极大的薄壳(光线几乎必然在那里停下),雾是很小的 \(\sigma\) 铺一大段(每处只拦下一点点)。计算机里把光线切成 \(N\) 段、每段宽 \(\delta_i\):这一段拦下光线的概率是 \(\alpha_i=1-e^{-\sigma_i\delta_i}\),之前一路没被拦下的概率是 \(T_i=\prod_{j<i}(1-\alpha_j)\),于是权重 \(w_i=T_i\alpha_i\),\(\hat C=\sum_i w_i\mathbf c_i\)。这正是 12.3 节里从前往后的 alpha 混合。下图的密度画在 16 个小格上(拖动条形顶端的圆圈,或直接点击某一格,改写自己的密度):

    FIG 1沿一条光线的体渲染
    σ(t)(拖圆圈)与 T(t)
    权重密度 Tσ 与采样权重 w
    预设
    左:条形是 16 格分段常数的密度 \(\sigma\)(颜色是该格材质的颜色,近红远蓝),黄线是精确的透射率 \(T(t)\),底部短竖线是 \(N\) 个采样点。右:彩色条是 \(N\) 段的权重 \(w_i/\delta\)(面积 = 权重),紫线是精确的权重密度 \(T\sigma\),竖线是期望深度(实线:采样求和;虚线:精确)。"Max" 用 \(\alpha=1-e^{-\sigma\delta}\),"朴素"用 \(\alpha=\sigma\delta\)(直接做黎曼和)。"前 k 个"滑块只合成前 \(k\) 个采样,就是前向 alpha 混合的中间状态。
    试一试
    • 点"实心墙":几乎所有权重压在墙的第一个格子上,\(\sum w\approx1\),期望深度就是墙的位置。墙后面的东西为什么对像素毫无贡献?
    • 把 \(N\) 减到 16 以下(比如 5):采样点可能"跨过"薄墙,颜色误差立刻出现。窄的东西需要足够多的采样。
    • 再把 \(N\) 调成 16 的倍数(16、32、48……):误差降到 \(10^{-9}\) 以下。为什么这时求和和积分完全相等?(密度在每格内是常数。)
    • 切到"朴素"并选"实心墙":\(\sum w\) 超过 1,颜色被"过曝"。\(\alpha=1-e^{-\sigma\delta}\) 保证了什么?
    核心洞见

    体渲染把"看到什么"写成了一个对密度和颜色都光滑可微的公式:\(\hat C=\sum_i T_i\alpha_i\mathbf c_i\) 只含乘法、指数和求和。所以只要有任何能产生 \(\sigma_i,\mathbf c_i\) 的参数化(神经网络、体素格、一堆高斯),损失 \(\|\hat C-C_{\text{照片}}\|^2\) 对这些参数的梯度都存在,可以直接梯度下降。NeRF 和 3DGS 的差别,只在于"\(\sigma_i,\mathbf c_i\) 从哪里来"。

    3动手玩:用一把高斯"泼"出一张图

    3DGS 的做法是把场景直接写成许多半透明、有朝向的椭球。每个椭球有位置 \(\boldsymbol\mu\)、形状 \(\Sigma\)、不透明度 \(o\)、颜色 \(\mathbf c\)。渲染时把它们投影到屏幕成二维椭圆("泼溅",splat),按深度从前到后排序,在每个像素上做 alpha 混合。下面的实验把相机拿掉,只留最后一步:屏幕上有 \(N\) 个二维高斯,每个有位置、两个尺度 \(s_1,s_2\)、朝向 \(\theta\)、颜色、不透明度和一个固定的深度 \(z\);像素 \(\mathbf x\) 处的颜色是

    $$ C(\mathbf x)=\sum_{i}\mathbf c_i\,\hl{alpha}{\alpha_i}\prod_{j<i}(1-\alpha_j),\qquad \alpha_i=o_i\exp\!\Big(-\tfrac12(\mathbf x-\boldsymbol\mu_i)^{\!\top}\Sigma_i^{-1}(\mathbf x-\boldsymbol\mu_i)\Big),\quad \Sigma_i=R(\theta_i)\,\mathrm{diag}(s_{1}^2,s_{2}^2)\,R(\theta_i)^{\!\top}, $$

    其中下标已按深度从前到后排好。这是真正的优化:损失是渲染图与目标图的均方误差,对每个高斯的全部 9 个参数(位置、两个对数尺度、角度、颜色、不透明度)的梯度是手写的解析梯度(页面里已和有限差分核对过),用 Adam 更新。"稠密化"和"剪枝"复刻了 3DGS 的自适应密度控制:位置梯度长期很大的高斯说明"这里还没拟合好",大的被分裂(这里把两个子高斯沿长轴摆开,原版是从母高斯的分布里采样)、小的被克隆;贡献几乎为零的被剪掉。点击图中的高斯可以选中它,然后拖动三个圆圈来改位置、长轴、短轴,亲手感受这种表示。

    FIG 2泼溅与混合:二维高斯拟合实验室
    渲染结果 64×48(点击选中高斯)
    左:当前渲染("椭圆"视图把每个高斯画成 2σ 的实心椭圆,"两者"在混合图上叠加轮廓)。右上:目标图与误差图(越亮误差越大);右下:PSNR 随迭代次数的曲线,竖虚线标出稠密化 / 剪枝的时刻。选中高斯后出现三个圆圈:中心(位置)、长轴端点(朝向与长轴)、短轴端点(短轴)。N 滑块会重新初始化。
    试一试
    • 点"拟合",看渲染从色块逐渐变成目标图,PSNR 升到 24 dB 以上。前几十步进步最快:先抓大块颜色,再修细节。
    • 选中一个高斯,把它拖离原位 3 个像素以上,PSNR 立刻下降;再点"拟合",优化器把它拉回去(或者让别的高斯接手)。
    • 选"棋盘"目标,N 设成 20,拟合一阵后点"稠密化"几次:高斯数增加,PSNR 继续上升。哪些地方的高斯最先被分裂?(锐利的边。)
    同一个公式,两种"泼法"

    把 FIG 1 的 \(\hat C=\sum T_i\alpha_i\mathbf c_i\) 和这里的 \(C=\sum\mathbf c_i\alpha_i\prod_{j<i}(1-\alpha_j)\) 并排看:形式一模一样,区别是 \(\alpha_i\) 怎么来。NeRF 沿光线采样空间点,\(\alpha_i\) 由网络在该点的密度给出;3DGS 沿光线遇到高斯,\(\alpha_i\) 由这个高斯投影到像素处的值给出。前者每个像素要问网络几百次,后者只需要对覆盖这个像素的少数高斯做排序混合。

    4第二、第三视角:位置编码、椭球的投影与两者的比较

    NeRF 的另一半:为什么直接喂坐标,网络画不出锐利的边

    NeRF 的场景是一个多层感知机 \(F_\Theta:(\mathbf x,\mathbf d)\mapsto(\sigma,\mathbf c)\)。如果直接把坐标喂给网络,它倾向于先学会低频的平滑成分,再极其缓慢地学高频,这叫谱偏置(spectral bias,Rahaman 等 2019)。NeRF 的办法是先把坐标做傅里叶编码 \(\gamma(x)=(\sin 2^k\pi x,\cos 2^k\pi x)_{k=0}^{L-1}\),再喂给网络(Tancik 等 2020 从神经正切核的角度解释了为什么这样有效)。下面用一维的"场景"把这个现象缩小到可以现场训练:目标是一条带锐利边的曲线,两个网络(2 个隐藏层、各 32 个单元,约 1.2 到 1.6 千个参数)用同样的 Adam 同时训练,一个吃原始的 \(x\),一个吃 \(\gamma(x)\)。反向传播会在第五部分讲,这里把训练循环当黑盒,里面的数学(手写的反向传播)已经用有限差分验证过。

    FIG 3位置编码:NeRF 的缩微版
    灰线是目标,灰点是 128 个训练样本(只在这些点上算损失)。紫色:只吃原始 \(x\) 的网络;黄色:吃 \(\gamma(x)\) 的网络。右图实线是在 400 个没训练过的点上的测试损失,虚线是训练损失。把 \(L\) 调大,黄色网络在训练点上拟合得越来越好,但样本之间会出现噪声:测试损失先降后升。
    试一试
    • 用"条纹"目标、\(L=4\) 训练 600 步以上:紫色网络仍是一条平缓的波,测试损失停在 \(10^{-1}\) 量级;黄色网络已经画出清晰的方波。
    • 把 \(L\) 增到 8 以上再训练:训练损失趋近 0,但样本之间出现高频噪声,测试损失比训练损失高几个数量级。编码频率要和数据密度匹配。

    3DGS 的几何:三维椭球怎样变成二维椭圆

    FIG 2 里二维椭圆是自由参数;真实的 3DGS 里它们是三维高斯投影的结果。一个三维高斯 \(\mathcal N(\boldsymbol\mu,\Sigma)\) 的协方差写成 \(\Sigma=R\,S\,S^{\top}R^{\top}\)(\(S\) = 三个尺度的对角阵,\(R\) = 旋转,1.11、1.12 节:特征向量是 \(R\) 的列,特征值是尺度的平方)。相机把它投到图像上时,透视投影是非线性的,但在 \(\boldsymbol\mu\) 附近可以用一阶泰勒展开(3.3 节的雅可比)近似成仿射映射,而高斯经过仿射映射仍是高斯,协方差按 4.5 节的传播公式变换:\(\Sigma'=J\,W\,\Sigma\,W^{\top}J^{\top}\)(\(J\) 是 \(2\times3\) 的,结果直接就是 \(2\times2\))。这与 EKF 里把非线性观测线性化是同一个技巧(4.8 节),在图形学里叫 EWA 泼溅(Zwicker 等,2001)。

    下图用蒙特卡洛检验它:从三维高斯采样 20000 个点,逐点做精确的透视投影,算出它们的经验协方差,与公式的 \(\Sigma'\) 比较。椭球小、离相机远时二者几乎重合(剩余的 1% 左右是采样噪声);椭球大、离相机近时,雅可比在椭球范围内变化显著,一阶近似就失效了。

    FIG 43D 高斯的投影:J W Σ Wᵀ Jᵀ
    世界:椭球 (2σ) 与相机,拖动旋转
    左:黄色线框是椭球的 2σ 曲面,三根彩色轴是 \(R\) 的列乘 \(2s_i\),青色是相机视锥,黄点是几个采样点。右:黄点是 20000 个采样点中前 700 个的精确投影;绿色实线椭圆是公式 \(\Sigma'\) 的 2σ 等值线,紫色虚线是经验协方差的 2σ 等值线。读数里的相对误差是 \(\|\Sigma'-\hat\Sigma_{MC}\|_F/\|\hat\Sigma_{MC}\|_F\)。
    试一试
    • 保持椭球较小、相机较远(\(s_{\max}/z<0.1\)):绿色实线和紫色虚线几乎重合,相对误差在 3% 以内。
    • 把椭球放大、相机拉近到 3 以内:相对误差超过 10%,两个椭圆明显错开。一阶近似的适用范围就是"椭球尺寸远小于它到相机的距离"。

    NeRF 与 3DGS:诚实的对比

    下表是一般性的、会随具体实现变化的概括,不是基准测试;"量级"只是数量级。

    NeRF(隐式) 3D Gaussian Splatting(显式)
    表示MLP(常配哈希网格等特征网格):\(F_\Theta(\mathbf x,\mathbf d)\to(\sigma,\mathbf c)\)几十万到几百万个三维高斯,每个约 59 个浮点数(含 3 阶球谐)
    渲染光线步进,每像素几十到几百次网络 / 特征查询;原版远不到实时,加速版本(Instant-NGP 等)可交互排序后的光栅化(按 16×16 分块),常见报告是桌面 GPU 上 1080p 实时
    训练原版数小时到一天;哈希网格版本几秒到几分钟一个场景约几分钟到半小时(取决于 GPU 与场景)
    内存小(几 MB 到几十 MB 的权重 / 特征网格)大:100 万高斯 ≈ 59×4 B×106 ≈ 240 MB,大场景可到 GB
    可编辑性难:知识藏在权重里相对容易:删除、移动、合并高斯;但没有语义分组
    几何密度场,没有明确表面;SDF 变体(NeuS、VolSDF)给出表面(12.2 节)一团半透明椭球,不是水密表面;2DGS 等变体改善几何
    画质好;抗锯齿的变体(Mip-NeRF 360、Zip-NeRF)在无界场景最强之一相当或更好,视场景而定;稀疏视角、远离训练视角时都会出现伪影

    5再看数学

    提示:把鼠标悬停在公式中带底色的符号上,FIG 1、FIG 2 或 FIG 4 中对应的元素会被高亮。

    体渲染的求积:为什么是 \(1-e^{-\sigma\delta}\),为什么可微

    设光线被切成 \(N\) 段,第 \(i\) 段内密度 \(\sigma_i\)、颜色 \(\mathbf c_i\) 为常数,宽 \(\delta_i\)。段内 \(T(t)=T_i\,e^{-\sigma_i(t-t_i)}\),所以这一段对积分的贡献可以直接积出来:

    $$ \begin{aligned}\int_{t_i}^{t_i+\delta_i}\!T(t)\,\sigma_i\,\mathbf c_i\,\mathrm{d}t&=\mathbf c_i\,T_i\!\int_0^{\delta_i}\!\sigma_ie^{-\sigma_is}\mathrm{d}s=\mathbf c_i\,T_i\,\underbrace{\big(1-e^{-\sigma_i\delta_i}\big)}_{\alpha_i},\\ \hat C&=\sum_{i=1}^{N}\hl{w}{w_i}\,\mathbf c_i,\quad w_i=T_i\alpha_i,\quad T_i=\prod_{j<i}(1-\alpha_j)=e^{-\sum_{j<i}\sigma_j\delta_j}.\end{aligned} $$

    这是 Max(1995)的结果,也是 NeRF 的式 (3)。当 \(\sigma,\mathbf c\) 在每段内真是常数时它精确等于积分(FIG 1 里 \(N\) 为 16 的倍数时误差 \(<10^{-9}\),已在 node 中核对)。因为 \(\prod(1-\alpha_j)\) 是"一路没被拦下"的概率,所以 \(\sum_iw_i=1-T_{N+1}\le1\):剩下的 \(T_{N+1}\) 分给背景。朴素黎曼和 \(\alpha=\sigma\delta\) 没有这个保证。实现上从前往后累加 \(C\leftarrow C+T\alpha\mathbf c,\ T\leftarrow T(1-\alpha)\),\(T\) 低于 \(10^{-4}\) 左右就可以提前终止,和 12.3 节的 alpha 混合一致。

    梯度。对每个采样有 \(\partial\hat C/\partial\mathbf c_k=w_k\),\(\partial\hat C/\partial\alpha_k=T_k\,(\mathbf c_k-\mathbf C_{>k})\),其中 \(\mathbf C_{>k}\) 是"第 \(k\) 个之后所有东西"混合出的颜色(从后往前递推 \(\mathbf C_{>k-1}=\alpha_k\mathbf c_k+(1-\alpha_k)\mathbf C_{>k}\),初值为背景)。直觉很清楚:提高 \(\alpha_k\) 就是把后面的颜色换成 \(\mathbf c_k\),影响的大小是它们的差乘以光线能到达这里的概率 \(T_k\)。FIG 2 的解析梯度就是这个递推。

    NeRF:网络、损失、位置编码

    $$ F_\Theta:\big(\gamma(\mathbf x),\gamma(\mathbf d)\big)\mapsto(\sigma,\mathbf c),\qquad \mathcal L(\Theta)=\sum_{\mathbf r\in\mathcal R}\big\|\hat C(\mathbf r;\Theta)-C_{\text{photo}}(\mathbf r)\big\|_2^2,\qquad \gamma(x)=\big(\sin(2^k\pi x),\cos(2^k\pi x)\big)_{k=0}^{L-1}. $$

    \(\sigma\) 只依赖位置 \(\mathbf x\)(保证多视角一致),颜色还依赖观察方向 \(\mathbf d\)(高光)。\(\mathcal R\) 是从已知位姿的照片里随机抽出的像素光线,位姿通常由 COLMAP(SfM + 束调整,11.6 节)给出,内参来自 10.3 节。原版 NeRF 对位置用 \(L=10\)、对方向用 \(L=4\),所以 \(\gamma(\mathbf x)\in\R^{3\cdot2\cdot10}=\R^{60}\)。采样用分层采样 + 层次采样:先在光线上均匀(带抖动)取 64 点跑"粗"网络,再按粗权重 \(w_i\) 的分布重要性采样 128 点跑"细"网络,把采样集中在表面附近。训练是标准 SGD / Adam(6.4 节)。后续工作改进了不同方面:Mip-NeRF 360 / Zip-NeRF(抗锯齿与无界场景)、Instant-NGP(哈希网格 + 小 MLP,训练从小时降到分钟)。

    3DGS:参数化、投影、混合、训练

    每个高斯有 \(\boldsymbol\mu\in\R^3\)、尺度 \(\mathbf s\in\R^3_{>0}\)、旋转(单位四元数)、不透明度 \(o\in(0,1)\)、以及颜色(3 阶球谐,48 个系数,使颜色依赖视角)。协方差不直接优化,而是

    $$ \hl{cov3}{\Sigma}=R\,S\,S^{\top}R^{\top}=(RS)(RS)^{\top}\ \Rightarrow\ \mathbf x^{\top}\Sigma\mathbf x=\|(RS)^{\top}\mathbf x\|^2\ge0,\qquad \Sigma\,R_{:,i}=s_i^2R_{:,i}. $$

    任何实数 \(R,S\) 都给出对称半正定矩阵,梯度更新永远不会产生"负方差";直接对 \(\Sigma\) 的 9 个元素做梯度步则会很快跑出半正定锥。特征向量就是 \(R\) 的列、特征值是 \(s_i^2\)(1.11 节,FIG 4 读数里核对过)。实现里尺度存为 \(\log s\),四元数每步归一化,不透明度存为 sigmoid 之前的值,保证约束自动满足。

    投影。设世界到相机的变换为 \(\mathbf x_c=W\mathbf x+\mathbf t\)(外参 \({}^{c}T_{w}\),10.3 节),像素 \(\mathbf u=\pi(\mathbf x_c)=(f\,x/z+c_x,\ f\,y/z+c_y)\)。中心点精确投影 \(\boldsymbol\mu'=\pi(W\boldsymbol\mu+\mathbf t)\);协方差按一阶泰勒展开 \(\pi(\mathbf x_c+\boldsymbol\epsilon)\approx\pi(\mathbf x_c)+J\boldsymbol\epsilon\) 传播(4.5 节):

    $$ \hl{J}{J}=\frac{\partial\pi}{\partial\mathbf x_c}=\begin{bmatrix}f/z&0&-f\,x/z^2\\0&f/z&-f\,y/z^2\end{bmatrix}_{\mathbf x_c=W\boldsymbol\mu+\mathbf t},\qquad \hl{cov2}{\Sigma'}=J\,W\,\Sigma\,W^{\top}J^{\top}\in\R^{2\times2}. $$

    注意:这里的 \(\Sigma\) 在世界系,\(W\) 是旋转部分(平移不影响协方差);\(J\) 在椭球中心处求值,所以远小于距离的椭球才准(FIG 4)。参考实现还在 \(\Sigma'\) 的对角线上加了一个很小的常数(0.3 像素²)当抗锯齿的低通滤波。屏幕上的高斯再按 FIG 2 的公式 \(\alpha_i=o_i\exp(-\tfrac12\,\Delta\mathbf u^{\top}\Sigma'^{-1}\Delta\mathbf u)\) 逐像素求值,并按相机系深度 \(z\) 从前到后混合。颜色 \(\mathbf c_i\) 由球谐函数在当前视线方向上求值。

    训练。损失 \(\mathcal L=(1-\lambda)\,\mathcal L_1+\lambda\,\mathcal L_{\text{D-SSIM}}\)(\(\lambda=0.2\)),初始高斯来自 SfM 的稀疏点云(12.1 节的点,被赋予了"大小")。每隔若干步做自适应密度控制:累计视图空间位置梯度的平均大小超过阈值的高斯被稠密化——大的分裂(尺度缩小到约 1/1.6,位置从原高斯采样),小的克隆;不透明度过低或尺寸过大的被剪掉;并周期性地重置不透明度以清除漂浮物。渲染用按 16×16 像素分块的 GPU 光栅化器,对"高斯 × 分块"的键值(分块号 + 深度)排序后逐块混合,梯度也通过同一个分块结构反传。FIG 2 是它的二维、L2 损失版本,其余逻辑一致。

    与本章其他表示的关系

    点云(12.1):3DGS 是"每个点带了形状、不透明度和朝向相关颜色"的点云,初始化就来自 SfM 点。SDF 与网格(12.2):NeRF 的密度可以改成由 SDF 导出(NeuS、VolSDF),这样体渲染学出的是一个有明确表面的隐式几何。渲染管线(12.3):3DGS 的渲染就是一个自定义的光栅化管线(投影 → 分块 → 深度排序 → alpha 混合),NeRF 则是光线投射;二者共用同一个 alpha 混合公式。

    6机器人中的它:渲染要多快,才能进控制环?

    在机器人里,辐射场往往不是"离线做一份漂亮的模型"就结束了:SLAM 要在每一帧用渲染误差修正位姿,仿真和策略学习要渲染成千上万张图,规划器要反复查询它。所以渲染的算术量和延迟决定了它能不能进入闭环。下面用一个粗略的成本模型把 NeRF 和 3DGS 摆在一起:它只算浮点运算的数量级,真实速度还受显存带宽、排序和实现影响(3DGS 的实际时间主要花在排序与内存访问上,所以按 FLOP 算出的毫秒数只是下界)。

    FIG 5渲染一帧的算术量:光线步进 vs 光栅化
    条形是每帧浮点运算量(对数坐标,\(10^8\) 到 \(10^{15}\))。假设(都是粗略的):原版 NeRF 每个采样的 MLP 约 0.6 M 次乘加;哈希网格版本的小 MLP 约 \(2\times10^4\) FLOP,且空区域跳过后只剩约 10% 的采样;3DGS 每个高斯预处理约 300 FLOP、排序键约 6 个分块×30 FLOP,每个像素混合约 50 个高斯×25 FLOP。时间是在持续 10 TFLOP/s 下的纯算术下界。
    试一试
    • 选 1080p、每条光线 192 个采样、100 万高斯,对比原版 NeRF 与 3DGS 的条形:差了几个数量级?再把高斯数拉到 \(10^7\),差距缩小多少?
    真实系统里

    工具:nerfstudio(模块化的 NeRF / 高斯训练框架)、gsplat(高斯泼溅的 CUDA 库)、INRIA 的原版 3DGS 实现、Instant-NGP;相机位姿通常来自 COLMAP。建图与 SLAM:iMAP(Sucar 等,ICCV 2021)和 NICE-SLAM(Zhu 等,CVPR 2022)把神经场当地图;SplaTAM(Keetha 等,CVPR 2024)和 MonoGS / Gaussian Splatting SLAM(Matsuki 等,CVPR 2024)用高斯当地图并以渲染误差跟踪相机,GS-ICP SLAM 把 G-ICP 与高斯地图结合。操作:Dex-NeRF(Ichnowski 等,CoRL 2021)用 NeRF 恢复透明物体几何来抓取;Evo-NeRF、GraspNeRF 等在辐射场里估计抓取;LERF(Kerr 等,ICCV 2023)把语言特征蒸馏进辐射场,F3RM(Shen 等,CoRL 2023)把类似的特征场用于语言指令的抓取。仿真与数据:用手机拍摄重建场景、再导入仿真(real2sim),或用新视角合成做策略学习的数据增强,目前是活跃方向,各仿真器的导入支持不同,请查最新文档。以上多数是研究原型:具体精度、速度和适用条件请以原论文为准。

    接下来读什么。这一节也是第三部分的终点:第 10 章让你知道一个像素从哪里来,第 11 章让你从多张图恢复相机和结构,第 12 章让你决定怎样表示结果——点云、体素 / 网格 / SDF、渲染管线,以及可微渲染的辐射场。后面:第四部分(状态估计与 SLAM)把这里"事先由 SfM 给定"的相机位姿改成在线估计,并把 EKF 的雅可比技巧用到整个系统;第五部分(神经网络基础)把 FIG 3 里当黑盒的 MLP、反向传播、自动微分和位置编码讲清楚,之后你才能自己训练 NeRF 或高斯模型;第七部分(基础模型与世界模型)再回到"机器人脑中的世界长什么样"这个问题。

    7常见误区

    误区 1:照片够多就行,位姿差一点没关系

    两种方法都把相机位姿当作已知真值。位姿有误差(SfM 在弱纹理、重复纹理、快速运动下失败;轮式里程计漂移)时,同一个表面点在不同照片里"对不上",优化器只能把它抹成模糊的一团或分裂成漂浮物(floaters)。实践里先用 11.6 节的重投影误差检查 SfM 的质量,再训练;SLAM 类方法则把位姿也作为变量联合优化。

    误区 2:场景是静止的

    辐射场假设所有照片看到的是同一个静止的世界。拍摄时有人走过、机械臂在动、光照在变,同一个位置在不同照片里颜色矛盾,模型要么把它平均成雾,要么留下"鬼影"。机器人自己的手臂和影子也算动态物体。常见对策是给动态物体打掩码、或用显式建模动态的变体,但默认的 NeRF / 3DGS 做不到。

    误区 3:在训练视角上看着很好,就是好

    FIG 3 已经演示了原理:训练损失可以趋近 0,而样本之间一团糟。辐射场同理:它被训练去复现训练照片,在训练视角附近可以很逼真,离开这些视角就会出现漂浮物、"空洞"和过平滑。评估必须用留出的视角(测试集);对机器人更要问:"我真正会去的视角,覆盖到了吗?"

    误区 4:照片级真实 = 几何准确,可以直接做碰撞检测

    渲染得像不等于几何对:NeRF 的密度可以在玻璃、反光面处"作弊",3DGS 的高斯是一团半透明椭球,不是水密表面,也没有"内外"。要做碰撞检测或抓取,需要先转成网格 / TSDF / ESDF(12.2 节)或用带几何正则的变体(2DGS、NeuS 类)。另外单目 SfM 的尺度是任意的,度量尺度要靠已知基线、IMU 或深度传感器恢复。

    误区 5:一阶近似和排序"差不多就行"

    FIG 4 说明 \(\Sigma'=JW\Sigma W^{\top}J^{\top}\) 只在椭球远小于其深度时准确;靠近相机的大高斯会被投成错误的形状,这是 3DGS 近景伪影的来源之一。另外 3DGS 按每个高斯一个深度排序,而不是每个像素;两个重叠的大高斯在视角变化时顺序翻转,画面会"跳变"(popping)。还有内存:每个高斯约 59 个浮点数,几百万个高斯就是几百 MB 到 GB,机器人板载 GPU 不一定放得下。

    8小练习

    1. 光线上某一段:\(\sigma=2\ \text{m}^{-1}\),宽 \(\delta=0.5\ \text{m}\),光线到达这一段起点的透射率 \(T_i=0.5\)。这一段的权重 \(w_i=T_i\alpha_i\) 是多少?
    \(\alpha=1-e^{-\sigma\delta}=1-e^{-1}\approx0.632\),\(w=T\alpha=0.5\times0.632\approx0.316\)。0.632 只是这一段"自己拦下光线"的概率,还要乘上光线能走到这里的概率 \(T_i\)。朴素的 \(\sigma\delta=1.0\) 则会让 \(\alpha\) 达到 1,是 FIG 1 里"朴素"模式过曝的原因。
    2. 3DGS 为什么把协方差写成 \(\Sigma=RSS^{\top}R^{\top}\),而不是直接优化 \(\Sigma\) 的元素?
    \(\mathbf x^{\top}\Sigma\mathbf x=\|(RS)^{\top}\mathbf x\|^2\ge0\) 对任何实数 \(R,S\) 成立;对 9 个元素直接做梯度步,很容易得到有负特征值的矩阵,那就不是协方差了。\(\Sigma\) 一般不是对角阵(\(R\) 是任意旋转),渲染当然依赖相机(通过 \(W\) 和 \(J\))。
    3. 原版 NeRF 对三维位置 \((x,y,z)\) 用 \(L=10\) 的傅里叶编码(不含原始坐标本身)。\(\gamma(\mathbf x)\) 的维数是?
    每个坐标有 \(L\) 个频率,每个频率一对 sin / cos:\(3\times10\times2=60\)。最高频率 \(2^{9}\pi\) 对应的周期是 \(2/512\approx0.004\)(坐标范围是 \([-1,1]\)),也就是 FIG 3 里 \(L\) 增大时能画出越来越细的结构。
    4. 一个球对称高斯 \(\Sigma=0.01\,I\)(世界系,\(W=I\)),中心在相机系 \((x,y,z)=(1,0,4)\),焦距 \(f=400\) 像素。\(\Sigma'\) 的 \(u\) 方向方差 \(\Sigma'_{uu}\) 是多少?
    \(J\) 的第一行 \((f/z,\,0,\,-fx/z^2)=(100,\,0,\,-25)\),所以 \(\Sigma'_{uu}=0.01\,(100^2+25^2)=106.25\ \text{px}^2\)。若只看 \(f/z\) 会得到 100,漏掉的 25 来自"物体偏离光轴时,深度方向的不确定性也会投到 \(u\) 上",这正是 \(J\) 第三列的作用。
    5. 你用手机绕桌子拍了一圈来重建场景,但拍摄过程中有一个人在桌子后面来回走动。训练出的辐射场最可能怎样?
    静态场景假设被打破:同一个位置在不同照片里有时是人、有时是背景,一个静止的场只能折中,表现为半透明的鬼影或浮在空中的色块。需要显式的动态建模、对动态物体加掩码,或者让拍摄时场景静止。

    9延伸阅读

    • B. Mildenhall, P. P. Srinivasan, M. Tancik, J. T. Barron, R. Ramamoorthi & R. Ng, NeRF: Representing Scenes as Neural Radiance Fields for View Synthesis, ECCV 2020 — NeRF 原文:体渲染、位置编码、层次采样
    • B. Kerbl, G. Kopanas, T. Leimkühler & G. Drettakis, 3D Gaussian Splatting for Real-Time Radiance Field Rendering, ACM Trans. Graphics (SIGGRAPH) 42(4), 2023 — 3DGS 原文:参数化、分块光栅化、自适应密度控制
    • M. Zwicker, H. Pfister, J. van Baar & M. Gross, EWA Volume Splatting, IEEE Visualization 2001 — 协方差经雅可比投影的出处
    • N. Max, Optical Models for Direct Volume Rendering, IEEE Trans. Visualization and Computer Graphics 1(2), 1995 — 体渲染方程与 alpha 合成求积
    • M. Tancik et al., Fourier Features Let Networks Learn High Frequency Functions in Low Dimensional Domains, NeurIPS 2020 — 位置编码为什么有效(FIG 3 的理论背景)
    • N. Rahaman et al., On the Spectral Bias of Neural Networks, ICML 2019 — 谱偏置
    • J. T. Barron et al., Mip-NeRF 360: Unbounded Anti-Aliased Neural Radiance Fields, CVPR 2022; Zip-NeRF, ICCV 2023 — 抗锯齿与无界场景的高质量 NeRF
    • T. Müller, A. Evans, C. Schied & A. Keller, Instant Neural Graphics Primitives with a Multiresolution Hash Encoding, ACM Trans. Graphics (SIGGRAPH) 2022 — 哈希网格:把 NeRF 训练缩短到分钟
    • A. Tewari et al., Advances in Neural Rendering, Computer Graphics Forum (EUROGRAPHICS STAR) 2022 — 神经渲染综述
    • P. Wang et al., NeuS, NeurIPS 2021; L. Yariv et al., VolSDF, NeurIPS 2021 — 用 SDF 做体渲染,得到明确的表面(与 12.2 节相连)
    • J. L. Schönberger & J.-M. Frahm, Structure-from-Motion Revisited, CVPR 2016 — COLMAP:为辐射场提供相机位姿
    • M. Tancik et al., Nerfstudio: A Modular Framework for Neural Radiance Field Development, SIGGRAPH 2023 — 上手 NeRF / 高斯的开源框架