项目链接:https://repo-sam.inria.fr/fungraph/3d-gaussian-splatting/ 代码链接:https://github.com/graphdeco-inria/gaussian-splatting 论文链接:https://repo-sam.inria.fr/fungraph/3d-gaussian-splatting/3d_gaussian_splatting_low.pdf

3D 高斯椭球

  1. 很好的数学性质
    • 仿射变换后高斯核仍然闭合
    • 3D 降维到 2D 后(沿着某一个轴积分(z 轴))仍然为高斯
  2. 定义:

    • 椭球高斯函数:
    \[ G(x) = \frac{1}{\sqrt{2\pi^k|\Sigma|}}e^{-\frac{1}{2}(x-\mu)^T\Sigma^{-1}(x-\mu)} \]

    其中\(\Sigma\)表示协方差矩阵,半正定,\(|\Sigma|\)是其行列式,\(\mu\)表示均量.

3D gaussian 为什么是椭球?

对于椭球高斯函数:

\[ G(x) = \frac{1}{\sqrt{2\pi^k|\Sigma|}}e^{-\frac{1}{2}(x-\mu)^T\Sigma^{-1}(x-\mu)} \]

来说,

\[ {\sqrt{2\pi^k|\Sigma|}} \]

始终是一个常数,变量只存在于,

\[ {-\frac{1}{2}(x-\mu)^T\Sigma^{-1}(x-\mu)} \]

当

\[ {(x-\mu)^T\Sigma^{-1}(x-\mu)}=constant \]

等于常数时,可展开为:

\[ \begin{align} constant ;= (x-\mu)^T\Sigma^{-1}(x-\mu) \\ ;= \frac{(x-\mu_x)^2}{\sigma_x^2} + \frac{(y-\mu_y)^2}{\sigma_y^2} + \frac{(z-\mu_z)^2}{\sigma_z^2} - \frac{2\sigma_{xy}(x-\mu_x)(y-\mu_y)}{\sigma_x\sigma_y}-\frac{2\sigma_{xz}(x-\mu_x)(z-\mu_z)}{\sigma_x\sigma_z}-\frac{2\sigma_{yz}(y-\mu_y)(z-\mu_z)}{\sigma_y\sigma_z} \end{align} \\ equal \quad to: Ax^2+By^2+Cz^2+2Dxy+2Exz+2Fyz=1 \]

其中:

\[ \Sigma = \begin{pmatrix} \sigma_x^2 ; \sigma_{xy} ; \sigma_{xz} \\ \sigma_{xy} ; \sigma_y^2 ; \sigma_{yz} \\ \sigma_{xz} ; \sigma_{yz} ; \sigma_z^2 \end{pmatrix} \]

最终就是一个椭圆面的表示形式。而

\[ {(x-\mu)^T\Sigma^{-1}(x-\mu)} \]

是有取值范围的,所以整体表现出来就是一个实心的椭球体。

如何利用旋转和缩放计算协方差矩阵

对应于 cuda 代码中的 computeConv3D

高斯分布:
*\(\boldsymbol{x}\sim N(\mu, \Sigma)\) * 均值:\(\mu_x, \mu_y, \mu_z\) * 协方差矩阵:

\[ \Sigma = \begin{pmatrix} \sigma*x^2 ; \sigma*{xy} ; \sigma*{xz} \\ \sigma*{yx} ; \sigma*y^2 ; \sigma*{yz} \\ \sigma*{zx} ; \sigma*{zy} ; \sigma_z^2 \end{pmatrix} \]

高斯分布的仿射变换: \(\boldsymbol{w} = A\boldsymbol{x}+b\) \(\boldsymbol{w} \sim N(A\mu+b, A\Sigma A^T)\) * 协方差和 b 没有关系

标准高斯分布: *\(\boldsymbol{x} \sim N(\bold{0}, I)\) * 均值:\(\bold{0}\) 协方差矩阵:

\[ \boldsymbol{\Sigma} = \begin{pmatrix} 1 ; 0 ; 0 \\ 0 ; 1 ; 0 \\ 0 ; 0 ; 1 \end{pmatrix} \]

*\(\boldsymbol{\Sigma} = \boldsymbol{A} \cdot \boldsymbol{I} \cdot \boldsymbol{A}^T\)任意高斯可以看作是标准高斯通过仿射变换得到

\[ \boldsymbol{A} = RS \]

其中R是旋转矩阵,S是缩放矩阵,因此

\[ \begin{align} \boldsymbol{\Sigma} = \boldsymbol{A} \cdot \boldsymbol{I} \cdot \boldsymbol{A}^T\\ =\boldsymbol{R}\boldsymbol{S}\boldsymbol{S}^T\boldsymbol{R}^T \end{align} \]

Splatting 过程介绍——从 3D 到像素

投影变换

正交投影

  • 对于一个立方体[l,r]×[b,t]×[f,n],将其平移到原点,然后缩放为[−1,1]×[−1,1]×[−1,1]的正方体
  • 投影矩阵:
\[ \begin{bmatrix} 2/(r-l) & 0 & 0 & 0 \\ 0 & 2/(t-b) & 0 & 0 \\ 0 & 0 & 2/(n-f) & 0 \\ 0 & 0 & 0 & 1 \end{bmatrix} \begin{bmatrix} 1 & 0 & 0 & -(r+l)/2 \\ 0 & 1 & 0 & -(t+b)/2 \\ 0 & 0 & 1 & -(n+f)/2 \\ 0 & 0 & 0 & 1 \end{bmatrix} \]

透视投影

有远小近大的原则,投影出来是一个锥体。因此需要先把锥体压成立方体,然后再进行正交投影,透视投影是非线性的,不是仿射变换。

\[ \boldsymbol{M}_{persp->ortho} = \begin{bmatrix} n & 0 & 0 & 0 \\ 0 & n & 0 & 0 \\ 0 & 0 & n+f & -nf \\ 0 & 0 & -1 & 0 \end{bmatrix} \]

视口变换

不管是透视投影还是正交投影,最终得到的都是\([-1, 1]^3\)范围内的立方体,然后进行视口变换将其映射回图片的大小 height * width,恢复出原始比例

\[ \boldsymbol{M}_{viewpoint} = \begin{bmatrix} \frac{w}{2} & 0 & 0 & \frac{w}{2} \\ 0 & \frac{h}{2} & 0 & \frac{h}{2} \\ 0 & 0 & 1 & 0 \\ 0 & 0 & 0 & 1 \end{bmatrix} \]

3D 高斯的观测变换过程,如何把物理坐标系的物体映射到像素空间

第一步:从物理坐标系到相机坐标系 * 物理坐标系: * 高斯核的中心点:\(\boldsymbol{t}_k = [t_x, t_y, t_z]^T\) * 高斯核对应的高斯分布:\(r^{, , }_k(t) = G_{V_k^{, , }}(t-t_k)\) * 其中\(V_k^{, , }\)是协方差矩阵 * 相机坐标系: * 高斯核中心:\(\boldsymbol{\mu}_k = [\mu_x, \mu_y, \mu_z]^T\) * 高斯核对应的高斯分布:\(r^{, }_k(t) = G_{V_k^{, }}(\mu-\boldsymbol{\mu}_k)\) * 均值:\(\boldsymbol{\mu}_k = Wt_k+d\) * 协方差矩阵:\(V_k^{, } = WV_k^{, , }W^T\)

  • 这一步就是简单做个仿射变换,3D 空间的坐标变换

第二步:从相机坐标系到像素空间 * 相机坐标系: * 高斯核中心:\(\boldsymbol{\mu}_k = [\mu_x, \mu_y, \mu_z]^T\) * 协方差矩阵:\(V_k^{, }\) * 投影变换:(非线性的变换,需要做泰勒展开做局部的线性近似) * 高斯核中心:\(\boldsymbol{x}_k = [x_x, x_y, x_z]^T\) * 高斯核对应的高斯分布:\(r_k(t) = G_{V_k}(x-\boldsymbol{x}_k)\) * 均值:& \boldsymbol{x}_k = m(\mu_k) &(对均值可以直接做非线性变换,不需要局部线性近似) * 协方差矩阵:\(V_k = \boldsymbol{J}V_k^{, }\boldsymbol{J}^T\) * 其中 \(\boldsymbol{J} = \frac{\partial m(\mu_k)}{\partial \mu}\) 为雅可比矩阵 * 至此,协方差矩阵\(V_k = \boldsymbol{J}WV_k^{, , }W^T\boldsymbol{J}^T\)

如何求得雅可比矩阵?

已知:

\[ \boldsymbol{M}_{persp-ortho} = \begin{bmatrix} n & 0 & 0 & 0 \\ 0 & n & 0 & 0 \\ 0 & 0 & n+f & -nf \\ 0 & 0 & -1 & 0 \end{bmatrix} \]

视锥中一个点:\([x y z 1]^T\)对其应用投影变换后:

\[ \begin{bmatrix} x_1 \\ x_2 \\ x_3 \\ 1 \end{bmatrix} = \begin{bmatrix} n & 0 & 0 & 0 \\ 0 & n & 0 & 0 \\ 0 & 0 & n+f & -nf \\ 0 & 0 & -1 & 0 \end{bmatrix} \begin{bmatrix} x \\ y \\ z \\ 1 \end{bmatrix} = \begin{bmatrix} nx \\ ny \\ (n+f)z-nf \\ z \end{bmatrix} = \begin{bmatrix} \frac{nx}{z} \\ \frac{ny}{z} \\ (n+f)-\frac{nf}{z} \\ 1 \end{bmatrix} \]

由此,雅可比矩阵为:

\[ \boldsymbol{J} = \begin{bmatrix} \frac{df_1}{dx} & \frac{df_1}{dy} & \frac{df_1}{dz} \\ \frac{df_2}{dx} & \frac{df_2}{dy} & \frac{df_2}{dz} \\ \frac{df_3}{dx} & \frac{df_3}{dy} & \frac{df_3}{dz} \\ \end{bmatrix} = \begin{bmatrix} \frac{n}{z} & 0 & -\frac{nx}{z^2} \\ 0 & \frac{n}{z} & -\frac{ny}{z^2} \\ 0 & 0 & -\frac{nf}{z^2} \\ \end{bmatrix} \]

3D 高斯球的颜色表示

把高斯椭球的颜色表示成了一个颜色球,这个颜色球从不同角度观察,都可以看到不同的颜色。但是颜色球的颜色应该怎么描述呢?这里就是使用球谐函数来对其做近似,然后从不同角度对其做渲染

球谐函数

  • 任何一个球面坐标的函数,都可以用多个球谐函数来近似 *\(f(t) \approx \sum_l\sum^l_{m=-l}c_l^my_l^m(\theta, \phi)\)
  • 其中,l表示当前的阶数,\(c_l^m\)是各项系数,\(y_l^m\)是基函数

\[ \begin{align} f(t) &\approx \sum_l\sum^l_{m=-l}c_l^my_l^m(\theta, \phi) \\ = &c_0^0y_0^0 + \\ &c_1^{-1}y_1^{-1} + c_1^{0}y_1^{0} + c_1^{1}y_1^{1}+ \\ &c_2^{-2}y_2^{-2} + c_2^{-1}y_2^{-1} + c_2^{0}y_2^{0} + c_2^{1}y_2^{1} + c_2^{2}y_2^{2} +\\ &... \end{align} \]
  • 其中各个基函数为:
\[ y_0^0 = \sqrt{\frac{1}{4\pi}} \\ y_1^{-1} = \sqrt{\frac{3}{4\pi}}\frac{y}{r}\\ y_1^{0} = \sqrt{\frac{3}{4\pi}}\frac{z}{r}\\ ... \\ \]
  • 由此,当 xyz 固定时,基函数就是固定的,但是系数是变化的。当系数维度为 3 时,共有 16 个系数,即一个高斯球,有 16 个颜色系数要估计

使用 α-blending 计算像素的颜色

与 NERF 中公式相同

\[ \begin{align} C &= T_i \alpha_i c_i \\ &= \sum_{i=1}^N T_i(1-e^{-\sigma_i\delta_i}c_i) \end{align} \\ where: T_i = r^{-\sum_{j=1}^{i-1}\sigma_i\delta_j} \]

其中: \(T_i\):在 s 点之前,光线没有被阻挡的概率 \(\alpha_i\):在 s 点处,光线被遮挡的概率。包含两点:1. 高斯椭球本身的不透明度;2. 该像素点距离高斯椭球中心越远,高斯椭球对其影响越小 \(c_i\):在 s 点处,高斯球的颜色。即通过球谐函数近似得到的颜色

注意,此时是在 2D 平面上计算像素值

当一轮迭代之后,参数都固定了,此时就可以计算像素的颜色值。3D 高斯在投影到 2D 平面上后,还是一个高斯分布。利用之前的理论,当:

\[ {(x-\mu)^T\Sigma^{-1}(x-\mu)}=constant \]

时,在二维上表现为一个椭圆:

\[ \frac{(x-\mu_1)^2}{\sigma_1^2} + \frac{(y-\mu_2)^2}{\sigma_2^2} - \frac{2\sigma_{xy}(x-\mu_1)(y-\mu_2)}{\sigma_1\sigma_2} = constant \]

此时\(\mu_1\)和\(\mu_2\)为高斯中心点在像素平面上的坐标,\(\sigma_1\)和\(\sigma_2\)为二维高斯协方差矩阵对角线上的元素。

高斯椭球的自适应密度控制

  • 这里使用 α 值来调控高斯函数的数量,以防止在优化过程中创建过多的高斯函数。α 值的调整基于一个预定义的阈值,当高斯函数的数量超过这个阈值时,就会使用剔除机制来移除那些贡献较小的高斯函数。(这里可以仔细在源码里找找)
  • 此外,为了处理小规模几何结构的不足重建问题,采用了复制(在重建不足的区域)和分裂(在过度重建的区域)高斯函数的策略。这些操作使得优化过程能够更精细地调整高斯函数的分布,以更精确地匹配场景的几何结构。具体地,这个过程包括以下步骤: 在重建不足的区域,如果小尺度的几何特征没有被足够覆盖,算法会克隆现有的高斯函数,即复制一个相同的高斯函数以增加局部密度,从而更好地捕捉细微的细节。 对于过度重建的区域,如果小尺度的几何被一个大的高斯函数所覆盖,算法会将其分裂为两个较小的高斯函数,这样可以减少单一高斯函数覆盖过多细节的情况,避免模糊和不必要的重叠。
  • 这种自适应的密度控制策略不仅可以增加细节的丰富性,也有助于避免过多的高斯函数对计算资源的消耗。α 值的动态调整和高斯函数的合理分布,使得模型在不同的迭代中逐渐收敛,最终得到一个既紧凑又精确的 3D 场景表示。
  • 优化过程中,通过增加 α 值来提高某些高斯函数的重要性,同时允许采用剔除方法来移除那些低于预设 α 阈值的高斯函数。尽管高斯函数可能会随着优化过程中的调整而增大或缩小,并与其他高斯函数产生重叠,但作者定期进行重建和调整,以确保在视觉空间中保留有重要贡献的高斯函数,同时优化整体的几何表现。
  • 通过这种方法,3D Gaussians 作为欧几里得空间中的基元,在所有时间内都保持一致,与其他方法(如基于投影或扭曲的策略处理大型高斯函数的方法)相比,这种方法避免了复杂的变换,使得渲染过程更加直接和高效。 代码解析

Reference

[0] https://fansaorz.github.io/2024/04/13/3D-Gaussian-Splatting%E8%AF%A6%E8%A7%A3/ [1] https://www.bilibili.com/video/BV1cz421872F