3D Gaussian Splatting 学习笔记(二) | 路人乙の小窝
0%

3D Gaussian Splatting 学习笔记(二)

前言

尝试精读了3dgs的论文原文,本文可以看做一个阅读笔记或者总结


论文基本信息

项目 详情
标题 3D Gaussian Splatting for Real-Time Radiance Field Rendering
作者 Bernhard Kerbl, Georgios Kopanas, Thomas Leimkühler, George Drettakis
单位 Inria, Université Côte d’Azur
arXiv 2308.04079
代码 graphdeco-inria/gaussian-splatting

研究背景和动机

本文提出了3DGS的方法,实现了在更短的训练时间内,达到SOTA的视觉效果及1080P高质量实时新视角重建。

在本文之前:

  • NeRF方法每条射线需要采样几十上百个点,而每个点需要跑一次MLP,渲染一张图需要进行成千上万次的网络前向传播;
  • 隐式表示紧凑但查询慢,显示表示查询快但质量差或占内存大,都无法实现实时渲染;

核心方法

3DGS的核心有三点:

  1. 使用3D Gaussian作为场景基元,代替原有的表示方法;
  2. 自适应密度控制;
  3. 使用可微分的渲染器(可微 tile-based 光栅化);

使用3D Gaussian作为场景基元

3D Gaussian相较三角形、体素、点云等场景基元,有着连续、可微、不依赖拓扑结构的优秀性质;相较MLP的隐式表示方法,它不需要进行ray marching,渲染速度快。

连续可微:

3d高斯是连续可微的,公式如下:

$$G(x) = \exp\Big(-\frac{1}{2}(x-\mu)^T \Sigma^{-1}(x-\mu)\Big)$$

其中,exp是指数函数,其内部是一个二次多项式,因此复合的结果处处无线可微。

对比三角形,三角形的分片是连续的。可是在边界处,由于”像素在三角形内”的判断结果是离散值,因此函数值会发生跳变,因此三角形不可微;

点云是离散的,且完全不可微;

体素本身是离散的。但使用三线性插值等方法可以将函数变为连续的分片线性函数,但在边界处存在跳变

各向异性协方差

  • 协方差矩阵 (\Sigma = RSS^TR^T) 的分解方式(R 是旋转,S 是缩放)
  • 为什么分解成 R 和 S?(保证半正定性、参数量可控)
  • 与各向同性(isotropic)高斯对比的优缺点

协方差矩阵只有当半正定时才是有意义的。将协方差矩阵进行分解:

$$\Sigma = RSS^TR^T$$

其中R为旋转矩阵、S为缩放矩阵。通过协方差矩阵的几何意义,可以得知这个分解是可行的,且这几个矩阵相乘的积总是正定的。

同时,旋转矩阵可以用四元数表示,缩放矩阵只需要维护三个方向的缩放系数,因此在这种分解方式下,只需要记录7个值就可以表示协方差矩阵,参数少,优化速度快,且总是满足其正定性。

与各向同性高斯对比:各向同性高斯不需要记录旋转信息,需要的参数量更小;可是各向同性高斯的形状是一个简单的球,难以近似现实中的物体,比如对于一个平面,需要密密麻麻的小球才能够近似表示。

$\Sigma$ 和高斯公式推出的一些性质

对 $G(x) = \exp\Big(-\frac{1}{2}(x-\mu)^T \Sigma^{-1}(x-\mu)\Big)$ 求等值面,可以得到一个高斯椭球。经过一系列的化简和坐标变换,可以得到一个标准椭球公式:
$$\frac{y_1^2}{r^2\lambda_1} + \frac{y_2^2}{r^2\lambda_2} + \frac{y_3^2}{r^2\lambda_3} = 1$$
其中 $y = Q^T(x-\mu)$
所以 $\mu$ 决定椭球的中心,$Q$ 决定椭球旋转方向,$\lambda$ 决定了每个方向上的尺度。
椭球半轴轴长为 $r\sqrt{\lambda_1}, r\sqrt{\lambda_2}, r\sqrt{\lambda_3}$

当 $\Sigma$ 有负特征值,G(x)在某些方向上函数值是发散的,对应的等值面也可能变成不闭合的双曲面;当 $\Sigma$ 有特征值为 0 ,其是不可逆的,公式不再成立。因此 $\Sigma$ 要求是正定的。

投影到二维

  • 投影近似(affine approximation of perspective projection)的基本思路
  • 为什么要近似?精确投影的高斯不再是高斯

精确的透视投影是一个非线性的变换,在经过这个变换之后,原本的高斯椭球不会变成一个标准的二维高斯。

通过在高斯中心附近做线性变换,用雅可比矩阵去近似透视投影,最终得到的是 2D 椭圆高斯。

每个高斯的属性总结

属性 符号 维度 作用
中心位置 (\mu) 3 决定高斯椭球最终的中心位置
协方差矩阵 (\Sigma) 3×3 → 分解为 R(4) + S(3) 决定高斯椭球的方向、形状、大小
不透明度 (\alpha) 1 决定某个高斯对最终颜色的贡献权重
球谐系数 SH coeff 48(3 阶 SH × RGB) 编码视角相关的颜色

自适应密度控制

  • 增加高斯:3DGS由sfm稀疏点云初始化高斯。后面训练时,算法会去统计每个高斯在视图空间中的位置梯度,如果这个梯度很大,说明这个结果对这个高斯的变化很敏感,所以会将这个高斯clone或split。
  • 减少高斯:算法会剔除掉几乎透明的高斯。同时,每经过一定次数的迭代,算法会将alpha重置为很小的值,重新审视每个高斯到底有没有贡献。

为什么要动态调整高斯数量?

  • 初始 SfM 点云是不完整的(遮挡区域没有点、弱纹理区域点稀疏)
  • 固定的高斯集合无法覆盖所有细节

两种增加策略:Clone 与 Split

当某个高斯在视图空间的位置梯度过大,说明需要进行clone或split:

  • Clone:高斯过小时触发?复制并沿梯度方向移动
  • Split:高斯过大时触发?拆成两个小一号的高斯
  • 两者的阈值设置:梯度阈值 $\tau_{\text{pos}}=0.0002$,尺寸阈值0.01(1%)

split实际是将高斯替换成两个尺寸除以1.6的小高斯。1.6是实验出来的经验值

与训练交替执行

密度控制每隔一定迭代次数(论文设定为从第 500 次迭代开始,每 100 次执行一次)与训练交替进行。训练初期高斯数量少,迭代很快;随着 Clone 和 Split 不断触发,高斯数量从初始的几万暴涨到几百万,每轮迭代的计算量显著增加——这与我实际训练时的观察一致(见笔记一中的训练日志)。


下一步

本文只覆盖了论文的三个核心部分中的两个——场景基元表示和自适应密度控制。第三个核心”可微 Tile-based 光栅化”是实现实时渲染的关键引擎,涉及逐 tile 排序、alpha blending 和 CUDA 反向传播等工程细节,计划在后续笔记中单独展开。训练流程(初始化策略、L1 + D-SSIM 损失函数等)也留到后面结合代码一并分析。

我很可爱,请给我钱qwq