3D高斯泼溅算法
在三维重建领域,随着计算机图形学和相关技术的飞速发展,各种创新算法不断涌现,为精准、高效地构建三维场景提供了强大支持。其中,3D高斯泼溅算法(3D Gaussian Splatting,简称3DGS)作为一种新兴的、具有革命性的三维重建技术,正逐渐受到广泛关注。
3D高斯泼溅算法的创新在于其独特的表示和渲染方法。它通过将场景中的每个点视为一个高斯球,利用三维高斯函数的数学性质,将离散的数据点或体素转换为可视化的效果。这一过程中,三维高斯球的叠加不仅实现了数据的平滑过渡,还保留了场景中的细粒度细节。同时,结合快速的可见性感知渲染算法,3D高斯泼溅算法能够在保证高质量渲染效果的同时,实现实时的新视图合成。
对比NeRF和传统的Mesh:一个是纯连续的、隐式表达在可微空间内;一个是纯离散的(虽然可以插值)、显式表达在三维空间内,3D高斯是在离散和连续间的一个平衡:在高斯球内部是连续的、可微的;在整个空间中,每个高斯球又是离散的。
本文将深入探讨3D高斯泼溅算法的基本原理,从其数学基础、实现步骤到应用场景,全面解析这一先进技术的核心优势和技术特点。通过本文的介绍,读者将能够更深入地理解3D高斯泼溅算法的工作原理,并探索其在三维重建、点云渲染、体数据可视化等领域的广泛应用前景。
算法框架
3DGS的主要任务有两个:三维重建和渲染。简单来说,就是提供一组某个场景的照片,然后将这个场景实时渲染出来。算法的主要框架如下图所示。
图1 3D Gaussian Splatting整体框架
由上图可以看出,当拿到一组场景照片以后,我们需要先使用某种SfM(Structure from Motion)算法估计出这一组照片的结构(位置)和姿态(摄像机方向)和一组稀疏点云(SfM Points)。然后交给3DGS进行初始化(Initialization)得到一组初始的3D高斯球(3D Gaussians)。然后,我们借助相机外参(结构和姿态)将这一组3D高斯球投影到相机平面上(Projection),接着再使用可微分块光栅化(Differentiable Tile Rasterizer)渲染得到图像(Image)。得到渲染图像后将其与相机原始的图像(Ground Truth)进行loss比对,然后沿着虚线箭头进行梯度回传。虚线箭头从上回传的时候,更新3D高斯球中的参数,从下回传时会经过自适应密度控制(Adaptive Density Control)的处理,而后更新3D高斯球中的点云。
接下来,我们详细讲解算法中的每一个步骤,并给出具体的实现方式。
算法内容
运动结构恢复
由于该步骤并不是3D Gaussian Splatting的主要内容(详细请见运动结构恢复),而且已经有较成熟的算法和软件可以实现这部分内容(例如COLMAP),因此在此不做过多介绍。
3D高斯椭球集的创建及描述
拿到相机的位置、姿态和稀疏点云后,就可以开始创建初始的3D高斯椭球集。描述一个3D高斯椭球需要四种信息:位置、形状、颜色和不透明度。
3D高斯椭球
在概率论中我们已经学到了多维高斯分布的表达式如下:
\[ f\left(\bm{x}|\bm{\mu},\bm{\Sigma}\right)=\frac{1}{\sqrt{\left(2\pi\right)^3\left|\bm{\Sigma}\right|}}\exp\left(-\frac{1}{2}\left(\bm{x}-\bm{\mu}\right)^{T}\bm{\Sigma}^{-1}\left(\bm{x}-\bm{\mu}\right)\right) \tag{1} \]其中 \(\bm{\mu}\) 是均值, \(\bm{\Sigma}\) 是协方差矩阵,它是对称且正定的。在三维空间中,我们将这么一个三维高斯分布叫做一个3D高斯椭球。
位置
3D高斯椭球的均值 \(\bm{\mu}\) 就是这个3D高斯椭球的位置,也就是其中心点。初始化3D高斯椭球的时候,这个中心点就是由SfM算法得到的稀疏点云。
形状
3D高斯椭球的协方差 \(\bm{\Sigma}\) 就是代表它的形状。由实对称矩阵的正交相似对角化和 \(\bm{\Sigma}\) 的对称性和正定性, \(\bm{\Sigma}\) 可以被分解成 \(\bm{\Sigma}=\bm{R}\bm{\Lambda}\bm{R}^T\) ,其中 \(\bm{R}\) 是一个正交矩阵, \(\bm{\Lambda}\) 是由 \(\bm{\Sigma}\) 的特征值构成的对角矩阵。注意正定矩阵的特征值都是正的,因此 \(\bm{\Lambda}\) 还可以被分解成 \(\bm{\Lambda}=\bm{S}\bm{S}^T\) ,其中 \(\bm{S}\) 也是一个正的对角矩阵,且其对角线上的值其实就是对应的 \(\bm{\Sigma}\) 特征值的平方根。因此有
\[ \bm{\Sigma}=\bm{R}\bm{S}\bm{S}^T\bm{R}^T \tag{2} \] 我们注意看这个式子的几何意义。由于 \(\bm{S}\) 是一个对角矩阵,因此其可以被看成一个放缩变换,而 \(\bm{R}\) 是一个正交矩阵,因此可以看成一个旋转变换(见旋转变换)。将其代回式(1),易得实际上这个操作就是把正交基先拉伸后旋转,再将去均值的随机向量 \(\bm{x}-\bm{\mu}\) 投影到新的正交基上的操作。
对于三维对角矩阵 \(\bm{S}\) ,只需要一个三维向量 \(\bm{s}\) 描述即可,该向量的每个分量对应对角矩阵 \(\bm{S}\) 的每个对角分量。即
对于正交矩阵 \(\bm{R}\) ,可以用一个四元数 \(\bm{q}\) 来表示(见四元数与旋转)。在机器学习中,直接对 \(\bm{\Sigma}\) 进行学习很难保证其正定性。因此,3DGS采用的方法是对 \(\bm{s}\) 和 \(\bm{q}\) 进行学习,再用公式间接计算 \(\bm{\Sigma}\) 。这里,我们先给出四元数到旋转矩阵的计算关系(具体推导见四元数与旋转):
\[ \bm{R}\left(\bm{q}\right)= \begin{pmatrix} 1-2\left(q_2^2+q_3^2\right) & 2\left(q_1q_2-q_0q_3\right) & 2\left(q_1q_3+q_0q_2\right) \\[5pt] 2\left(q_1q_2+q_0q_3\right) & 1-2\left(q_1^2+q_3^2\right) & 2\left(q_2q_3-q_0q_1\right) \\[5pt] 2\left(q_1q_3-q_0q_2\right) & 2\left(q_2q_3+q_0q_1\right) & 1-2\left(q_1^2+q_2^2\right) \end{pmatrix} \tag{4} \]在初始化的时候,3DGS会利用KNN算法计算点云中每个点到与其最近的3个点的平均距离,然后取对数,将其同时作为 \(\bm{s}\) 中的三个分量的值。对于 \(\bm{q}\) ,3DGS将其初始化为 \(\bm{q}=\left(1,0,0,0\right)\) ,也就是不进行旋转。
颜色
对于一个3D高斯球,它的不同方向会呈现不同的颜色,那么这种各向异性的颜色该如何描述呢?这里需要运用到数学中的一个重要的展开工具:实球谐函数(Real Spherical Harmonics)(见球谐函数)。
计算机图形学中常用的实球谐函数的定义如下:
其中
\[ K_l^m=\sqrt{\frac{2l+1}{4\pi}\frac{\left(l-|m|\right)!}{\left(l+|m|\right)!}} \tag{6} \]是归一化系数。 \(P^m_l\left(\cos\theta\right)\) 是连带Legendre多项式(见连带Legendre多项式),定义如下:
\[ P^m_l\left(x\right)=\left(-1\right)^m\frac{\left(1-x^2\right)^{\frac{m}{2}}}{2^ll!}\frac{\mathrm{d}^{l+m}}{\mathrm{d}x^{l+m}}(x^2-1)^l \tag{7} \]类似于Tayler展开和Fourier展开,任何一个在球面上连续的实函数 \(f(\theta,\varphi)\) 可以用 \(Y_{lm}(\theta,\varphi)\) 展开为一平均收敛的级数
\[ f(\theta,\varphi)=\sum_{l=0}^{\infin}\sum_{-l}^{l}C_l^m\mathcal{Y}_l^m(\theta,\varphi) \tag{8} \]其中
\[ C_l^m=\int_0^\pi\int_0^{2\pi}\mathcal{Y}_l^m(\theta,\varphi)f(\theta,\varphi)\sin\theta d\theta d\varphi \tag{9} \] 3DGS算法使用 \(3\) 阶球函数近似,使用RGB颜色来进行渲染。也就是,一共有三个通道,每个通道由区间 \([0,1]\) 的一个数来映射到每个通道表示颜色的 \(0\text{\textasciitilde}255\) 的一个数字。将每个RGB通道展开成一个 \(3\) 阶球函数需要 \((3+1)^2=16\) 个系数。由此可得,要想表示一个3D高斯椭球的颜色信息,需要 \(3\times (3+1)^2=48\) 个参数。
具体的,当我们拿到这 \(48\) 个参数和一个方向向量 \(\bm{n}=(x,y,z)\) 以后,利用式(8),我们可以通过如下推导得到该方向的球谐函数值
\(i\) 取 \(1,2,3\) 表示 \(3\) 个RGB通道, \(C_{00}(i)\text{\textasciitilde}C_{33}(i)\) 均已知,下面给出 \(\mathcal{Y}_{00}(\bm{n})\text{\textasciitilde}\mathcal{Y}_{33}(\bm{n})\) 的表达式(可直接根据式(5)得到)
实球谐函数 | 表达式 | 值 |
---|---|---|
\(\mathcal{Y}_0^0(\bm{n})\) | \(\displaystyle\frac{1}{2}\sqrt{\frac{1}{\pi}}\) | \(0.28209479177387814\) |
\(\mathcal{Y}_1^{-1}(\bm{n})\) | \(-\displaystyle\frac{1}{2}\sqrt{\frac{3}{2\pi}}y\) | \(-0.4886025119029199\times y\) |
\(\mathcal{Y}_1^0(\bm{n})\) | \(\displaystyle\frac{1}{2}\sqrt{\frac{3}{2\pi}}z\) | \(0.4886025119029199\times z\) |
\(\mathcal{Y}_1^1(\bm{n})\) | \(-\displaystyle\frac{1}{2}\sqrt{\frac{3}{2\pi}}x\) | \(-0.4886025119029199\times x\) |
\(\mathcal{Y}_2^{-2}(\bm{n})\) | \(\displaystyle\frac{1}{2}\sqrt{\frac{15}{\pi}}xy\) | \(1.0925484305920792\times xy\) |
\(\mathcal{Y}_2^{-1}(\bm{n})\) | \(-\displaystyle\frac{1}{2}\sqrt{\frac{15}{\pi}}yz\) | \(-1.0925484305920792\times yz\) |
\(\mathcal{Y}_2^0(\bm{n})\) | \(-\displaystyle\frac{1}{4}\sqrt{\frac{5}{\pi}}(3z^2-1)\) | \(0.31539156525252005\times (3z^2-1)\) |
\(\mathcal{Y}_2^1(\bm{n})\) | \(-\displaystyle\frac{1}{2}\sqrt{\frac{15}{\pi}}xz\) | \(-1.0925484305920792\times xz\) |
\(\mathcal{Y}_2^2(\bm{n})\) | \(\displaystyle\frac{1}{4}\sqrt{\frac{15}{\pi}}(x^2-y^2)\) | \(0.5462742152960396\times (x^2-y^2)\) |
\(\mathcal{Y}_3^{-3}(\bm{n})\) | \(-\displaystyle\frac{1}{8}\sqrt{\frac{70}{\pi}}y(3x^2-y^2)\) | \(-0.5900435899266435\times y(3x^2-y^2)\) |
\(\mathcal{Y}_3^{-2}(\bm{n})\) | \(\displaystyle\frac{1}{2}\sqrt{\frac{105}{\pi}}xyz\) | \(2.890611442640554\times xyz\) |
\(\mathcal{Y}_3^{-1}(\bm{n})\) | \(-\displaystyle\frac{1}{8}\sqrt{\frac{42}{\pi}}y(5z^2-1)\) | \(-0.4570457994644658\times y(5z^2-1)\) |
\(\mathcal{Y}_3^0(\bm{n})\) | \(\displaystyle\frac{1}{4}\sqrt{\frac{7}{\pi}}z(5z^2-3)\) | \(0.3731763325901154\times z(5z^2-3)\) |
\(\mathcal{Y}_3^1(\bm{n})\) | \(-\displaystyle\frac{1}{8}\sqrt{\frac{42}{\pi}}x(5z^2-1)\) | \(-0.4570457994644658\times x(5z^2-1)\) |
\(\mathcal{Y}_3^2(\bm{n})\) | \(\displaystyle\frac{1}{4}\sqrt{\frac{105}{\pi}}z(x^2-y^2)\) | \(1.445305721320277\times z(x^2-y^2)\) |
\(\mathcal{Y}_3^3(\bm{n})\) | \(-\displaystyle\frac{1}{8}\sqrt{\frac{70}{\pi}}x(x^2-3y^2)\) | \(-0.5900435899266435\times x(x^2-3y^2)\) |
表1 球谐函数表达式及值
这是在实球谐函数一侧进行合成的方法。但是我们还需要将其换算到RGB通道参数。为了方便合成与分解(减少精度损失)和让展开更对称,3DGS采用如下变换联系实球谐函数和RGB通道参数:
\[ f_i(\bm{n})_{SH}=f_i(\bm{n})_{RGB}-0.5 \tag{11} \]在初始化的时候,3DGS将 \(C_0^0(i)\) 初始化成稀疏点云中的RGB通道值(需要通过上式变换到球谐函数侧),其他参数均初始化为0。
不透明度
除了位置、形状和颜色,每个3D高斯椭球还有一个不透明度参数 \(\omicron\) 。此时对于某个点 \((x,y,z)\) ,其不透明度为:
\[ \alpha(x,y,z)=\omicron\cdot\exp\left(-\frac{1}{2}\left(\bm{x}-\bm{\mu}\right)^{T}\bm{\Sigma}^{-1}\left(\bm{x}-\bm{\mu}\right)\right) \tag{12} \]这个不透明度会在下文渲染部分仔细讲解。初始化的时候,每个3D高斯椭球的透明度均被初始化成 \(0.1\) 。
渲染
得到一组3D高斯椭球集之后,我们需要把他渲染出来。渲染操作的输入是3D高斯椭球集的各个参数和相机参数,输出是相机看到的图片。首先,我们需要将3D高斯椭球集投影到相机对应的2D平面内,然后再采用可微分块光栅化的办法进行渲染。
投影
如何将3D高斯椭球投影到2D平面进行渲染是3DGS中非常重要的关键点。首先我们来证明一个重要的结论:
结论1:多维高斯分布的概率分布函数 \(\displaystyle f\left(\bm{x}|\bm{\mu},\bm{\Sigma}\right)\) ,对仿射变换 \(\bm{u}=\phi(\bm{x})=\bm{M}\bm{x}+\bm{c}\) ,有
由 \(|AB|=|A||B|\) 和 \(|A^T|=|A|\) ,对系数部分有
\[ \begin{aligned} &\frac{1}{\left|\bm{M}^{-1}\right|}\frac{1}{\sqrt{\left(2\pi\right)^3\left|\bm{M}\bm{\Sigma}\bm{M}^T\right|}}\\ =&\frac{1}{\sqrt{\left|\bm{M}^{-1}\right|^2\left(2\pi\right)^3\left|\bm{M}\right|\left|\bm{\Sigma}\right|\left|\bm{M}^T\right|}}\\ =&\frac{1}{\sqrt{\left|\bm{M}^{-1}\right|^2\left(2\pi\right)^3\left|\bm{M}\right|\left|\bm{\Sigma}\right|\left|\bm{M}\right|}}\\ =&\frac{1}{\sqrt{\left(2\pi\right)^3\left|\bm{M}^{-1}\right|\left|\bm{M}\right|\left|\bm{\Sigma}\right|\left|\bm{M}^{-1}\right|\left|\bm{M}\right|}}\\ =&\frac{1}{\sqrt{\left(2\pi\right)^3\left|\bm{M}^{-1}\bm{M}\right|\left|\bm{\Sigma}\right|\left|\bm{M}^{-1}\bm{M}\right|}}\\ =&\frac{1}{\sqrt{\left(2\pi\right)^3\left|\bm{\Sigma}\right|}} \end{aligned} \tag{15} \]由 \((AB)^{-1}=B^{-1}A^{-1}\) 和 \((AB)^T=B^TA^T\) ,对指数部分有
\[ \begin{aligned} &\exp\left(-\frac{1}{2}\left(\left(\bm{M}\bm{x}+\bm{c}\right)-\left(\bm{M}\bm{\mu}+\bm{c}\right)\right)^{T}(\bm{M}\bm{\Sigma}\bm{M}^T)^{-1}\left(\left(\bm{M}\bm{x}+\bm{c}\right)-\left(\bm{M}\bm{\mu}+\bm{c}\right)\right)\right)\\ =&\exp\left(-\frac{1}{2}\left(\bm{M}\left(\bm{x}-\bm{\mu}\right)\right)^{T}\left(\bm{M}^T\right)^{-1}\bm{\Sigma}^{-1}\bm{M}^{-1}\bm{M}\left(\bm{x}-\bm{\mu}\right)\right)\\ =&\exp\left(-\frac{1}{2}\left(\bm{x}-\bm{\mu}\right)^T\bm{M}^T\left(\bm{M}^T\right)^{-1}\bm{\Sigma}^{-1}\bm{M}^{-1}\bm{M}\left(\bm{x}-\bm{\mu}\right)\right)\\ =&\exp\left(-\frac{1}{2}\left(\bm{x}-\bm{\mu}\right)^T\bm{\Sigma}^{-1}\left(\bm{x}-\bm{\mu}\right)\right)\\ \end{aligned} \tag{16} \]综上可得
\[ \frac{1}{\left|\bm{M}^{-1}\right|}f\left(\bm{u}|\phi(\bm{\mu}),\bm{M}\bm{\Sigma}\bm{M}^T\right)=\frac{1}{\sqrt{\left(2\pi\right)^3\left|\bm{\Sigma}\right|}}\exp\left(-\frac{1}{2}\left(\bm{x}-\bm{\mu}\right)^T\bm{\Sigma}^{-1}\left(\bm{x}-\bm{\mu}\right)\right)=f\left(\bm{x}|\bm{\mu},\bm{\Sigma}\right) \tag{17} \]证毕。
我们先将3D高斯椭球从世界坐标系下变换到相机坐标系下(只是平移和旋转)。这个变换可以写为
\[ \bm{x}^{\prime\prime}=\phi^{\prime\prime}(\bm{x})=\bm{W}\bm{x}+\bm{b} \tag{18} \]其中 \(\bm{W}\) 和 \(\bm{b}\) 可以由相机坐标系的旋转矩阵 \(\bm{R}\) 和位置坐标 \(\bm{t}\) 得来。
\[ \bm{W}=\bm{R}^T\\[5pt] \bm{b}=-\bm{R}^T\bm{t} \tag{19} \]使用结论1,我们可以得到经过该变换后的期望值 \(\bm{\mu}^{\prime\prime}\) 协方差矩阵 \(\bm{\Sigma}^{\prime\prime}\)
\[ \bm{\mu}^{\prime\prime}=\phi(\bm{\mu})\\[5pt] \bm{\Sigma}^{\prime\prime}=\bm{W}\bm{\Sigma}\bm{W}^T \tag{20} \]然后,在相机坐标系下,我们需要使用一个透视变换将其变换到图像坐标系(见透视变换)。注意3DGS使用了和UnrealEngine相同的左手坐标系。
\[ \bm{M}= \begin{pmatrix} \displaystyle\frac{2z_{near}}{x_{right}-x_{left}} & 0 & \displaystyle\frac{x_{right}+x_{left}}{x_{right}-x_{left}} & 0 \\[20pt] 0 & \displaystyle\frac{2z_{near}}{y_{top}-y_{bottom}} & \displaystyle\frac{y_{top}+y_{bottom}}{y_{top}-y_{bottom}} & 0\\[20pt] 0 & 0 & \displaystyle\frac{z_{far}}{z_{far}-z_{near}} & \displaystyle-\frac{z_{far}z_{near}}{z_{far}-z_{near}}\\[20pt] 0 & 0 & 1 & 0 \end{pmatrix} \tag{21} \]该矩阵是在齐次坐标下的变换矩阵,所以是4维的。其中, \(z_{near}\) 是近平面, \(z_{far}\) 是远平面, \(y_{top},y_{bottom},x_{left},x_{right}\) 分别是相机取景框的上下左右边框。可以将其用 \(x,y\) 轴的视场角表示
\[ \begin{aligned} &x_{right}=z_{near}\tan\left(\frac{fov_x}{2}\right)\\[5pt] &x_{left}=-x_{right}\\[5pt] &y_{top}=z_{near}\tan\left(\frac{fov_y}{2}\right)\\[5pt] &y_{bottom}=-y_{top} \end{aligned} \tag{22} \]透视变换的三维形式不是仿射变换,但我们可以尝试写出它。对于 \(\bm{P}^{\prime\prime}=(x^{\prime\prime},y^{\prime\prime},z^{\prime\prime},1)^T\) ,由 \(\bm{P}^{\prime}=\bm{M}\bm{P}^{\prime\prime}\) 得
\[ \bm{P}^{\prime}= \begin{pmatrix} \displaystyle\frac{2z_{near}}{x_{right}-x_{left}}x^{\prime\prime}+\displaystyle\frac{x_{right}+x_{left}}{x_{right}-x_{left}}z^{\prime\prime}\\[20pt] \displaystyle\frac{2z_{near}}{y_{top}-y_{bottom}}y^{\prime\prime}+\displaystyle\frac{y_{top}+y_{bottom}}{y_{top}-y_{bottom}}z^{\prime\prime}\\[20pt] \displaystyle\frac{z_{far}}{z_{far}-z_{near}}z^{\prime\prime}\displaystyle-\frac{z_{far}z_{near}}{z_{far}-z_{near}}\\[20pt] z^{\prime\prime} \end{pmatrix} \tag{23} \]将其齐次化后可得
\[ \begin{aligned} x^{\prime}=&\displaystyle\frac{2z_{near}}{x_{right}-x_{left}}\frac{x^{\prime\prime}}{z^{\prime\prime}}+\displaystyle\frac{x_{right}+x_{left}}{x_{right}-x_{left}}\\[20pt] y^{\prime}=&\displaystyle\frac{2z_{near}}{y_{top}-y_{bottom}}\frac{y^{\prime\prime}}{z^{\prime\prime}}+\displaystyle\frac{y_{top}+y_{bottom}}{y_{top}-y_{bottom}}\\[20pt] z^{\prime}=&\displaystyle\frac{z_{far}}{z_{far}-z_{near}}-\displaystyle\frac{z_{far}z_{near}}{z_{far}-z_{near}}\frac{1}{z^{\prime\prime}} \end{aligned} \tag{24} \]这不是一个仿射变换。但是,考虑到3D高斯椭球都很小,我们可以将右端的式子在 \(\bm{\mu}^{\prime\prime}=\phi(\bm{\mu})\) 处展开。由多元函数展开
\[ \begin{pmatrix} x^{\prime}\\ y^{\prime}\\ z^{\prime} \end{pmatrix} =\bm{\mu}^{\prime\prime}+\bm{J}(\bm{\mu}^{\prime\prime}) \begin{pmatrix} x^{\prime\prime}\\ y^{\prime\prime}\\ z^{\prime\prime} \end{pmatrix} \tag{25} \]其中 \(\bm{J}(\bm{\mu}^{\prime\prime})\) 是上述变换的Jacobi矩阵。具体来说对式(24)
\[ \begin{aligned} \bm{J}(\bm{\mu}^{\prime\prime})=& \left. \begin{pmatrix} \displaystyle\frac{\partial x^{\prime}}{\partial x^{\prime\prime}} & \displaystyle\frac{\partial x^{\prime}}{\partial y^{\prime\prime}} & \displaystyle\frac{\partial x^{\prime}}{\partial z^{\prime\prime}}\\[10pt] \displaystyle\frac{\partial y^{\prime}}{\partial x^{\prime\prime}} & \displaystyle\frac{\partial y^{\prime}}{\partial y^{\prime\prime}} & \displaystyle\frac{\partial y^{\prime}}{\partial z^{\prime\prime}}\\[10pt] \displaystyle\frac{\partial z^{\prime}}{\partial x^{\prime\prime}} & \displaystyle\frac{\partial z^{\prime}}{\partial y^{\prime\prime}} & \displaystyle\frac{\partial z^{\prime}}{\partial z^{\prime\prime}}\\[10pt] \end{pmatrix} \right._{\bm{x}^{\prime\prime}=\bm{\mu}^{\prime\prime}} \\[50pt] =& \begin{pmatrix} \displaystyle\frac{2z_{near}}{x_{right}-x_{left}}\frac{1}{\mu_z^{\prime\prime}} & \displaystyle-\frac{2z_{near}}{x_{right}-x_{left}}\frac{\mu_x^{\prime\prime}}{\left(\mu_z^{\prime\prime}\right)^2} & 0\\[20pt] 0 & \displaystyle\frac{2z_{near}}{y_{top}-y_{bottom}}\frac{1}{\mu_z^{\prime\prime}} & \displaystyle-\frac{2z_{near}}{y_{top}-y_{bottom}}\frac{\mu_y^{\prime\prime}}{\left(\mu_z^{\prime\prime}\right)^2}\\[20pt] 0 & 0 & \displaystyle\frac{z_{far}z_{near}}{z_{far}-z_{near}}\frac{1}{\left(\mu_z^{\prime\prime}\right)^2} \end{pmatrix} \end{aligned} \tag{26} \]这样就可以把透视变换近似为一个仿射变换。因此可以使用结论1
\[ \bm{\Sigma}^{\prime}=\bm{J}\bm{\Sigma}^{\prime\prime}\bm{J}^T \tag{27} \] \[ \bm{\Sigma}^{\prime}==\bm{J}\bm{W}\bm{\Sigma}\bm{W}^T\bm{J}^T \tag{28} \]\(\bm{\mu}\) 按照点坐标规则变换就行。这样我们就将3D高斯椭球变换到了图像坐标系内。但是,在3DGS算法中, \(\bm{\Sigma}^{\prime}\) 实际上是 \(2\times 2\) 的2D形式,也就是忽略 \(z\) 坐标而直接投影到了 \(xy\) 平面。这也很简单,把式(28)中的 \(\bm{J}\) 的第三行去掉,变成 \(2 \times 3\) 的矩阵,此时容易验证结论1仍然适用。此时得到的 \(\bm{\Sigma}^{\prime}\) 就是投影到 \(xy\) 平面上的2D矩阵了。
着色
3DGS采用的是Alpha-Blending和体渲染光线行进着色算法。假设我们让视图平面某个点 \((x,y)\) 对N个高斯进行采样,那么该点的颜色为
\[ C(x,y)=\sum_{i=1}^{N}c_i(x,y)\alpha_i(x,y)\prod_{j=1}^{i-1}(1-\alpha_j(x,y)) \tag{29} \]这N个高斯按照世界坐标系下与 \((x,y)\) 的距离(深度)由近到远的顺序排序。 \(c_i(x^{\prime},y^{\prime})\) 是第 \(i\) 个高斯在 \((x^{\prime},y^{\prime})\) 处的颜色(在世界坐标系下用式(10)和式(11)求出)。 \(\alpha_i(x^{\prime},y^{\prime})\) 是第 \(i\) 个高斯在 \((x^{\prime},y^{\prime})\) 处的不透明度,在二维平面中式(12)也适用,因此有
\[ \alpha_i(x^{\prime},y^{\prime})=\omicron_i\cdot\exp\left(-\frac{1}{2}\left(\bm{x}^{\prime}-\bm{\mu}^{\prime}\right)^{T}\left(\bm{\Sigma}^{\prime}\right)^{-1}\left(\bm{x}^{\prime}-\bm{\mu}^{\prime}\right)\right) \tag{30} \]\(\omicron_i\) 就是由不透明度定义的第 \(i\) 个3D高斯椭球的不透明度。注意,式(29)中的 \(C(x,y)\) 是三个RGB通道各自的颜色值,取值范围为 \([0,1]\) 。也就是三个RGB通道各自独立混合后,再一起作为 \((x,y)\) 点处的颜色。
分块
如果对于每个像素,相对所有高斯(2D)都进行一次光线行进,那这将耗费巨大的计算资源而且还不一定能起到很好的效果。因此,3DGS提出了一种分块渲染的方法。其思想是将屏幕分成每个大小为 \(16\times 16\) 像素的块,在渲染每个块中的像素的时候只考虑和这个块有交叠的高斯。对于不同的块,可以采用并行计算的方法加快渲染速度。
那么该如何判断某个高斯与某个块是否有交叠呢?首先得确定它的边界。3DGS采用 \(99\\%\) 作为置信区间,也就是以概率为 \(99\\%\) 作为边界。即
由于 \(\bm{\Sigma}^\prime\) 是正定矩阵,因此这是一个椭圆。椭圆方程可以被求出来,再结合某个块的四条边的参数,就可以判断出是否交叠。(当然,在实际代码中并没有采用上述椭圆方程的求法,也没有采用传统的椭圆和矩形的碰撞检测算法,因为这样会增加不必要的计算量,因此在3DGS的代码实现中将2D高斯的碰撞箱简化为了一个矩形,再用这个矩形做碰撞判断,具体见代码)。
我们先对所有高斯做一个预处理。对于我们需要处理的高斯,首先,这个高斯必须位于相机的视锥内部(或与其相交),这样可以预先排除掉很大一部分高斯。然后,这个高斯不能距离摄像机过近或过远(一般来说,会将 \(z^\prime\) 控制在某一个区间内)。最后再执行判断这个高斯与某个块是否有交叠的操作。
接下来的问题是如何得到与某个块有交叠的所有高斯,并按照深度进行排序方便进行着色。