3DGS三维高斯泼溅技术原理深度解析
目录
- 概述
- 数学基础
- 核心算法原理
- [可微光栅化(Differentiable Rasterization)](#可微光栅化(Differentiable Rasterization))
- [自适应密度控制(Adaptive Density Control)](#自适应密度控制(Adaptive Density Control))
- 优化策略
- 训练流程详解
- 渲染算法
- 关键技术细节
- 性能优化技术
- 与相关技术对比
- [3DGS vs NeRF](#3DGS vs NeRF)
- [3DGS vs 传统点云](#3DGS vs 传统点云)
- [3DGS vs 体素表示](#3DGS vs 体素表示)
- 技术演进与变体
- 实际应用分析
- 总结与展望
概述
3D Gaussian Splatting(3DGS,三维高斯泼溅)是2023年由Inria、Max Planck Institute和TU Darmstadt联合提出的一种革命性的3D场景表示方法。它使用显式的3D高斯点云来表示场景,通过可微光栅化实现高效训练和实时渲染。
核心创新
3DGS的核心创新:
┌─────────────────────────────────────────────┐
│ 1. 显式表示 │
│ - 3D高斯点云(可编辑、可裁剪) │
│ - 相比NeRF的隐式表示更直观 │
└─────────────────────────────────────────────┘
↓
┌─────────────────────────────────────────────┐
│ 2. 可微光栅化 │
│ - 支持梯度反向传播 │
│ - 实现端到端训练 │
└─────────────────────────────────────────────┘
↓
┌─────────────────────────────────────────────┐
│ 3. 自适应密度控制 │
│ - 动态调整高斯点分布 │
│ - 细节区域更多点,平滑区域更少点 │
└─────────────────────────────────────────────┘
↓
┌─────────────────────────────────────────────┐
│ 4. 实时渲染 │
│ - GPU加速光栅化 │
│ - 支持交互式查看 │
└─────────────────────────────────────────────┘
技术特点
| 特性 | 说明 | 优势 |
|---|---|---|
| 显式表示 | 3D高斯点云 | 可编辑、可裁剪、可压缩 |
| 训练速度 | 数十分钟 | 比NeRF快10-100倍 |
| 渲染速度 | 实时(30-60fps) | 支持交互式应用 |
| 质量 | 高保真度 | PSNR 28-32 dB |
| 可扩展性 | 支持大场景 | 通过空间数据结构优化 |
应用领域
- 新视角合成(Novel View Synthesis):从多视角照片生成任意视角
- 场景重建:室内外场景的3D重建
- 虚拟现实:VR/AR场景构建
- 内容创作:游戏、电影、设计
- 科研应用:机器人仿真、科学可视化
数学基础
3D高斯函数
基本定义
3D高斯函数是3DGS的核心数学工具,用于表示3D空间中的概率分布。其数学表达式为:
G(x) = (1 / √((2π)³|Σ|)) × exp(-0.5 × (x-μ)ᵀ Σ⁻¹ (x-μ))
简化形式(忽略归一化常数):
G(x) = exp(-0.5 × (x-μ)ᵀ Σ⁻¹ (x-μ))
参数说明:
- x:3D空间中的任意点,x = (x, y, z)ᵀ
- μ:高斯中心位置,μ = (μₓ, μᵧ, μᵧ)ᵀ
- Σ:3×3协方差矩阵,控制椭球的形状和方向
- Σ⁻¹:协方差矩阵的逆矩阵
几何意义
3D高斯函数的几何表示:
┌─────────────────────────────────────────────┐
│ 在3D空间中,高斯函数形成一个椭球体: │
│ │
│ ┌─────┐ │
│ ╱ ╲ ╱ │
│ │ μ │ ← 椭球中心(高斯中心) │
│ ╲ ╱ ╲ │
│ └─────┘ │
│ │
│ 椭球的形状由Σ决定: │
│ - 主轴方向:特征向量方向 │
│ - 主轴长度:特征值的平方根 │
└─────────────────────────────────────────────┘
2D投影
当3D高斯投影到2D图像平面时,仍然是一个2D高斯函数:
2D投影过程:
┌─────────────────────────────────────────────┐
│ 3D高斯 G₃(x, y, z) │
│ ↓ 投影变换 │
│ 2D高斯 G₂(u, v) │
│ │
│ 投影后的2D高斯: │
│ G₂(u, v) = exp(-0.5 × [u-μᵤ, v-μᵥ] Σ₂⁻¹ [u-μᵤ, v-μᵥ]ᵀ) │
└─────────────────────────────────────────────┘
投影数学推导:
给定投影矩阵P(包含相机内参和外参),3D点投影到2D:
[u, v, w]ᵀ = P × [x, y, z, 1]ᵀ
u' = u/w, v' = v/w
3D协方差到2D协方差的转换:
Σ₂ = J × Σ₃ × Jᵀ
其中J是投影的雅可比矩阵:
J = ∂(u', v')/∂(x, y, z)
详细计算:
对于透视投影:
J = [
[fₓ/Z, 0, -fₓ×X/Z²],
[0, fᵧ/Z, -fᵧ×Y/Z²]
]
其中:
- fₓ, fᵧ:焦距
- X, Y, Z:3D点坐标
- Z:深度值
高斯函数的可视化
1D高斯函数:
╱╲
╱ ╲
╱ ╲
╱ ╲
╱ ╲
╱ ╲
╱ ╲
2D高斯函数(俯视图):
●
╱│╲
╱ │ ╲
╱ │ ╲
╱ │ ╲
╱ │ ╲
╱ │ ╲
3D高斯函数(椭球):
╱╲
╱ ╲
╱ ╲
╱ ● ╲ ← 中心
╲ ╱
╲ ╱
╲╱
协方差矩阵与椭球表示
协方差矩阵
协方差矩阵Σ是一个3×3的对称正定矩阵:
┌─────────────────┐
│ σₓₓ σₓᵧ σₓᵧ │
Σ = │ σᵧₓ σᵧᵧ σᵧᵧ │
│ σᵧₓ σᵧᵧ σᵧᵧ │
└─────────────────┘
性质:
- 对称性:σᵢⱼ = σⱼᵢ
- 正定性:所有特征值 > 0
- 行列式:|Σ| > 0
椭球参数化
为了便于优化,3DGS使用缩放-旋转分解来表示协方差矩阵:
Σ = R × S × Sᵀ × Rᵀ
其中:
-
S :对角缩放矩阵
S = diag(sₓ, sᵧ, sᵧ) -
R:旋转矩阵(由四元数q计算)
四元数表示旋转:
q = (q₀, q₁, q₂, q₃) // 单位四元数,|q| = 1
旋转矩阵计算:
R = 旋转矩阵(q)
优势:
- 参数更少:7个参数(3个缩放 + 4个四元数)vs 6个独立参数
- 约束更自然:缩放 > 0,四元数归一化
- 优化更稳定
椭球可视化
椭球形状示例:
┌─────────────────────────────────────────────┐
│ 球形(sₓ = sᵧ = sᵧ): │
│ ○ │
│ │
│ 椭球形(sₓ ≠ sᵧ = sᵧ): │
│ ╱╲ │
│ ╱ ╲ │
│ │
│ 任意方向椭球(旋转 + 缩放): │
│ ╱╲ │
│ ╱ ╲ │
│ ╱ ╲ │
└─────────────────────────────────────────────┘
球谐函数基础
什么是球谐函数
球谐函数(Spherical Harmonics, SH)是一组定义在球面上的正交基函数,用于表示方向相关的函数。
数学定义
球谐函数:
Yₗᵐ(θ, φ) = Nₗᵐ × Pₗ|ᵐ|(cos θ) × e^(imφ)
其中:
- l:阶数(degree),l ≥ 0
- m:次数(order),-l ≤ m ≤ l
- θ, φ:球面坐标(极角和方位角)
- Pₗᵐ:关联勒让德多项式
- Nₗᵐ:归一化常数
在3DGS中的应用
颜色表示:
颜色(θ, φ) = Σₗ₌₀ᴸ Σₘ₌₋ₗˡ cₗᵐ × Yₗᵐ(θ, φ)
其中:
- L:最大阶数(通常L=3,即3阶SH)
- cₗᵐ:SH系数(RGB三个通道各一套)
- θ, φ:视角方向
实际计算:
对于3阶SH(L=3),颜色计算为:
C(θ, φ) = c₀⁰ × Y₀⁰(θ, φ) + // DC项(基础颜色)
c₁⁻¹ × Y₁⁻¹(θ, φ) + c₁⁰ × Y₁⁰(θ, φ) + c₁¹ × Y₁¹(θ, φ) + // 1阶
c₂⁻² × Y₂⁻²(θ, φ) + ... + c₂² × Y₂²(θ, φ) + // 2阶
c₃⁻³ × Y₃⁻³(θ, φ) + ... + c₃³ × Y₃³(θ, φ) // 3阶
视角变化示例:
视角方向变化对颜色的影响:
┌─────────────────────────────────────────────┐
│ 视角1(正面): │
│ C₁ = SH(θ₁, φ₁) = c₀⁰ + 其他项 │
│ │
│ 视角2(侧面): │
│ C₂ = SH(θ₂, φ₂) = c₀⁰ + 其他项 │
│ (其他项的值不同,导致颜色变化) │
│ │
│ 视角3(背面): │
│ C₃ = SH(θ₃, φ₃) = c₀⁰ + 其他项 │
└─────────────────────────────────────────────┘
SH系数数量
| 阶数L | 系数数量 | 说明 |
|---|---|---|
| 0 | 1 | 固定颜色(DC项) |
| 1 | 4 | 基础方向变化 |
| 2 | 9 | 中等复杂度 |
| 3 | 16 | 常用配置 |
| 4 | 25 | 高复杂度 |
| 5 | 36 | 极高复杂度 |
3阶SH(常用):
- 总系数:1 + 3 + 5 + 7 = 16个
- RGB三通道:16 × 3 = 48个系数
- 存储:48 × 4 bytes = 192 bytes
SH的优势
固定RGB vs 球谐函数:
┌─────────────────────────────────────────────┐
│ 固定RGB: │
│ - 颜色不随视角变化 │
│ - 存储:3 × 4 = 12 bytes │
│ - 适用:Lambertian表面 │
└─────────────────────────────────────────────┘
↓
┌─────────────────────────────────────────────┐
│ 球谐函数(3阶): │
│ - 颜色随视角变化 │
│ - 存储:48 × 4 = 192 bytes │
│ - 适用:有光照变化的表面 │
│ - 可以表示: │
│ * 镜面反射 │
│ * 环境光照 │
│ * 视角相关效果 │
└─────────────────────────────────────────────┘
核心算法原理
可微光栅化(Differentiable Rasterization)
传统光栅化 vs 可微光栅化
传统光栅化:
3D几何 → 2D投影 → 像素值
(不可微,无法反向传播)
可微光栅化:
3D高斯 → 2D投影 → 像素值
(可微,支持梯度计算)
投影变换
3D到2D的投影:
给定相机参数(内参K和外参[R|t]),3D点投影到2D:
[u, v, 1]ᵀ = K × [R|t] × [x, y, z, 1]ᵀ
详细投影过程:
步骤1:世界坐标 → 相机坐标
┌─────────────────────────────────────────────┐
│ [X_c, Y_c, Z_c, 1]ᵀ = [R|t] × [X_w, Y_w, Z_w, 1]ᵀ │
└─────────────────────────────────────────────┘
↓
步骤2:相机坐标 → 图像坐标
┌─────────────────────────────────────────────┐
│ [u, v, w]ᵀ = K × [X_c, Y_c, Z_c]ᵀ │
│ u' = u/w, v' = v/w │
└─────────────────────────────────────────────┘
3D高斯投影到2D高斯:
3D协方差矩阵 Σ₃ → 2D协方差矩阵 Σ₂
Σ₂ = J × Σ₃ × Jᵀ
其中J是投影的雅可比矩阵:
J = ∂(u', v') / ∂(x, y, z)
雅可比矩阵计算:
对于透视投影相机模型:
J = [
[fₓ/Z, 0, -fₓ×X/Z²],
[0, fᵧ/Z, -fᵧ×Y/Z²]
]
其中:
- fₓ, fᵧ:焦距(像素单位)
- X, Y, Z:相机坐标系中的3D点
- Z:深度值
投影可视化:
3D空间中的高斯椭球:
╱╲
╱ ╲
╱ ╲
╱ ● ╲
╲ ╱
╲ ╱
╲╱
↓ 投影到图像平面
2D图像中的高斯椭圆:
╱╲
╱ ╲
╱ ● ╲
╲ ╱
╲╱
深度排序
目的:确定渲染顺序(从前到后)
方法:
- 计算每个高斯点到相机的深度
- 按深度值排序
- 从前到后渲染
深度计算:
depth = (R × [x, y, z]ᵀ + t) · [0, 0, 1]ᵀ
Alpha混合
原理:按深度顺序混合颜色
公式:
C = Σᵢ (αᵢ × cᵢ × ∏ⱼ<ᵢ(1 - αⱼ))
其中:
- C:最终像素颜色
- αᵢ:第i个高斯点的不透明度
- cᵢ:第i个高斯点的颜色
- ∏ⱼ<ᵢ(1 - αⱼ):前面所有点的透明度累积
可视化:
Alpha混合过程:
┌─────────────────────────────────────────────┐
│ 像素位置 │
│ │
│ 背景色 │
│ ↓ │
│ α₁ × c₁ × (1-0) │
│ ↓ │
│ α₂ × c₂ × (1-α₁) │
│ ↓ │
│ α₃ × c₃ × (1-α₁)(1-α₂) │
│ ↓ │
│ 最终颜色 C │
└─────────────────────────────────────────────┘
可微性保证
关键技巧:
- 软排序:使用可微的排序方法
- 软Alpha:使用sigmoid等可微函数
- 近似方法:在保持可微性的同时近似传统光栅化
自适应密度控制(Adaptive Density Control)
问题背景
挑战:
- 初始点云可能稀疏或不均匀
- 需要在高细节区域增加点
- 需要在平滑区域减少点
- 需要控制总点数
三种操作
1. 克隆(Clone)
触发条件:
- 梯度大:|∇L| > threshold
- 不透明度高:α > threshold
操作:
原高斯点 G(μ, Σ, α, c)
↓
克隆为两个点:
G₁(μ + ε, Σ, α, c) // 稍微偏移
G₂(μ - ε, Σ, α, c) // 稍微偏移
目的:在细节区域增加高斯点
可视化:
克隆前: 克隆后:
● ●
╱ ╲
● ●
2. 分割(Split)
触发条件:
- 高斯点过大:|Σ| > threshold
- 或梯度大且尺度大
操作:
大高斯点 G(μ, Σ, α, c)
↓
分割为两个小点:
G₁(μ, Σ/2, α, c)
G₂(μ, Σ/2, α, c)
目的:将大高斯点分割成小点,提高细节
可视化:
分割前: 分割后:
╱╲ ╱╲
╱ ╲ ╱ ╲
╱ ╲ ╱ ╲
3. 剪枝(Prune)
触发条件:
- 不透明度低:α < threshold
- 或位置不合理
操作:
低质量点 → 删除
目的:移除不重要的点,减少存储和计算
密度控制策略
时间表:
训练阶段:
┌─────────────────────────────────────────────┐
│ 0-500次: │
│ - 不执行密度控制 │
│ - 让初始点先优化 │
└─────────────────────────────────────────────┘
↓
┌─────────────────────────────────────────────┐
│ 500-15000次: │
│ - 每100次迭代执行一次 │
│ - 克隆:高梯度区域 │
│ - 分割:大高斯点 │
│ - 剪枝:低不透明度点 │
└─────────────────────────────────────────────┘
↓
┌─────────────────────────────────────────────┐
│ 15000-30000次: │
│ - 仅剪枝,不再增加点 │
│ - 仅优化现有点参数 │
└─────────────────────────────────────────────┘
阈值设置:
| 操作 | 梯度阈值 | 不透明度阈值 | 尺度阈值 |
|---|---|---|---|
| 克隆 | 0.0002 | 0.01 | - |
| 分割 | 0.0002 | - | 较大 |
| 剪枝 | - | 0.005 | - |
优化策略
学习率调度
位置学习率:
position_lr(t) = position_lr_init × exp(-t / position_lr_delay)
特点:
- 早期:高学习率,快速定位
- 后期:低学习率,精细调整
其他参数学习率:
- 颜色:相对稳定
- 不透明度:中等
- 缩放/旋转:与位置类似
正则化
不透明度正则化:
L_reg = λ × Σᵢ αᵢ
目的:鼓励稀疏表示,减少不必要的点
位置正则化:
L_pos = λ × Σᵢ ||μᵢ - μ₀||²
目的:防止点过度分散
训练流程详解
初始化策略
从SfM点云初始化
流程:
COLMAP稀疏点云
↓
┌─────────────────────────────────────────────┐
│ 1. 提取3D点位置 │
│ μᵢ = 点云中的点位置 │
└─────────────────────────────────────────────┘
↓
┌─────────────────────────────────────────────┐
│ 2. 初始化颜色 │
│ cᵢ = 最近视角的平均颜色 │
└─────────────────────────────────────────────┘
↓
┌─────────────────────────────────────────────┐
│ 3. 初始化不透明度 │
│ αᵢ = 0.1(较小初始值) │
└─────────────────────────────────────────────┘
↓
┌─────────────────────────────────────────────┐
│ 4. 初始化协方差矩阵 │
│ Σᵢ = 基于最近邻距离估计 │
│ 或使用固定小值 │
└─────────────────────────────────────────────┘
从随机位置初始化
适用场景:没有SfM点云时
方法:
- 在场景边界内随机采样位置
- 其他参数随机初始化
迭代优化过程
单次迭代流程
迭代 t:
┌─────────────────────────────────────────────┐
│ 1. 前向传播 │
│ - 可微光栅化 │
│ - 生成渲染图像 I_rendered │
└─────────────────────────────────────────────┘
↓
┌─────────────────────────────────────────────┐
│ 2. 损失计算 │
│ L = L1(I_rendered, I_gt) + │
│ λ_ssim × L_ssim(I_rendered, I_gt) │
└─────────────────────────────────────────────┘
↓
┌─────────────────────────────────────────────┐
│ 3. 反向传播 │
│ - 计算梯度 ∇L │
│ - 更新参数: │
│ μ ← μ - lr_μ × ∇L/∇μ │
│ c ← c - lr_c × ∇L/∇c │
│ α ← α - lr_α × ∇L/∇α │
│ Σ ← Σ - lr_Σ × ∇L/∇Σ │
└─────────────────────────────────────────────┘
↓
┌─────────────────────────────────────────────┐
│ 4. 密度控制(每N次迭代) │
│ - 克隆/分割/剪枝 │
└─────────────────────────────────────────────┘
训练循环伪代码
python
# 伪代码示例
def train_3dgs(images, cameras, iterations=30000):
# 初始化
gaussians = initialize_from_sfm(cameras)
for iteration in range(iterations):
# 随机选择一个视角
camera_idx = random.randint(0, len(cameras)-1)
camera = cameras[camera_idx]
image_gt = images[camera_idx]
# 前向传播:可微光栅化
image_rendered = rasterize(gaussians, camera)
# 损失计算
loss = L1_loss(image_rendered, image_gt) + \
lambda_ssim * SSIM_loss(image_rendered, image_gt)
# 反向传播
loss.backward()
# 参数更新
optimizer.step()
optimizer.zero_grad()
# 密度控制(每100次迭代)
if iteration % 100 == 0 and iteration < 15000:
densify_and_prune(gaussians)
# 定期保存
if iteration % 1000 == 0:
save_checkpoint(gaussians, iteration)
损失函数设计
L1损失
公式:
L_L1 = (1/N) × Σᵢ |I_rendered(i) - I_gt(i)|
特点:
- 对异常值不敏感
- 计算简单
- 梯度稳定
SSIM损失
公式:
L_SSIM = 1 - SSIM(I_rendered, I_gt)
SSIM计算:
SSIM(x, y) = [l(x, y)]^α × [c(x, y)]^β × [s(x, y)]^γ
其中:
- l(x, y):亮度比较
- c(x, y):对比度比较
- s(x, y):结构比较
优势:
- 更符合人眼感知
- 保留结构信息
总损失
L_total = L_L1 + λ_ssim × L_SSIM + λ_reg × L_reg
典型权重:
- λ_ssim = 0.2
- λ_reg = 0.0001
渲染算法
前向渲染流程
完整渲染管线
输入:高斯点云 + 相机参数
↓
┌─────────────────────────────────────────────┐
│ 1. 视锥剔除 │
│ - 移除视锥外的点 │
│ - 减少计算量 │
└─────────────────────────────────────────────┘
↓
┌─────────────────────────────────────────────┐
│ 2. 投影变换 │
│ - 3D高斯 → 2D高斯 │
│ - 计算2D协方差矩阵 │
└─────────────────────────────────────────────┘
↓
┌─────────────────────────────────────────────┐
│ 3. 深度排序 │
│ - 按深度值排序 │
│ - 准备从前到后渲染 │
└─────────────────────────────────────────────┘
↓
┌─────────────────────────────────────────────┐
│ 4. 光栅化 │
│ - 对每个像素: │
│ * 找到影响该像素的高斯点 │
│ * 计算2D高斯值 │
│ * Alpha混合 │
└─────────────────────────────────────────────┘
↓
输出图像
像素级渲染
对每个像素(u, v):
1. 找到影响该像素的高斯点集合 S
2. 按深度排序 S
3. 初始化颜色 C = 背景色
4. 对每个高斯点 i ∈ S(从前到后):
- 计算2D高斯值:w = G₂(u - μᵤ, v - μᵥ)
- 计算不透明度:α_eff = α × w
- 计算颜色:c = SH(视角方向)
- 混合:C = C + α_eff × c × (1 - α_accum)
- 更新累积不透明度:α_accum += α_eff
深度排序与Alpha混合
深度排序算法
方法1:全局排序
- 对所有高斯点按深度排序
- 时间复杂度:O(N log N)
- 适合点数较少时
方法2:分块排序
- 将图像分成块
- 每块内排序
- 适合并行计算
方法3:近似排序
- 使用可微的软排序
- 保持可微性
Alpha混合公式详解
标准Alpha混合:
C_final = C_bg × (1 - α_total) + Σᵢ (cᵢ × αᵢ × ∏ⱼ<ᵢ(1 - αⱼ))
简化形式(从前到后):
C = C_bg
for i in sorted_gaussians:
C = C + cᵢ × αᵢ × (1 - α_accum)
α_accum = α_accum + αᵢ × (1 - α_accum)
关键点:
- 必须从前到后混合
- 累积不透明度影响后续混合
- 保证物理正确性
抗锯齿技术
问题:锯齿现象
原因:
- 离散采样
- 高斯点边界不连续
- 缩放时出现锯齿
Mip-Splatting解决方案
原理:
- 根据视角距离调整高斯点大小
- 使用多尺度表示
- 预过滤技术
实现:
根据视角距离 d:
- 近处:使用原始高斯
- 远处:使用放大的高斯(预过滤)
效果:
- 远距离:更平滑
- 近距离:更清晰
- 整体:无锯齿
关键技术细节
协方差矩阵的参数化
为什么需要参数化
直接优化Σ的问题:
- Σ必须是正定矩阵
- 约束复杂
- 优化不稳定
缩放-旋转分解
分解公式:
Σ = R × S × Sᵀ × Rᵀ
其中:
- S = diag(sₓ, sᵧ, sᵧ):缩放矩阵
- R = R(q):旋转矩阵(从四元数计算)
参数约束:
- sₓ, sᵧ, sᵧ > 0(使用exp确保正数)
- |q| = 1(四元数归一化)
四元数到旋转矩阵
转换公式:
R = [
[1-2(q₂²+q₃²), 2(q₁q₂-q₀q₃), 2(q₁q₃+q₀q₂)],
[2(q₁q₂+q₀q₃), 1-2(q₁²+q₃²), 2(q₂q₃-q₀q₁)],
[2(q₁q₃-q₀q₂), 2(q₂q₃+q₀q₁), 1-2(q₁²+q₂²)]
]
归一化:
q = q / ||q||
球谐函数的应用
SH系数优化
优化目标:
- 最小化颜色误差
- 保持平滑性
梯度计算:
∂L/∂cₗᵐ = Σᵢ (∂L/∂I(i) × ∂I(i)/∂cₗᵐ)
视角方向计算
从相机到高斯点的方向:
direction = normalize(μ - camera_center)
转换为球面坐标:
θ = arccos(direction.z)
φ = arctan2(direction.y, direction.x)
计算SH值:
SH_value = Σₗ₌₀ᴸ Σₘ₌₋ₗˡ cₗᵐ × Yₗᵐ(θ, φ)
梯度计算与反向传播
关键梯度
位置梯度:
∂L/∂μ = Σᵢ (∂L/∂I(i) × ∂I(i)/∂μ)
颜色梯度:
∂L/∂c = Σᵢ (∂L/∂I(i) × ∂I(i)/∂c)
不透明度梯度:
∂L/∂α = Σᵢ (∂L/∂I(i) × ∂I(i)/∂α)
协方差梯度:
∂L/∂Σ = Σᵢ (∂L/∂I(i) × ∂I(i)/∂Σ)
链式法则应用
∂L/∂μ = ∂L/∂I × ∂I/∂G₂ × ∂G₂/∂G₃ × ∂G₃/∂μ
每一步都需要可微实现。
性能优化技术
空间数据结构
八叉树(Octree)
结构:
八叉树节点:
┌─────────────────────────────────────────────┐
│ 根节点 │
│ ┌─────┬─────┬─────┬─────┐ │
│ │ 000 │ 001 │ 010 │ 011 │ │
│ ├─────┼─────┼─────┼─────┤ │
│ │ 100 │ 101 │ 110 │ 111 │ │
│ └─────┴─────┴─────┴─────┘ │
│ │
│ 每个子节点递归细分 │
└─────────────────────────────────────────────┘
应用:
- 快速查找影响像素的高斯点
- 视锥剔除
- 层次细节(LOD)
空间哈希
原理:
- 将3D空间划分为网格
- 每个网格存储包含的高斯点
- 快速查找
优势:
- 实现简单
- 查询快速
并行计算优化
GPU并行化
策略:
- 像素级并行:每个线程处理一个像素
- 高斯点并行:每个线程处理一个高斯点
- 混合策略:根据场景选择
CUDA实现:
cuda
// 伪代码
__global__ void rasterize_kernel(
Gaussian* gaussians,
int num_gaussians,
float* output_image
) {
int pixel_idx = blockIdx.x * blockDim.x + threadIdx.x;
// 处理像素pixel_idx
// ...
}
内存访问优化
合并访问:
- 连续内存访问
- 减少内存延迟
共享内存:
- 缓存常用数据
- 减少全局内存访问
内存优化
压缩技术
量化:
- 位置:16位浮点数
- 颜色:8位整数
- 不透明度:8位整数
压缩比:
- 原始:236 bytes/点
- 压缩后:约50-100 bytes/点
- 压缩比:2-5倍
稀疏存储
方法:
- 只存储不透明度 > 阈值的点
- 使用稀疏数据结构
与相关技术对比
3DGS vs NeRF
表示方式对比
NeRF(隐式表示):
┌─────────────────────────────────────────────┐
│ 神经网络 f(x, d) → (c, σ) │
│ - 输入:3D位置x + 视角方向d │
│ - 输出:颜色c + 密度σ │
│ - 存储:网络权重(几MB到几十MB) │
└─────────────────────────────────────────────┘
3DGS(显式表示):
┌─────────────────────────────────────────────┐
│ 高斯点云 {μᵢ, Σᵢ, αᵢ, cᵢ} │
│ - 直接存储3D点 │
│ - 存储:点云数据(几十MB到几GB) │
└─────────────────────────────────────────────┘
训练对比
| 方面 | NeRF | 3DGS |
|---|---|---|
| 训练时间 | 数小时到数天 | 数十分钟 |
| 迭代次数 | 100K-1M | 10K-50K |
| 每次迭代时间 | 秒级 | 毫秒级 |
| 内存占用 | 中等 | 较高 |
渲染对比
| 方面 | NeRF | 3DGS |
|---|---|---|
| 渲染速度 | 慢(秒级) | 快(实时) |
| 渲染方法 | 体积渲染 | 光栅化 |
| 可并行性 | 低 | 高 |
| GPU利用率 | 中等 | 高 |
质量对比
| 指标 | NeRF | 3DGS |
|---|---|---|
| PSNR | 30-35 dB | 28-32 dB |
| SSIM | 0.92-0.97 | 0.90-0.95 |
| 细节 | 很高 | 高 |
| 伪影 | 较少 | 可能更多 |
3DGS vs 传统点云
表示能力
传统点云:
- 固定颜色
- 固定大小
- 无方向性
3DGS:
- 视角相关颜色(SH)
- 自适应大小(协方差)
- 有方向性(旋转)
渲染质量
传统点云:
- 需要大量点才能平滑
- 容易出现空洞
3DGS:
- 较少点即可平滑
- 高斯重叠填补空洞
3DGS vs 体素表示
存储效率
体素:
- 规则网格
- 存储:O(N³)
- 稀疏场景浪费大
3DGS:
- 自适应分布
- 存储:O(N)
- 只存储有内容的区域
分辨率
体素:
- 固定分辨率
- 受内存限制
3DGS:
- 自适应分辨率
- 细节区域更密
技术演进与变体
Mip-Splatting
问题:缩放时的锯齿
传统方法:
- 固定大小高斯
- 缩放时出现锯齿
Mip-Splatting:
- 多尺度表示
- 预过滤技术
- 根据视角距离调整
实现原理
根据视角距离d:
- 计算有效尺度:s_eff = s × (d / d_ref)
- 使用预过滤的高斯
- 平滑过渡
动态场景处理
挑战
静态3DGS:
- 只能表示静态场景
- 无法处理动态物体
解决方案
4D高斯:
- 增加时间维度
- 表示时空变化
变形场:
- 学习变形函数
- 将静态高斯变形
压缩与量化
量化技术
位置量化:
原始:32位浮点数
量化:16位浮点数或整数
颜色量化:
原始:48个SH系数(32位)
量化:减少SH阶数或使用8位
压缩算法
熵编码:
- 利用统计特性
- 进一步压缩
预测编码:
- 利用空间相关性
- 差分编码
实际应用分析
应用场景分析
场景1:室内场景重建
特点:
- 几何复杂
- 光照变化大
- 需要高细节
3DGS优势:
- 快速训练
- 实时渲染
- 可编辑
挑战:
- 透明物体(玻璃)
- 镜面反射
- 大范围场景
场景2:产品展示
特点:
- 小物体
- 需要高保真
- 多角度查看
3DGS优势:
- 高质量渲染
- 交互式查看
- 易于集成
性能分析
训练性能
影响因素:
- 图像数量
- 图像分辨率
- 场景复杂度
- GPU性能
优化方向:
- 减少迭代次数
- 降低分辨率
- 使用混合精度
渲染性能
影响因素:
- 高斯点数量
- 图像分辨率
- GPU性能
优化方向:
- 视锥剔除
- LOD技术
- 空间数据结构
内存占用分析
内存组成:
总内存 = 高斯点内存 + 临时内存 + 图像内存
高斯点内存:
内存 = N_points × (位置 + 颜色 + 不透明度 + 协方差)
= N_points × (12 + 192 + 4 + 28) bytes
= N_points × 236 bytes
示例:
- 100万点:约236 MB
- 500万点:约1.18 GB
- 1000万点:约2.36 GB
优化策略:
- 量化压缩
- 稀疏存储
- 分块加载
质量评估
评估指标:
| 指标 | 公式 | 说明 |
|---|---|---|
| PSNR | 20×log₁₀(MAX/√MSE) | 峰值信噪比,越大越好 |
| SSIM | [l×c×s] | 结构相似性,0-1,越大越好 |
| LPIPS | 感知损失 | 基于深度学习,越小越好 |
典型值范围:
| 场景类型 | PSNR | SSIM | LPIPS |
|---|---|---|---|
| 简单场景 | 30-35 dB | 0.95-0.98 | 0.02-0.05 |
| 中等场景 | 28-32 dB | 0.90-0.95 | 0.05-0.10 |
| 复杂场景 | 25-30 dB | 0.85-0.90 | 0.10-0.15 |
算法复杂度分析
时间复杂度:
训练阶段:
- 单次迭代:O(N_points × H × W)
- 总训练:O(N_points × H × W × N_iterations)
渲染阶段:
- 单帧渲染:O(N_visible_points × H × W)
- 其中N_visible_points通过视锥剔除减少
空间复杂度:
存储:
- 高斯点:O(N_points)
- 临时缓冲区:O(H × W)
- 总空间:O(N_points + H × W)
实现细节
CUDA内核优化
光栅化内核结构:
cuda
// 伪代码示例
__global__ void rasterize_gaussians(
Gaussian* gaussians,
int num_gaussians,
Camera camera,
float* output_image,
float* alpha_buffer
) {
int pixel_idx = blockIdx.x * blockDim.x + threadIdx.x;
int pixel_x = pixel_idx % image_width;
int pixel_y = pixel_idx / image_width;
// 初始化
float color[3] = {0, 0, 0};
float alpha = 0.0;
// 遍历影响该像素的高斯点
for (int i = 0; i < num_gaussians; i++) {
Gaussian g = gaussians[i];
// 投影到2D
float2 proj = project(g.position, camera);
// 计算2D高斯值
float2 diff = {pixel_x - proj.x, pixel_y - proj.y};
float gaussian_value = compute_2d_gaussian(diff, g.cov_2d);
// Alpha混合
float alpha_contrib = g.opacity * gaussian_value;
color = color + g.color * alpha_contrib * (1 - alpha);
alpha = alpha + alpha_contrib * (1 - alpha);
}
// 写入结果
output_image[pixel_idx * 3 + 0] = color[0];
output_image[pixel_idx * 3 + 1] = color[1];
output_image[pixel_idx * 3 + 2] = color[2];
}
内存访问模式优化
合并访问:
- 高斯点数据连续存储
- 使用结构体数组(SoA)或数组结构体(AoS)
- 根据访问模式选择
缓存优化:
- 使用共享内存缓存常用数据
- 减少全局内存访问
- 预取数据
实验与分析
消融实验
关键组件贡献:
| 组件 | 移除后PSNR下降 | 说明 |
|---|---|---|
| 自适应密度控制 | -2 dB | 点分布不均匀 |
| 球谐函数 | -1 dB | 视角变化不自然 |
| SSIM损失 | -0.5 dB | 结构细节丢失 |
| Mip-Splatting | -0.3 dB | 出现锯齿 |
参数敏感性分析
学习率影响:
- 过高:训练不稳定,可能发散
- 过低:训练慢,可能陷入局部最优
- 最优:根据实验调整
密度控制阈值:
- 梯度阈值:影响克隆/分割频率
- 不透明度阈值:影响剪枝频率
- 需要平衡质量和效率
场景3:大场景重建
特点:
- 范围大
- 细节多
- 内存限制
挑战:
- 内存占用大
- 训练时间长
- 渲染性能
解决方案:
- 分块处理
- 使用LOD技术
- 空间数据结构优化
总结与展望
技术优势总结
3DGS的核心优势:
┌─────────────────────────────────────────────┐
│ 1. 训练速度快 │
│ - 比NeRF快10-100倍 │
│ - 数十分钟完成训练 │
└─────────────────────────────────────────────┘
↓
┌─────────────────────────────────────────────┐
│ 2. 渲染速度快 │
│ - 实时渲染(30-60fps) │
│ - 支持交互式应用 │
└─────────────────────────────────────────────┘
↓
┌─────────────────────────────────────────────┐
│ 3. 可编辑性强 │
│ - 显式表示 │
│ - 可裁剪、可编辑 │
└─────────────────────────────────────────────┘
↓
┌─────────────────────────────────────────────┐
│ 4. 质量优秀 │
│ - 高保真度重建 │
│ - 细节丰富 │
└─────────────────────────────────────────────┘
技术局限
当前局限:
- 对透明/半透明物体支持有限
- 大场景内存占用较大
- 动态场景处理仍在研究
未来发展方向
研究方向:
- 动态场景:4D高斯、变形场
- 压缩技术:更高效的存储
- 质量提升:减少伪影、提高细节
- 实时编辑:交互式编辑工具
- 移动端部署:在移动设备上运行
应用方向:
- VR/AR内容创作
- 数字孪生
- 文化遗产保护
- 游戏开发
- 电影制作
3DGS作为新兴的3D场景表示技术,在训练速度、渲染速度和可编辑性方面具有显著优势,正在成为3D重建和渲染领域的重要技术。随着技术的不断发展,3DGS将在更多领域发挥重要作用。