3D Gaussian Splatting代码中的forward和backward两个文件代码解读

3dgs代码前向传播部分

先来讨论一下glm,因为定义变量的时候用到了这个。

glm的解释

glm 是指 OpenGL Mathematics,这是一个针对图形编程的数学库。它的全称是 OpenGL Mathematics (GLM),主要用于 OpenGL 的开发。这个库是基于 C++ 的模板库,设计目标是尽可能提供类似 GLSL(OpenGL 着色语言)的语法和功能,使得在 C++ 中使用数学运算时更加直观和方便。

GLM 提供了各种数学功能和数据结构,包括:

  • 向量(vec2, vec3, vec4)
  • 矩阵(mat2, mat3, mat4)
  • 四元数(quaternion)
  • 常见的数学函数(如平移、旋转、缩放、透视投影等)

在计算机视觉领域,处理几何变换和坐标系转换时,GLM 非常有用。例如,我们需要进行矩阵运算、向量运算等,都可以通过 GLM 提供的功能来方便地实现。使用方法如下所示。

1. 向量

glm::vec3 v1(1.0f, 2.0f, 3.0f);
glm::vec3 v2(4.0f, 5.0f, 6.0f);
glm::vec3 v3 = v1 + v2;  // 向量加法

2. 矩阵

#include <glm/gtc/matrix_transform.hpp>
glm::mat4 identity = glm::mat4(1.0f);  // 单位矩阵
glm::mat4 translation = glm::translate(identity, glm::vec3(10.0f, 0.0f, 0.0f));  // 平移矩阵
glm::mat4 rotation = glm::rotate(identity, glm::radians(45.0f), glm::vec3(0.0f, 1.0f, 0.0f));  // 旋转矩阵

3. 四元数

#include <glm/gtc/quaternion.hpp>
glm::quat q = glm::angleAxis(glm::radians(90.0f), glm::vec3(0.0f, 1.0f, 0.0f));  // 绕 Y 轴

3dgs的代码的forward部分

球谐函数的建立

submodules\diff-gaussian-rasterization\cuda_rasterizer\forward.cu
line 20
// Forward method for converting the input spherical harmonics
// coefficients of each Gaussian to a simple RGB color.
__device__ glm::vec3 computeColorFromSH(int idx, int deg, int max_coeffs, const glm::vec3* means, glm::vec3 campos, const float* shs, bool* clamped)
{
   
    '''
    这个函数基于 Zhang 等人 (2022) 的论文"Differentiable Point-Based Radiance Fields for Efficient View Synthesis" 中的代码实现
    '''
    
    // 获取当前点的中心位置
    glm::vec3 pos = means[idx];
    // 计算从相机位置到当前点的位置向量
    glm::vec3 dir = pos - campos;
    // 将位置向量归一化
    dir = dir / glm::length(dir);

    // 获取当前点的 SH 系数
    glm::vec3* sh = ((glm::vec3*)shs) + idx * max_coeffs;
    // 计算 SH 零阶系数的颜色值
    glm::vec3 result = SH_C0 * sh[0];

    // 如果阶数大于 0,则计算一阶 SH 系数的颜色值
    if (deg > 0)
    {
   
        float x = dir.x;
        float y = dir.y;
        float z = dir.z;
        result = result - SH_C1 * y * sh[1] + SH_C1 * z * sh[2] - SH_C1 * x * sh[3];

        // 如果阶数大于 1,则计算二阶 SH 系数的颜色值
        if (deg > 1)
        {
   
            float xx = x * x, yy = y * y, zz = z * z;
            float xy = x * y, yz = y * z, xz = x * z;
            result = result +
                SH_C2[0] * xy * sh[4] +
                SH_C2[1] * yz * sh[5] +
                SH_C2[2] * (2.0f * zz - xx - yy) * sh[6] +
                SH_C2[3] * xz * sh[7] +
                SH_C2[4] * (xx - yy) * sh[8];

            // 如果阶数大于 2,则计算三阶 SH 系数的颜色值
            if (deg > 2)
            {
   
                result = result +
                    SH_C3[0] * y * (3.0f * xx - yy) * sh[9] +
                    SH_C3[1] * xy * z * sh[10] +
                    SH_C3[2] * y * (4.0f * zz - xx - yy) * sh[11] +
                    SH_C3[3] * z * (2.0f * zz - 3.0f * xx - 3.0f * yy) * sh[12] +
                    SH_C3[4] * x * (4.0f * zz - xx - yy) * sh[13] +
                    SH_C3[5] * z * (xx - yy) * sh[14] +
                    SH_C3[6] * x * (xx - 3.0f * yy) * sh[15];
            }
        }
    }
    // 为结果颜色值加上一个偏移量
    result += 0.5f;

    // 将 RGB 颜色值限制在正值范围内。如果值被限制,则需要在反向传播过程中记录此信息。
    clamped[3 * idx + 0] = (result.x < 0);
    clamped[3 * idx + 1] = (result.y < 0);
    clamped[3 * idx + 2] = (result.z < 0);
    return glm::max(result, 0.0f);
}

EWA投影来消除误差

submodules\diff-gaussian-rasterization\cuda_rasterizer\forward.cu
line 73
// Forward version of 2D covariance matrix computation
// 在 CUDA 设备上定义的函数,用于计算2D协方差矩阵
__device__ float3 computeCov2D(const float3& mean, float focal_x, float focal_y, float tan_fovx, float tan_fovy, const float* cov3D, const float* viewmatrix)
{
   
    // 该函数实现了 "EWA Splatting" (Zwicker et al., 2002) 中的公式2931// 同时考虑了视口的纵横比/缩放。
    // 转置用于处理行/列优先顺序。

    // 将3D点转换到视图坐标系中
    float3 t = transformPoint4x3(mean, viewmatrix);

    // 定义x和y方向的视锥限制
    const float limx = 1.3f * tan_fovx;
    const float limy = 1.3f * tan_fovy;
    const float txtz = t.x / t.z;
    const float tytz = t.y / t.z;
    
    // 限制x和y方向的值,使其不超过视锥限制
    t.x = min(limx, max(-limx, txtz)) * t.z;
    t.y = min(limy, max(-limy, tytz)) * t.z;

    // 计算雅可比矩阵J,表示从3D到2D的投影变换
    glm::mat3 J = glm::mat3(
        focal_x / t.z, 0.0f, -(focal_x * t.x) / (t.z * t.z),
        0.0f, focal_y / t.z, -(focal_y * t.y) / (t.z * t.z),
        0, 0, 0);

    // 提取视图矩阵的前3x3部分,用于线性变换
    glm::mat3 W = glm::mat3(
        viewmatrix[0], viewmatrix[4], viewmatrix[8],
        viewmatrix[1], viewmatrix[5], viewmatrix[9],
        viewmatrix[2], viewmatrix[6], viewmatrix[10]);

    // 计算组合变换矩阵T
    glm::mat3 T = W * J;

    // 从输入的3D协方差矩阵中构建Vrk矩阵
    glm::mat3 Vrk = glm::mat3(
        cov3D[0], cov3D[1], cov3D[2],
        cov3D[1], cov3D[3], cov3D[4],
        cov3D[2], cov3D[4], cov3D[5]);

    // 计算最终的2D协方差矩阵
    glm::mat3 cov = glm::transpose(T) * glm::transpose(Vrk) * T;

    // 应用低通滤波器:每个高斯函数应至少在一个像素宽/// 丢弃第3行和第3列
    cov[0][0] += 0.3f;
    cov[1][1] += 0.3f;

    // 返回2D协方差矩阵的三个元素
    return {
    float(cov[0][0]), float(cov[0][1]), float(cov[1][1]) };
}

EWA Splatting论文中6.2.2节的描述

我们将视图变换与将相机坐标转换为射线坐标的投影变换连接起来,如图8所示。相机空间的定义是相机坐标系的原点在投影中心,投影平面是 t 2 = 1 t_2 = 1 t2=1 的平面。相机空间和射线空间通过映射 x = t \mathbf{x} = \mathbf{t} x=t相关联。使用第4.1节中的射线空间定义, t \mathbf{t} t及其逆映射 t − 1 \mathbf{t}^{-1} t1可以表示为:
( x 0 x 1 x 2 ) = ϕ ( t ) = ( t 0 / t 2 t 1 / t 2 ∣ ∣ ( t 0 , t 1 , t 2 ) T ∣ ∣ ) (26) \begin{pmatrix} x_0 \\ x_1 \\ x_2 \end{pmatrix} =\phi(t)= \begin{pmatrix} t_0/t_2 \\ t_1/t_2 \\ ||(t_0,t_1,t_2)^T|| \end{pmatrix} \tag{26} x0x1x2 =ϕ(t)= t0/t2t1/t2∣∣(t0,t1,t2)T∣∣ (26)

( t 0 t 1 t 2 ) = ϕ − 1 ( x ) = ( x 0 / l ⋅ x 2 x 1 / l ⋅ x 2 1 / l ⋅ x 2 ) (27) \begin{pmatrix} t_0 \\ t_1 \\ t_2 \end{pmatrix} =\phi^{-1}(x)= \begin{pmatrix} x_0/l \cdot x_2 \\ x_1/l \cdot x_2 \\ 1/l \cdot x_2 \end{pmatrix} \tag{27} t0t1t2 =ϕ1(x)= x0/lx2x1/lx21/lx2 (27)

其中, l = ∣ ∣ ( x 0 , x 1 , 1 ) ∣ ∣ T l = ||(x_0, x_1, 1)||^T l=∣∣(x0,x1,1)T

不幸的是,这些映射不是仿射的,因此我们不能直接应用公式(21): G V n ( Φ − 1 ( u ) − p ) = 1 ∣ M − 1 ∣ G M V M T n ( u − Φ ( p ) ) G^n_V(\Phi^{-1}(u)-p)=\frac{1}{|M^{-1}|}G^{n}_{MVM^T}(u-\Phi(p)) GVn(Φ1(u)p)=

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值