首页 > 3DGS教程 > 3DGS初始化

3DGS初始化:从SfM稀疏点云到高斯分布

将稀疏点云转化为连续的3D表示

在3DGS(3D Gaussian Splatting)中,我们如何将通过SfM(Structure from Motion)获得的稀疏点云转换为连续的3D高斯分布呢?这就是3DGS初始化要解决的问题。

3D视觉趣闻

  • 3DGS技术在2023年被提出后,迅速成为NeRF(神经辐射场)的有力竞争者,因为它能实现实时渲染高质量的3D场景。
  • 与NeRF使用神经网络隐式表示3D场景不同,3DGS使用显式的高斯分布来表示场景,这使得渲染速度大大提升。
  • 3DGS的初始化过程类似于将一个由点组成的"骨架"转换为一个由高斯分布组成的"血肉",让3D场景更加丰满。
  • SfM技术在3DGS初始化中扮演着重要角色,它为3DGS提供了初始的几何结构。
  • 3DGS在虚拟现实(VR)和增强现实(AR)领域有广泛应用,能够创建逼真的3D环境和物体。
  • 许多大型科技公司如Meta、Google和Apple都在积极研究和应用3DGS技术,用于改进他们的AR/VR产品和地图服务。
  • 3DGS技术甚至被应用于电影特效制作,为观众带来更加震撼的视觉体验。

在3DGS中,场景被表示为一组3D高斯分布,每个高斯分布都有位置、协方差矩阵(描述形状和方向)以及颜色和透明度参数。

让我们一起探索如何将SfM生成的稀疏点云转换为这些3D高斯分布!

核心知识点讲解

1 什么是3DGS初始化?

3DGS初始化是指将通过SfM技术获得的稀疏点云转换为3D高斯分布的过程。

在这个过程中,我们需要为每个点分配以下参数:

  • 位置:直接使用SfM点云中点的3D坐标
  • 协方差矩阵:描述高斯分布的形状和方向
  • 颜色和透明度:决定高斯分布的外观属性

🧊 点与高斯:如果把SfM点云比作一堆冰块,那么3DGS初始化就像给每个冰块加上"柔光"效果,让它们变成有体积、有颜色、有透明度的"果冻"。

3DGS技术在多个领域有重要应用:

  • 虚拟现实和增强现实:创建逼真的3D环境和物体
  • 自动驾驶:构建高精度的3D地图
  • 文化遗产保护:数字化保存文物和古迹
  • 医学影像:重建器官和组织的3D模型
  • 游戏开发:快速创建高质量的游戏场景

2 核心操作1:点云转换为高斯分布

这是最直观的一步。SfM生成的每个3D点直接作为3D高斯分布的中心位置

设SfM点云中的一个点为 \( P_i = (x_i, y_i, z_i) \),则对应的3D高斯分布中心位置就是 \( \mu_i = (x_i, y_i, z_i) \)。

3 核心操作2:初始化协方差矩阵

协方差矩阵 \( \Sigma \) 决定了3D高斯分布的形状方向。初始化方法有多种,常见的有:

  • 固定大小:为所有高斯分布设置相同的协方差矩阵
  • 基于邻近点:根据点周围的邻近点分布来确定协方差矩阵
  • 基于重建误差:根据点在不同视角下的重建误差来调整协方差矩阵

一个简单的初始化方法是设置协方差矩阵为一个各向同性的球体:

\( \Sigma_i = \begin{bmatrix} \sigma^2 & 0 & 0 \\ 0 & \sigma^2 & 0 \\ 0 & 0 & \sigma^2 \end{bmatrix} \)

其中 \( \sigma^2 \) 是一个预设的方差值,可以根据点云的密度来调整。

4 核心操作3:设置初始颜色和透明度

颜色和透明度决定了3D高斯分布的外观

  • 颜色:在3DGS中,颜色通常使用球谐函数(Spherical Harmonics)来表示,以实现更好的视相关颜色效果。在初始化阶段,可以基于点云中点在图像上的投影位置,从对应图像中获取初始颜色值。
  • 透明度:初始透明度通常设置为一个较小的值(如0.1),在后续优化中会调整

设点 \( P_i \) 在图像 \( I_j \) 上的投影点为 \( p_{ij} \),对应的颜色为 \( C_{ij} \),则该点的初始颜色可以设置为:

\( C_i = \frac{1}{N} \sum_{j=1}^{N} C_{ij} \)

其中 \( N \) 是观测到该点的图像数量。

🧊 点与高斯:如果把SfM点云比作一堆冰块,那么3DGS初始化就像给每个冰块加上"柔光"效果,让它们变成有体积、有颜色、有透明度的"果冻"。

动手实践:用Python实现3DGS初始化

下面我们用Python来实现一个简化的3DGS初始化过程。这段代码将:

  1. 生成模拟的SfM点云数据
  2. 将点云转换为3D高斯分布
  3. 初始化协方差矩阵
  4. 设置初始颜色和透明度
import numpy as np
import matplotlib.pyplot as plt
from mpl_toolkits.mplot3d import Axes3D

# 设置中文字体
plt.rcParams["font.family"] = ["SimHei", "WenQuanYi Micro Hei", "Heiti TC"]

class SfMPointCloud:
    """
    模拟SfM点云数据
    """
    def __init__(self, num_points=100):
        # 生成随机3D点
        self.points = np.random.rand(num_points, 3) * 10 - 5  # 范围[-5, 5]
        
        # 为每个点生成随机颜色(RGB)
        self.colors = np.random.rand(num_points, 3)
        
    def get_points(self):
        return self.points
        
    def get_colors(self):
        return self.colors

class Gaussian3D:
    """
    3D高斯分布类
    """
    def __init__(self, position, covariance, color, alpha=0.1):
        self.position = position      # 位置 (x, y, z)
        self.covariance = covariance  # 协方差矩阵 (3x3)
        self.color = color            # 颜色 (R, G, B)
        self.alpha = alpha            # 透明度
        
    def __str__(self):
        return f"Gaussian3D(position={self.position}, color={self.color}, alpha={self.alpha})"

class GaussianSplattingInitializer:
    """
    3DGS初始化器
    """
    def __init__(self, point_cloud, initial_sigma=0.1):
        self.point_cloud = point_cloud
        self.initial_sigma = initial_sigma
        self.gaussians = []
        
    def initialize(self):
        """
        执行3DGS初始化
        """
        points = self.point_cloud.get_points()
        colors = self.point_cloud.get_colors()
        
        # 创建单位协方差矩阵
        covariance = np.eye(3) * self.initial_sigma**2
        
        # 为每个点创建高斯分布
        for i in range(len(points)):
            position = points[i]
            color = colors[i]
            
            # 创建3D高斯分布
            gaussian = Gaussian3D(position, covariance, color)
            self.gaussians.append(gaussian)
            
        return self.gaussians
        
    def visualize(self):
        """
        可视化点云和初始化的高斯分布
        """
        points = self.point_cloud.get_points()
        colors = self.point_cloud.get_colors()
        
        fig = plt.figure(figsize=(12, 5))
        
        # 绘制原始点云
        ax1 = fig.add_subplot(121, projection='3d')
        ax1.scatter(points[:, 0], points[:, 1], points[:, 2], c=colors, s=20)
        ax1.set_title('SfM点云')
        ax1.set_xlabel('X')
        ax1.set_ylabel('Y')
        ax1.set_zlabel('Z')
        
        # 绘制高斯分布中心点(与点云相同)
        ax2 = fig.add_subplot(122, projection='3d')
        ax2.scatter(points[:, 0], points[:, 1], points[:, 2], c=colors, s=20)
        ax2.set_title('3DGS初始化(高斯分布中心)')
        ax2.set_xlabel('X')
        ax2.set_ylabel('Y')
        ax2.set_zlabel('Z')
        
        plt.tight_layout()
        plt.show()

# 主程序
def main():
    # 1. 创建模拟的SfM点云
    sfm_cloud = SfMPointCloud(num_points=50)
    
    # 2. 初始化3DGS
    initializer = GaussianSplattingInitializer(sfm_cloud, initial_sigma=0.2)
    gaussians = initializer.initialize()
    
    # 3. 打印前5个高斯分布信息
    print("前5个初始化的3D高斯分布:")
    for i in range(min(5, len(gaussians))):
        print(f"  {i+1}. {gaussians[i]}")
    
    # 4. 可视化结果
    initializer.visualize()

if __name__ == "__main__":
    main()

总结与思考

通过本节的学习,我们了解了3DGS初始化的核心步骤:

  • 将SfM点云中的点作为3D高斯分布的中心位置
  • 初始化协方差矩阵以确定高斯分布的形状和方向
  • 设置初始颜色和透明度以确定高斯分布的外观

🧠 深入思考:3DGS初始化的质量对后续优化和最终渲染效果有很大影响。如何设计更好的初始化策略来提高重建质量?

练习题

1. 概念理解

为什么需要将SfM点云转换为3D高斯分布,而不是直接使用点云进行渲染?

查看答案

点云是离散的几何表示,缺乏连续性和体积感。3D高斯分布提供了连续的、有体积的表示,使得渲染更加平滑和真实。此外,高斯分布还包含了颜色和透明度信息,可以直接用于渲染。

2. 参数分析

协方差矩阵的初始值对3DGS重建有什么影响?

查看答案

协方差矩阵的初始值决定了高斯分布的初始大小和形状。如果初始值过大,可能导致过度平滑;如果初始值过小,可能导致重建过于稀疏。合适的初始值有助于后续优化过程收敛到更好的结果。

3. 实践探索

修改代码中的初始化策略,尝试不同的协方差矩阵初始化方法,并观察对可视化结果的影响。