unified_cg

第9章:显式神经表示

在前面的章节中,我们探讨了将辐射场表示为连续函数的隐式神经表示(NeRF)。本章转向显式表示方法,这些方法直接在离散空间结构中存储场景信息。显式表示的核心优势在于查询效率和直观的空间组织,而主要挑战在于内存需求和离散化带来的伪影。我们将展示如何将这些显式表示统一到体积渲染框架中,并分析它们相对于隐式方法的计算和存储权衡。

9.1 体素网格与八叉树

9.1.1 经典体素表示

最直接的显式表示是规则体素网格。对于分辨率为 $N^3$ 的体素网格,我们将空间离散化为:

\[\mathbf{x}_{ijk} = \mathbf{x}_{\min} + \left(\frac{i}{N}, \frac{j}{N}, \frac{k}{N}\right) \odot (\mathbf{x}_{\max} - \mathbf{x}_{\min})\]

其中 $i,j,k \in {0,1,…,N-1}$,$\odot$ 表示逐元素乘积。

每个体素存储局部体积属性:

体积渲染方程在离散情况下变为黎曼和近似:

\[C(\mathbf{r}) = \sum_{n=1}^{N_{\text{samples}}} T_n \alpha_n \mathbf{c}_n\]

其中:

这个离散化引入了 $O(\delta^2)$ 的误差,根据中点法则: \(\left|\int_a^b f(t)dt - \sum_{n} f(t_n)\delta\right| \leq \frac{(b-a)\delta^2}{24}\max_{t \in [a,b]}|f''(t)|\)

离散化的数学基础

从连续体积渲染方程出发: \(C(\mathbf{r}) = \int_{t_{\text{near}}}^{t_{\text{far}}} T(t)\sigma(\mathbf{r}(t))\mathbf{c}(\mathbf{r}(t),\mathbf{d})dt\)

其中透射率 $T(t) = \exp\left(-\int_{t_{\text{near}}}^t \sigma(\mathbf{r}(s))ds\right)$。

应用分片常数近似,假设在区间 $[t_n, t_{n+1}]$ 内:

则透射率的递推关系: \(T_{n+1} = T_n \cdot \exp(-\sigma_n \delta_n)\)

区间 $[t_n, t_{n+1}]$ 对颜色的贡献: \(\Delta C_n = \int_{t_n}^{t_{n+1}} T(t)\sigma(t)\mathbf{c}(t)dt \approx T_n \sigma_n \mathbf{c}_n \int_{t_n}^{t_{n+1}} \exp\left(-\int_{t_n}^t \sigma_n ds\right)dt\)

计算内部积分: \(\int_{t_n}^{t_{n+1}} \exp(-\sigma_n(t-t_n))dt = \frac{1}{\sigma_n}[1 - \exp(-\sigma_n \delta_n)]\)

因此: \(\Delta C_n = T_n \mathbf{c}_n [1 - \exp(-\sigma_n \delta_n)] = T_n \alpha_n \mathbf{c}_n\)

这正是我们使用的离散公式,其中 $\alpha_n = 1 - \exp(-\sigma_n \delta_n)$ 是精确的局部不透明度。

采样策略与误差分析

为了减少离散化误差,可以采用更高阶的数值积分方法:

  1. 梯形法则:使用端点值的平均,误差降至 $O(\delta^2)$ \(\int_{t_i}^{t_{i+1}} f(t)dt \approx \frac{\delta}{2}[f(t_i) + f(t_{i+1})]\)

  2. Simpson法则:使用二次插值,误差为 $O(\delta^4)$ \(\int_{t_i}^{t_{i+2}} f(t)dt \approx \frac{\delta}{3}[f(t_i) + 4f(t_{i+1}) + f(t_{i+2})]\)

  3. 自适应采样:在高频区域(边界、细节)增加采样密度

    • 基于梯度的细化:$\delta_{\text{local}} = \delta_0 / (1 + |\nabla\sigma|)$
    • 基于曲率的细化:考虑二阶导数 $\nabla^2\sigma$

误差传播分析

考虑数值积分误差如何影响最终渲染结果。设真实积分为 $I$,数值近似为 $\tilde{I}$,则:

对于颜色积分: \(\epsilon_C = \left|C - \tilde{C}\right| \leq \int_{t_{\text{near}}}^{t_{\text{far}}} |T(t)||\epsilon_\sigma(t)|dt + \int_{t_{\text{near}}}^{t_{\text{far}}} |\epsilon_T(t)||\sigma(t)\mathbf{c}(t)|dt\)

其中:

透射率误差满足递推关系: \(\epsilon_{T,n+1} \leq \epsilon_{T,n} + T_n \cdot \epsilon_{\exp}(\sigma_n\delta_n)\)

其中 $\epsilon_{\exp}(x) \approx \frac{x^2}{2}e^x \cdot \epsilon_x$ 是指数函数的误差传播。

最优采样密度

给定总采样预算 $N_{\text{total}}$,如何分配采样点以最小化误差?使用变分法,最优采样密度满足:

\[\rho(t) \propto \sqrt{|f''(t)|}\]

其中 $f(t) = T(t)\sigma(t)\mathbf{c}(t)$ 是被积函数。这导致在场景边界($\sigma$ 变化剧烈)处需要更密集的采样。

体素遍历算法

光线与体素网格的相交使用3D DDA(Digital Differential Analyzer)算法:

  1. 初始化:计算光线进入边界框的参数 $t_{\text{min}}$
  2. 步进计算: \(t_{\text{next},d} = t_{\text{current}} + \frac{\text{sign}(\mathbf{d}_d)}{\mathbf{d}_d} \cdot \text{voxelSize}_d\) 其中 $d \in {x,y,z}$
  3. 选择最近边界:$t_{\text{next}} = \min(t_{\text{next},x}, t_{\text{next},y}, t_{\text{next},z})$
  4. 更新体素索引:根据最小 $t$ 对应的维度递增

该算法的复杂度为 $O(N)$,其中 $N$ 是光线穿过的体素数,最坏情况下为 $O(N_{\text{grid}})$。

Amanatides-Woo算法详解

更高效的体素遍历使用Amanatides-Woo算法,它预计算步进参数:

给定光线 $\mathbf{r}(t) = \mathbf{o} + t\mathbf{d}$:

  1. 初始化参数
    • 步长:$\Delta t_x = \text{voxelSize}/\mathbf{d}_x $,类似地计算 $\Delta t_y, \Delta t_z$
    • 初始边界:$t_{\max,x} = (\text{voxelBound}_x - \mathbf{o}_x)/\mathbf{d}_x$
    • 步进方向:$\text{step}_x = \text{sign}(\mathbf{d}_x)$
  2. 主循环
    while (t < t_far) {
        // 处理当前体素 (ix, iy, iz)
        processVoxel(ix, iy, iz)
           
        // 找到最近的边界
        if (t_max_x < t_max_y && t_max_x < t_max_z) {
            t = t_max_x
            t_max_x += Delta_t_x
            ix += step_x
        } else if (t_max_y < t_max_z) {
            t = t_max_y
            t_max_y += Delta_t_y
            iy += step_y
        } else {
            t = t_max_z
            t_max_z += Delta_t_z
            iz += step_z
        }
    }
    

整数算术优化

为避免浮点误差累积,可以使用整数算术版本:

\[\text{error}_d = \text{error}_d + |\mathbf{d}_d| \cdot \text{voxelSize}\]
当 $\text{error}_d \geq \mathbf{d}_{\max} \cdot \text{voxelSize}$ 时,递增对应维度并减少误差。

这种方法完全避免了浮点数操作,适合硬件实现。

9.1.2 三线性插值

为避免块状伪影,我们在体素中心之间进行三线性插值。给定查询点 $\mathbf{x}$,首先找到包含它的体素 $(i,j,k)$,然后计算局部坐标:

\[\mathbf{u} = \left(\frac{x - x_{i}}{x_{i+1} - x_i}, \frac{y - y_{j}}{y_{j+1} - y_j}, \frac{z - z_{k}}{z_{k+1} - z_k}\right)\]

三线性插值公式为:

\[f(\mathbf{x}) = \sum_{i'=0}^{1}\sum_{j'=0}^{1}\sum_{k'=0}^{1} f_{i+i',j+j',k+k'} \prod_{d \in \{x,y,z\}} \begin{cases} 1-u_d & \text{if } d'=0 \\ u_d & \text{if } d'=1 \end{cases}\]

这等价于三次线性插值的嵌套: \(f(\mathbf{x}) = \text{lerp}_z\left(\text{lerp}_y\left(\text{lerp}_x(f_{000}, f_{100}, u_x), \text{lerp}_x(f_{010}, f_{110}, u_x), u_y\right), \ldots, u_z\right)\)

这保证了 $C^0$ 连续性但在体素边界处导数不连续,导致法线计算时出现阶跃。

三线性插值的张量表示

三线性插值可以视为三阶张量的多线性形式。定义插值张量 $\mathcal{F} \in \mathbb{R}^{2 \times 2 \times 2}$,其元素为八个顶点值:

\[\mathcal{F}_{i'j'k'} = f_{i+i',j+j',k+k'}\]

则插值结果为: \(f(\mathbf{u}) = \mathcal{F} \times_1 \mathbf{w}^x \times_2 \mathbf{w}^y \times_3 \mathbf{w}^z\)

其中 $\mathbf{w}^d = [1-u_d, u_d]^T$ 是每个维度的权重向量,$\times_n$ 表示沿第 $n$ 个模式的张量乘积。

展开后: \(f(\mathbf{u}) = \sum_{i',j',k' \in \{0,1\}} \mathcal{F}_{i'j'k'} \cdot w^x_{i'} \cdot w^y_{j'} \cdot w^z_{k'}\)

这种表示揭示了三线性插值的张量分解结构,为后续的TensoRF方法提供了理论基础。

插值权重的几何解释

三线性插值的权重具有直观的几何意义——每个顶点的贡献与查询点到对角顶点形成的子体积成正比:

\[w_{ijk} = \prod_{d \in \{x,y,z\}} \begin{cases} (1-u_d) & \text{if bit}_d(ijk) = 0 \\ u_d & \text{if bit}_d(ijk) = 1 \end{cases}\]

其中 $\text{bit}_d(ijk)$ 提取索引的第 $d$ 位。

重心坐标解释

另一种理解是通过重心坐标。在立方体中,任意点 $\mathbf{x}$ 可以表示为八个顶点的加权平均:

\[\mathbf{x} = \sum_{i=0}^{7} \lambda_i \mathbf{v}_i\]

其中 $\lambda_i \geq 0$ 且 $\sum_i \lambda_i = 1$。对于立方体,重心坐标恰好等于三线性插值权重:$\lambda_i = w_i$。

这个性质保证了:

  1. 保凸性:插值结果在顶点值的凸包内
  2. 线性精确性:对线性函数 $f(\mathbf{x}) = \mathbf{a}^T\mathbf{x} + b$,插值是精确的
  3. 对称性:对于对称的顶点值,插值结果也对称

梯度计算

尽管函数值连续,梯度在体素边界不连续。体素内部的梯度为:

\[\nabla f(\mathbf{x}) = \begin{pmatrix} \frac{\partial f}{\partial x} \\ \frac{\partial f}{\partial y} \\ \frac{\partial f}{\partial z} \end{pmatrix} = \begin{pmatrix} \frac{1}{\Delta x} \sum_{j',k'} (f_{1,j',k'} - f_{0,j',k'}) w_{j',k'}^{yz} \\ \frac{1}{\Delta y} \sum_{i',k'} (f_{i',1,k'} - f_{i',0,k'}) w_{i',k'}^{xz} \\ \frac{1}{\Delta z} \sum_{i',j'} (f_{i',j',1} - f_{i',j',0}) w_{i',j'}^{xy} \end{pmatrix}\]

其中 $w^{yz}$ 表示仅在 $y,z$ 维度的权重积。

梯度不连续性分析

考虑体素边界 $x = x_{i+1}$ 处的梯度跳变。从左侧接近(体素 $i$ 内): \(\frac{\partial f}{\partial x}\bigg|_{x_{i+1}^-} = \frac{1}{\Delta x}[(f_{i+1,j,k} - f_{i,j,k})(1-u_y)(1-u_z) + \ldots]\)

从右侧接近(体素 $i+1$ 内): \(\frac{\partial f}{\partial x}\bigg|_{x_{i+1}^+} = \frac{1}{\Delta x}[(f_{i+2,j,k} - f_{i+1,j,k})(1-u_y)(1-u_z) + \ldots]\)

跳变大小: \(\Delta\left(\frac{\partial f}{\partial x}\right) = \frac{\partial f}{\partial x}\bigg|_{x_{i+1}^+} - \frac{\partial f}{\partial x}\bigg|_{x_{i+1}^-}\)

这个跳变导致:

  1. 法线计算不稳定:基于梯度的法线在体素边界不连续
  2. 光照计算伪影:反射计算依赖于法线,导致可见的网格结构
  3. 优化不稳定性:导数不连续使得基于梯度的优化方法收敛困难

平滑梯度计算

为缓解梯度不连续问题,常用方法包括:

  1. 中心差分:使用相邻体素值 \(\frac{\partial f}{\partial x} \approx \frac{f_{i+1,j,k} - f_{i-1,j,k}}{2\Delta x}\)

  2. Sobel算子:带有平滑核的差分 \(G_x = \begin{bmatrix} -1 & 0 & 1 \\ -2 & 0 & 2 \\ -1 & 0 & 1 \end{bmatrix} * f\)

  3. 预平滑:先对场进行高斯平滑,再计算梯度

高阶插值方案

为获得更平滑的结果,可以使用高阶插值:

  1. 三次样条插值:保证 $C^2$ 连续性 \(f(\mathbf{x}) = \sum_{i=-1}^{2}\sum_{j=-1}^{2}\sum_{k=-1}^{2} f_{i+i_0,j+j_0,k+k_0} \cdot B(u_x-i)B(u_y-j)B(u_z-k)\) 其中 $B(t)$ 是三次B样条基函数

  2. Catmull-Rom插值:通过4个点的三次插值 \(f(u) = \frac{1}{2}\begin{pmatrix} u^3 & u^2 & u & 1 \end{pmatrix} \begin{pmatrix} -1 & 3 & -3 & 1 \\ 2 & -5 & 4 & -1 \\ -1 & 0 & 1 & 0 \\ 0 & 2 & 0 & 0 \end{pmatrix} \begin{pmatrix} f_{-1} \\ f_0 \\ f_1 \\ f_2 \end{pmatrix}\)

  3. Kaiser-Bessel窗插值:最小化频谱泄漏 \(w(r) = \begin{cases} \frac{I_0(\beta\sqrt{1-r^2})}{I_0(\beta)} & |r| \leq 1 \\ 0 & |r| > 1 \end{cases}\) 其中 $I_0$ 是修正贝塞尔函数,$\beta$ 控制窗口形状

B样条基函数详解

三次均匀B样条基函数定义为: \(B(t) = \begin{cases} \frac{2}{3} - |t|^2 + \frac{|t|^3}{2} & 0 \leq |t| < 1 \\ \frac{(2-|t|)^3}{6} & 1 \leq |t| < 2 \\ 0 & |t| \geq 2 \end{cases}\)

它具有以下性质:

插值的频域分析

从频域角度看,插值是一个低通滤波过程。三线性插值的频率响应:

\[H(\boldsymbol{\omega}) = \prod_{d \in \{x,y,z\}} \text{sinc}^2\left(\frac{\omega_d\Delta_d}{2}\right)\]

其中 $\text{sinc}(x) = \sin(x)/x$。这表明:

  1. 高频衰减:以 $ \omega ^{-2}$ 速率衰减
  2. 混叠:当采样率不足时产生摩尔纹
  3. 相位失真:非线性相位响应导致形状改变

更高阶的插值方法提供更好的频率特性,但计算成本也更高。

9.1.3 稀疏八叉树

对于大多数场景,空间是稀疏的——大部分体积为空。八叉树通过自适应细分提供了高效的表示。每个节点代表一个立方体区域,可以是:

形式化定义:

struct OctreeNode {
    Vector3 center;     // 节点中心
    float halfWidth;    // 半边长
    union {
        struct { float sigma; Vector3 color; } leaf;
        OctreeNode* children[8];
    };
    bool isLeaf;
}

子节点索引通过位操作确定: \(\text{childIndex} = (x > x_c) + 2(y > y_c) + 4(z > z_c)\)

八叉树遍历算法:

  1. 从根节点开始
  2. 计算射线与当前节点的交点
  3. 如果是叶节点,采样并累积
  4. 否则递归访问相交的子节点

遍历的期望复杂度为 $O(\log N)$,其中 $N$ 是叶节点数。证明基于平衡树的高度为 $\lceil \log_8 N \rceil$。

存储复杂度从密集网格的 $O(N^3)$ 降低到 $O(N_{\text{occupied}})$,其中 $N_{\text{occupied}}$ 是非空体素的数量。实际压缩率取决于场景稀疏性。

八叉树的数学结构

八叉树可以视为空间的递归分解。设空间域为 $\Omega = [0,1]^3$,则第 $\ell$ 层的每个节点对应一个子域:

\[\Omega_{\ell,i,j,k} = \left[\frac{i}{2^\ell}, \frac{i+1}{2^\ell}\right] \times \left[\frac{j}{2^\ell}, \frac{j+1}{2^\ell}\right] \times \left[\frac{k}{2^\ell}, \frac{k+1}{2^\ell}\right]\]

其中 $i,j,k \in {0,1,…,2^\ell-1}$。

特征函数表示: \(\chi_{\ell,i,j,k}(\mathbf{x}) = \begin{cases} 1 & \mathbf{x} \in \Omega_{\ell,i,j,k} \\ 0 & \text{otherwise} \end{cases}\)

场的多分辨率表示: \(f(\mathbf{x}) = \sum_{\ell=0}^{L} \sum_{(i,j,k) \in \mathcal{L}_\ell} c_{\ell,i,j,k} \chi_{\ell,i,j,k}(\mathbf{x})\)

其中 $\mathcal{L}\ell$ 是第 $\ell$ 层的叶节点集合,$c{\ell,i,j,k}$ 是存储的值。

高效光线-八叉树相交

优化的遍历算法利用空间相干性:

  1. 参数化相交测试:对于光线 $\mathbf{r}(t) = \mathbf{o} + t\mathbf{d}$,计算与节点边界的进入/退出参数: \(t_{\text{near}} = \max_{i \in \{x,y,z\}} \frac{(\mathbf{c}_i - h_i - \mathbf{o}_i)}{\mathbf{d}_i}, \quad t_{\text{far}} = \min_{i \in \{x,y,z\}} \frac{(\mathbf{c}_i + h_i - \mathbf{o}_i)}{\mathbf{d}_i}\) 其中 $\mathbf{c}$ 是节点中心,$h$ 是半边长

  2. 子节点访问顺序:基于光线方向确定遍历顺序,优先访问更近的子节点:
    childOrder = ComputeTraversalOrder(rayDirection)
    for i in childOrder:
        if RayIntersectsChild(ray, children[i]):
            TraverseChild(ray, children[i])
    
  3. 早期终止:当累积透明度低于阈值时停止遍历: \(T < \epsilon \Rightarrow \text{terminate}\)

区间算术优化

为避免浮点误差,使用区间算术进行保守的相交测试:

\[[t_{\text{near}}^-, t_{\text{near}}^+] = \max_{i} \left[\frac{\mathbf{c}_i - h_i - \mathbf{o}_i}{\mathbf{d}_i} - \epsilon, \frac{\mathbf{c}_i - h_i - \mathbf{o}_i}{\mathbf{d}_i} + \epsilon\right]\]

这保证不会错过任何相交,代价是可能会访问一些额外的边界节点。

遍历顺序预计算

对于给定的光线方向 $\mathbf{d} = (d_x, d_y, d_z)$,预计算所有可能的子节点访问顺序:

int orderLUT[8][8] = {
    // d_x >= 0, d_y >= 0, d_z >= 0
    {0, 1, 2, 3, 4, 5, 6, 7},
    // d_x < 0, d_y >= 0, d_z >= 0
    {1, 0, 3, 2, 5, 4, 7, 6},
    // ...
};
int lutIndex = (d_x < 0) + 2*(d_y < 0) + 4*(d_z < 0);

这种查找表方法避免了遍历时的排序计算。

自适应细分准则

决定何时细分节点的准则包括:

  1. 基于密度的细分:当节点内密度变化超过阈值 \(\text{var}(\sigma) > \tau_{\sigma} \Rightarrow \text{subdivide}\)

  2. 基于梯度的细分:在边界区域增加分辨率 \(\|\nabla\sigma\| > \tau_{\nabla} \Rightarrow \text{subdivide}\)

  3. 视点相关细分:基于投影大小动态调整 \(\frac{\text{nodeSize}}{\|\mathbf{x} - \mathbf{o}_{\text{camera}}\|} > \tau_{\text{pixel}} \Rightarrow \text{subdivide}\)

信息论细分准则

使用信息增益来决定是否细分。设节点 $n$ 包含样本集 $S_n$,则信息熵:

\[H(S_n) = -\sum_{i} p_i \log p_i\]

其中 $p_i$ 是类别 $i$ 的概率(例如,空/非空)。

细分后的信息增益: \(IG = H(S_n) - \sum_{c=0}^{7} \frac{|S_{n,c}|}{|S_n|} H(S_{n,c})\)

当 $IG > \tau_{IG}$ 时进行细分。

误差引导的细分

基于重建误差的自适应细分:

\[E_n = \int_{\Omega_n} |f(\mathbf{x}) - \bar{f}_n|^2 d\mathbf{x}\]

其中 $\bar{f}_n$ 是节点 $n$ 内的常数近似。

使用泰勒展开估计误差: \(E_n \approx \frac{h_n^2}{12} \int_{\Omega_n} \|\nabla f(\mathbf{x})\|^2 d\mathbf{x}\)

其中 $h_n$ 是节点大小。这导致基于梯度的细分准则。

内存优化技术

  1. 线性八叉树:使用Morton编码将树结构线性化 \(\text{MortonCode}(x,y,z) = \sum_{i=0}^{L-1} 2^{3i}[(x_i) + 2(y_i) + 4(z_i)]\) 其中 $x_i, y_i, z_i$ 是坐标的第 $i$ 位

  2. 节点池分配:预分配大块内存,减少碎片
    nodePool = AllocateBlock(MAX_NODES * sizeof(OctreeNode))
    freeList = InitializeFreeList(nodePool)
    
  3. LOD(细节层次):存储多分辨率版本
    • 粗糙级别用于远处物体
    • 精细级别用于近处细节
    • 级别间的平滑过渡

Morton编码的位交织实现

Morton编码的核心是位交织操作。对于32位整数:

uint32_t expandBits(uint32_t v) {
    v = (v * 0x00010001u) & 0xFF0000FFu;
    v = (v * 0x00000101u) & 0x0F00F00Fu;
    v = (v * 0x00000011u) & 0xC30C30C3u;
    v = (v * 0x00000005u) & 0x49249249u;
    return v;
}

uint32_t morton3D(uint32_t x, uint32_t y, uint32_t z) {
    return expandBits(x) | (expandBits(y) << 1) | (expandBits(z) << 2);
}

这种编码保持了空间局部性:相邻的Morton码对应空间中相近的位置。

紧凑指针结构

为进一步减少内存,使用紧凑的指针表示:

struct CompactOctreeNode {
    uint32_t childrenOffset; // 相对于节点池的偏移
    uint8_t validMask;       // 位掩码指示哪些子节点存在
    uint8_t leafMask;        // 位掩码指示哪些子节点是叶子
    // 数据紧随其后
};

这将每个节点的开销从64字节降低到约16字节。

并行构建算法

利用GPU并行性加速八叉树构建:

  1. 自顶向下构建
    • 并行计算每个节点的占用状态
    • 使用原子操作分配子节点
    • 复杂度:$O(\log N)$ 并行步骤
  2. 自底向上构建
    • 首先对所有点进行空间排序(Morton编码)
    • 并行识别节点边界
    • 自底向上合并构建树
    • 复杂度:$O(N \log N)$ 工作量,$O(\log N)$ 深度

基于合并的并行构建

给定排序后的点集,使用分治策略:

  1. 划分阶段:找到分割点将点集分为8个子集
    parallel for each level l:
        for each node at level l:
            splitPoints = FindOctantBoundaries(points)
            AssignPointsToChildren(points, splitPoints)
    
  2. 合并阶段:自底向上合并节点信息
    parallel for each level l from leaf to root:
        for each node at level l:
            node.bounds = Union(children.bounds)
            node.density = Average(children.density)
    

GPU优化策略

  1. 宽度优先遍历:适合GPU的SIMD执行模型
  2. 紧凑存储布局:最大化合并内存访问
  3. 工作负载平衡:使用工作窃取模式处理不均匀的树结构
  4. 流压缩:即时压缩稀疏节点,减少内存带宽

这些优化使得可以在毫秒级时间内构建包含数百万节点的八叉树。

9.2 Plenoxels:球谐函数体素

9.2.1 球谐函数回顾

球谐函数 $Y_{\ell}^m(\theta, \phi)$ 形成了球面 $S^2$ 上平方可积函数的完备正交基。它们是拉普拉斯-贝尔特拉米算子在球面上的本征函数:

\[\nabla^2_{S^2} Y_{\ell}^m = -\ell(\ell+1) Y_{\ell}^m\]

复球谐函数定义为:

\[Y_{\ell}^m(\theta, \phi) = \sqrt{\frac{2\ell+1}{4\pi}\frac{(\ell-m)!}{(\ell+m)!}} P_{\ell}^m(\cos\theta) e^{im\phi}\]

其中 $P_{\ell}^m$ 是关联勒让德多项式,满足: \(P_{\ell}^m(x) = (-1)^m (1-x^2)^{m/2} \frac{d^m}{dx^m} P_{\ell}(x)\)

对于计算机图形学中的实值函数,我们使用实球谐函数基:

前几阶的具体形式:

9.2.2 Plenoxels 表示

Plenoxels(”Plenoptic Voxels”的缩写)是一种纯显式优化方法,完全避免了神经网络。在每个体素中存储:

  1. 体积密度 $\sigma \in \mathbb{R}^+$:控制不透明度
  2. 球谐系数 $\mathbf{k} \in \mathbb{R}^{(L+1)^2 \times 3}$:编码视角相关的RGB颜色

视角相关的辐射通过球谐展开计算:

\[\mathbf{c}(\mathbf{x}, \mathbf{d}) = \text{sigmoid}\left(\sum_{\ell=0}^{L} \sum_{m=-\ell}^{\ell} \mathbf{k}_{\ell m}(\mathbf{x}) Y_{\ell m}(\mathbf{d})\right)\]

其中:

9.2.3 直接优化

与NeRF不同,Plenoxels直接优化体素参数,无需神经网络。这导致了一个大规模但结构化的优化问题。损失函数包含数据项和正则化项:

\[\mathcal{L} = \mathcal{L}_{\text{data}} + \lambda_{\text{TV}} \mathcal{L}_{\text{TV}} + \lambda_{\text{sparse}} \mathcal{L}_{\text{sparse}}\]

数据项衡量渲染图像与真实图像的差异: \(\mathcal{L}_{\text{data}} = \sum_{\mathbf{r} \in \mathcal{R}} \|\hat{C}(\mathbf{r}) - C(\mathbf{r})\|^2\)

总变差(TV)正则化促进空间平滑性: \(\mathcal{L}_{\text{TV}} = \sum_{i,j,k} \left(\|\sigma_{i+1,j,k} - \sigma_{i,j,k}\|^2 + \|\sigma_{i,j+1,k} - \sigma_{i,j,k}\|^2 + \|\sigma_{i,j,k+1} - \sigma_{i,j,k}\|^2\right)\)

这等价于各向异性TV范数,防止密度场出现噪声。

稀疏性正则化鼓励空体素: \(\mathcal{L}_{\text{sparse}} = \sum_{i,j,k} \log(1 + \sigma_{ijk}^2/\epsilon^2)\)

这是 $\ell_1$ 范数的平滑近似,避免了不可微点。

优化使用Adam优化器,学习率调度遵循: \(\eta(t) = \eta_0 \cdot 0.1^{t/T}\)

梯度通过可微体积渲染反向传播: \(\frac{\partial \mathcal{L}}{\partial \sigma_{ijk}} = \sum_{\mathbf{r} \text{ through } (i,j,k)} \frac{\partial \mathcal{L}}{\partial C(\mathbf{r})} \frac{\partial C(\mathbf{r})}{\partial \sigma_{ijk}}\)

9.3 TensoRF:张量分解辐射场

9.3.1 张量分解基础

TensoRF的核心洞察是辐射场具有低秩结构——场景中的规律性(平面、对称性、重复纹理)导致信息冗余。通过张量分解,我们可以用紧凑的因子表示高维数据。

考虑4D辐射场张量 $\mathcal{T} \in \mathbb{R}^{X \times Y \times Z \times C}$,其中前三维是空间坐标,第四维是特征通道。

CP分解(CANDECOMP/PARAFAC)将张量表示为秩-1张量的和: \(\mathcal{T} = \sum_{r=1}^{R} \lambda_r \cdot \mathbf{u}_r \otimes \mathbf{v}_r \otimes \mathbf{w}_r \otimes \mathbf{s}_r\)

其中:

元素形式: \(\mathcal{T}_{ijkc} = \sum_{r=1}^{R} \lambda_r u_{ri} v_{rj} w_{rk} s_{rc}\)

向量-矩阵(VM)分解是CP分解的推广,将某些模式组合成矩阵: \(\mathcal{T} = \sum_{r=1}^{R_1} \mathbf{M}_{r,xy} \otimes \mathbf{v}_{r,z} \otimes \mathbf{b}_{r,1} + \sum_{r=1}^{R_2} \mathbf{M}_{r,xz} \otimes \mathbf{v}_{r,y} \otimes \mathbf{b}_{r,2} + \sum_{r=1}^{R_3} \mathbf{M}_{r,yz} \otimes \mathbf{v}_{r,x} \otimes \mathbf{b}_{r,3}\)

其中 $\mathbf{M}_{r,\cdot} \in \mathbb{R}^{D_1 \times D_2}$ 是矩阵因子。这种分解更灵活,可以捕获平面结构。

9.3.2 密度和外观分解

TensoRF 分别建模密度和外观,利用它们的不同特性:

密度场使用VM分解: \(\sigma(\mathbf{x}) = \text{ReLU}\left(\sum_{r=1}^{R_\sigma} \left\langle \mathbf{A}_r^{\sigma}, \mathbf{x} \right\rangle + b_\sigma\right)\)

其中 $\mathbf{A}_r^{\sigma}$ 是通过VM分解得到的: \(\mathbf{A}_r^{\sigma} = \sum_{i=1}^{3} \mathbf{M}_{r,i}^{\sigma} \otimes \mathbf{v}_{r,i}^{\sigma}\)

这种分解特别适合表示平面结构(墙壁、地板)和轴对齐的几何。

外观场结合张量分解和小型神经网络: \(\mathbf{c}(\mathbf{x}, \mathbf{d}) = \mathcal{F}_\theta\left(\mathbf{f}_{\text{app}}(\mathbf{x}), \mathbf{d}\right)\)

其中外观特征 $\mathbf{f}_{\text{app}}(\mathbf{x})$ 通过VM分解计算: \(\mathbf{f}_{\text{app}}(\mathbf{x}) = \sum_{r=1}^{R_c} \left\langle \mathbf{A}_r^{c}, \mathbf{x} \right\rangle\)

解码器 $\mathcal{F}_\theta$ 是一个2层MLP,将空间特征和视角方向映射到RGB颜色: \(\mathcal{F}_\theta: \mathbb{R}^{R_c} \times S^2 \rightarrow [0,1]^3\)

这种混合方法平衡了表达能力和计算效率。

9.3.3 存储和计算复杂度

存储分析

对于分辨率 $N^3$ 的密集网格,原始存储需求为 $O(N^3C)$,其中 $C$ 是每个体素的通道数。

TensoRF的存储需求:

压缩率: \(\text{压缩率} = \frac{N^3C}{RN^2} = \frac{NC}{R}\)

典型情况下,$N=300$,$C=4$,$R=16$,压缩率约为 75×。

计算复杂度

查询单个点的值:

虽然单点查询更慢,但:

  1. $R \ll N$(通常 $R \sim 16-48$)
  2. 向量运算可以高效并行化
  3. 缓存局部性更好(因子向量可以驻留在缓存中)

9.4 低秩与稀疏表示

9.4.1 数学基础

辐射场的低秩结构源于场景的内在规律性——平坦表面、重复纹理、对称性等。这些规律性在适当的基下表现为数据矩阵的低秩性。

奇异值分解(SVD)提供了最优低秩近似。对于矩阵 $\mathbf{A} \in \mathbb{R}^{m \times n}$:

\[\mathbf{A} = \mathbf{U}\mathbf{\Sigma}\mathbf{V}^T = \sum_{i=1}^{r} \sigma_i \mathbf{u}_i \mathbf{v}_i^T\]

其中:

Eckart-Young定理:最优 $k$ 秩近似(在任何酉不变范数下)是: \(\mathbf{A}_k = \sum_{i=1}^{k} \sigma_i \mathbf{u}_i \mathbf{v}_i^T\)

近似误差: \(\|\mathbf{A} - \mathbf{A}_k\|_F = \sqrt{\sum_{i=k+1}^{r} \sigma_i^2}\) \(\|\mathbf{A} - \mathbf{A}_k\|_2 = \sigma_{k+1}\)

有效秩衡量矩阵的”近似秩”: \(r_{\text{eff}}(\mathbf{A}) = \frac{\|\mathbf{A}\|_F^2}{\|\mathbf{A}\|_2^2} = \frac{\sum_{i=1}^r \sigma_i^2}{\sigma_1^2}\)

当奇异值快速衰减时,有效秩远小于真实秩,表明数据可压缩。

9.4.2 稀疏性诱导

许多场景在适当的变换域中是稀疏的。关键是找到使信号稀疏的基。

稀疏表示问题:给定过完备字典 $\mathbf{D} \in \mathbb{R}^{n \times p}$($p > n$),寻找稀疏系数 $\mathbf{w}$: \(\mathbf{f} = \mathbf{D}\mathbf{w}, \quad \|\mathbf{w}\|_0 \ll p\)

其中 $|\mathbf{w}|_0$ 计算非零元素个数。

由于 $\ell_0$ 优化是NP难的,我们使用 $\ell_1$ 松弛: \(\min_{\mathbf{w}} \frac{1}{2}\|\mathbf{y} - \mathbf{D}\mathbf{w}\|_2^2 + \lambda\|\mathbf{w}\|_1\)

这是LASSO问题,可通过多种算法求解:

迭代收缩阈值算法(ISTA): \(\mathbf{w}^{(k+1)} = \mathcal{S}_{\lambda/L}\left(\mathbf{w}^{(k)} + \frac{1}{L}\mathbf{D}^T(\mathbf{y} - \mathbf{D}\mathbf{w}^{(k)})\right)\)

其中 $\mathcal{S}_\tau(x) = \text{sign}(x)\max( x -\tau, 0)$ 是软阈值算子,$L$ 是 $\mathbf{D}^T\mathbf{D}$ 的最大特征值。

快速ISTA(FISTA)通过动量加速收敛: \(\mathbf{z}^{(k+1)} = \mathbf{w}^{(k)} + \frac{k-1}{k+2}(\mathbf{w}^{(k)} - \mathbf{w}^{(k-1)})\)

收敛率从 $O(1/k)$ 提升到 $O(1/k^2)$。

9.4.3 压缩感知视角

压缩感知理论表明,稀疏信号可以从远少于奈奎斯特速率的测量中精确重建。

限制等距性质(RIP):矩阵 $\mathbf{A}$ 满足阶为 $s$ 的RIP,如果存在 $\delta_s \in (0,1)$ 使得对所有 $s$-稀疏向量 $\mathbf{x}$: \((1-\delta_s)\|\mathbf{x}\|_2^2 \leq \|\mathbf{A}\mathbf{x}\|_2^2 \leq (1+\delta_s)\|\mathbf{x}\|_2^2\)

重建保证:如果 $\mathbf{A}$ 满足 $\delta_{2s} < \sqrt{2} - 1$,则 $\ell_1$ 最小化的解 $\mathbf{x}^*$ 满足: \(\|\mathbf{x}^* - \mathbf{x}\|_2 \leq \frac{C}{\sqrt{s}}\|\mathbf{x} - \mathbf{x}_s\|_1 + C'\epsilon\)

其中 $\mathbf{x}_s$ 是 $\mathbf{x}$ 的最佳 $s$ 项近似,$\epsilon$ 是测量噪声。

对于辐射场重建:

所需测量数:$M = O(s\log(N/s))$,其中 $s$ 是稀疏度,$N$ 是信号维度。

9.5 显式与隐式权衡

9.5.1 内存占用

隐式(NeRF)

显式(体素)

9.5.2 渲染速度

查询复杂度

缓存效率

9.5.3 训练特性

收敛速度

表示能力

9.5.4 统一视角

两种方法都解决相同的体积渲染方程:

\[C(\mathbf{r}) = \int_{t_n}^{t_f} T(t)\sigma(t)\mathbf{c}(t,\mathbf{d})dt\]

区别在于如何表示 $\sigma$ 和 $\mathbf{c}$:

选择取决于具体应用需求。

本章小结

本章探讨了神经辐射场的显式表示方法,展示了如何将离散空间结构统一到体积渲染框架中:

核心概念

  1. 体素网格:最直接的显式表示,通过三线性插值实现连续性
  2. Plenoxels:使用球谐函数编码视角相关效果,直接优化无需神经网络
  3. TensoRF:通过张量分解实现紧凑表示,将存储从 $O(N^3)$ 降至 $O(RN)$
  4. 低秩结构:利用场景的内在规律性进行压缩

关键公式

实践要点

练习题

基础题

练习 9.1:八叉树遍历复杂度 证明在平衡八叉树中,从根到叶的平均遍历深度是 $O(\log N)$,其中 $N$ 是叶节点数。

提示 考虑深度为 $d$ 的完全八叉树最多包含多少叶节点。
答案 深度为 $d$ 的完全八叉树最多有 $8^d$ 个叶节点。 如果有 $N$ 个叶节点,则最小深度 $d$ 满足: $$8^{d-1} < N \leq 8^d$$ 取对数: $$d-1 < \log_8 N \leq d$$ 因此 $d = \lceil \log_8 N \rceil = O(\log N)$。 平均情况下,假设叶节点均匀分布,平均深度约为 $\log_8 N$。

练习 9.2:球谐函数正交性 证明前两阶球谐函数在单位球面上正交: \(\int_{S^2} Y_{\ell m}(\mathbf{d}) Y_{\ell' m'}(\mathbf{d}) d\mathbf{d} = \delta_{\ell\ell'}\delta_{mm'}\)

提示 使用球坐标 $(\theta, \phi)$ 并利用关联勒让德多项式的正交性。
答案 在球坐标中: $$\int_{S^2} Y_{\ell m} Y_{\ell' m'} d\mathbf{d} = \int_0^{2\pi} \int_0^{\pi} Y_{\ell m}(\theta,\phi) Y_{\ell' m'}(\theta,\phi) \sin\theta d\theta d\phi$$ 代入球谐函数定义: $$= \sqrt{\frac{(2\ell+1)(2\ell'+1)}{16\pi^2} \frac{(\ell-m)!(\ell'-m')!}{(\ell+m)!(\ell'+m')!}} \times$$ $$\int_0^{2\pi} e^{i(m-m')\phi} d\phi \int_0^{\pi} P_{\ell}^m(\cos\theta) P_{\ell'}^{m'}(\cos\theta) \sin\theta d\theta$$ 方位角积分给出 $2\pi\delta_{mm'}$。 对于极角积分,令 $x = \cos\theta$: $$\int_{-1}^{1} P_{\ell}^m(x) P_{\ell'}^{m}(x) dx = \frac{2}{2\ell+1} \frac{(\ell+m)!}{(\ell-m)!} \delta_{\ell\ell'}$$ 组合所有项得到 $\delta_{\ell\ell'}\delta_{mm'}$。

练习 9.3:三线性插值连续性 证明三线性插值在体素边界处是 $C^0$ 连续但不是 $C^1$ 连续。

提示 检查跨越体素边界时函数值和导数的行为。
答案 考虑1D情况的线性插值: $$f(x) = f_0(1-x) + f_1 x, \quad x \in [0,1]$$ 在边界 $x=1$ 处,从当前体素:$f(1^-) = f_1$ 从相邻体素(新坐标系):$f(0^+) = f_1$ 因此函数值连续($C^0$)。 但导数: - 当前体素:$f'(1^-) = f_1 - f_0$ - 相邻体素:$f'(0^+) = f_2 - f_1$ 一般情况下 $f'(1^-) \neq f'(0^+)$,所以不是 $C^1$ 连续。 三线性情况类似,在每个维度独立应用。

挑战题

练习 9.4:张量分解误差界 给定秩为 $r$ 的 3 阶张量 $\mathcal{T} \in \mathbb{R}^{n \times n \times n}$,推导 CP 分解的最优 $k$ 项近似误差界。

提示 类比矩阵 SVD 的 Eckart-Young 定理,但注意张量情况更复杂。
答案 与矩阵不同,张量的最优低秩近似不一定由截断的CP分解给出。但我们可以建立界限。 设 $\mathcal{T}_k$ 是最优 $k$ 秩近似,$\tilde{\mathcal{T}}_k$ 是 $k$ 项CP分解。则: $$\|\mathcal{T} - \tilde{\mathcal{T}}_k\|_F \leq \sqrt{1 + \epsilon_k} \|\mathcal{T} - \mathcal{T}_k\|_F$$ 其中 $\epsilon_k$ 依赖于张量的条件数。 对于"良态"张量(如低秩加噪声),CP分解给出近最优近似: $$\|\mathcal{T} - \tilde{\mathcal{T}}_k\|_F \leq C\sqrt{\sum_{i=k+1}^r \lambda_i^2}$$ 其中 $\lambda_i$ 是张量的"奇异值"(通过高阶SVD定义),$C$ 是常数。

练习 9.5:稀疏八叉树的期望存储 考虑在单位立方体中均匀分布的 $M$ 个点,每个点占据半径 $\epsilon$ 的球。推导存储这些点所需的八叉树节点数的期望值。

提示 计算不同深度级别的期望占用体素数。
答案 在深度 $d$ 处,体素大小为 $2^{-d}$。 一个半径 $\epsilon$ 的球与体素相交的条件是球心到体素的距离 $\leq \epsilon + \frac{\sqrt{3}}{2} \cdot 2^{-d}$。 在深度 $d$ 的期望占用体素数: $$E[N_d] = \min\left(8^d, M \cdot V_{\text{intersection}}(d) \cdot 8^d\right)$$ 其中 $V_{\text{intersection}}(d)$ 是相交体积。 当 $2^{-d} \gg \epsilon$:一个球占据 $O(1)$ 个体素 当 $2^{-d} \ll \epsilon$:一个球占据 $O((\epsilon \cdot 2^d)^3)$ 个体素 最优深度约为 $d^* = \log_2(1/\epsilon)$,总存储: $$E[N_{\text{total}}] = O(M) + O(M(\epsilon \cdot 2^{d^*})^3) = O(M)$$ 因此稀疏八叉树存储与点数成线性关系。

练习 9.6:Plenoxels vs NeRF 收敛分析 分析为什么直接优化体素参数(Plenoxels)比通过神经网络(NeRF)收敛更快。考虑优化landscape和梯度流。

提示 比较参数到输出的映射复杂度和梯度传播路径。
答案 **Plenoxels 优化景观**: - 参数直接映射到输出:$\theta_{ijk} \rightarrow C(\mathbf{r})$ - 凸优化问题(对每个体素独立) - 梯度:$\frac{\partial \mathcal{L}}{\partial \theta_{ijk}} = \sum_{\mathbf{r} \text{ through } ijk} \frac{\partial \mathcal{L}}{\partial C(\mathbf{r})} \frac{\partial C(\mathbf{r})}{\partial \theta_{ijk}}$ **NeRF 优化景观**: - 非凸,多个局部最小值 - 梯度通过多层网络:$\frac{\partial \mathcal{L}}{\partial \mathbf{W}} = \frac{\partial \mathcal{L}}{\partial C} \prod_{l} \frac{\partial f_l}{\partial f_{l-1}} \frac{\partial f_1}{\partial \mathbf{W}}$ - 梯度消失/爆炸问题 **收敛速度差异**: 1. **条件数**:Plenoxels 的 Hessian 对角占优,条件数更好 2. **局部性**:每个体素参数主要影响局部区域 3. **并行性**:体素更新可以并行进行 理论上,Plenoxels 的收敛速度为 $O(1/t)$(凸优化),而 NeRF 为 $O(1/\sqrt{t})$(非凸)。

常见陷阱与错误

  1. 内存爆炸:密集体素网格的 $O(N^3)$ 增长
    • 调试技巧:始终从粗分辨率开始,监控内存使用
  2. 混叠伪影:采样不足导致的摩尔纹
    • 调试技巧:使用抗混叠滤波器,增加超采样
  3. 数值不稳定:张量分解中的退化情况
    • 调试技巧:添加小的正则化项 $\epsilon I$,使用稳定的初始化
  4. 边界伪影:体素边界的不连续性
    • 调试技巧:扩展边界体素,使用更高阶插值
  5. 稀疏性与质量权衡:过度稀疏化导致细节丢失
    • 调试技巧:使用自适应阈值,保留重要区域
  6. 球谐截断误差:低阶球谐不能表示高频
    • 调试技巧:分析频谱内容,自适应选择阶数

最佳实践检查清单

设计显式神经表示时,确保: