3D Gaussian Splatting代码详解(二):模型构建

3 模型构建 

gaussians = GaussianModel(dataset.sh_degree)

3.1 初始化函数

__init__ 构造函数

构造函数 __init__ 的主要作用是初始化 3D 高斯模型的各项参数和激活函数,用于生成 3D 空间中的高斯表示。

  1. 初始化球谐函数的参数

    • self.active_sh_degree:当前激活的球谐函数次数,初始为 0
    • self.max_sh_degree:指定的最大球谐函数次数(由 sh_degree 参数传入),用于控制颜色表示的复杂度。
  2. 初始化 3D 高斯模型的各项参数

    • self._xyz:3D 高斯中心位置(均值),用于确定高斯分布的中心。
    • self._features_dc:第一个球谐系数,用于表示基础颜色。
    • self._features_rest:其余球谐系数,用于表示颜色细节。
    • self._scaling:3D 高斯的尺度参数,控制高斯分布的宽度。
    • self._rotation:3D 高斯的旋转参数,使用四元数表示旋转。
    • self._opacity:3D 高斯的不透明度,控制可见性。
    • self.max_radii2D:在 2D 投影中的最大半径,控制每个高斯点在屏幕上呈现的大小。
    • self.xyz_gradient_accum:用于累积 3D 高斯中心位置的梯度信息,可能在优化时会用到。
    • self.denom:未明确用途的参数,但可能是为后续的计算准备。
    • self.optimizer:优化器,将用于调整上述参数以优化模型效果。
  3. 调用 setup_functions 初始化处理函数setup_functions 定义了一些用于操作这些参数的处理函数(如协方差矩阵构建、激活函数等)。

setup_functions 函数

setup_functions 是一个辅助方法,用于定义和初始化一些与 3D 高斯模型参数有关的函数。这些函数主要用于 3D 高斯模型的计算和优化,特别是协方差矩阵、激活函数等。

  1. 构建协方差矩阵

    • build_covariance_from_scaling_rotation:根据高斯的尺度参数和旋转参数构建协方差矩阵。
      • 使用 build_scaling_rotation(假设是外部函数)对 scaling_modifier * scalingrotation 参数进行处理,生成一个变换矩阵 L
      • 计算实际协方差矩阵 actual_covariance = L @ L.transpose(1, 2),从而得到对称的协方差矩阵 symm
  2. 激活函数

    • self.scaling_activationself.scaling_inverse_activation:分别为尺度参数的激活函数(torch.exp)和逆激活函数(torch.log),确保尺度参数为非负。
    • self.covariance_activation:用于计算协方差矩阵的激活函数,设置为 build_covariance_from_scaling_rotation
    • self.opacity_activationself.inverse_opacity_activation:分别为不透明度的激活函数(torch.sigmoid)和逆激活函数(inverse_sigmoid),确保不透明度在 0 到 1 之间。
    • self.rotation_activation:用于标准化旋转参数的函数,使用 torch.nn.functional.normalize 确保四元数的单位长度,维持旋转参数的有效性。

代码功能:这段代码为 3D 高斯模型定义了各种属性和函数,能够支持对模型位置、颜色、透明度、旋转等特征进行控制,并提供协方差矩阵生成、尺度和不透明度控制等方法。

代码如下:

def __init__(self, sh_degree: int):"""初始化3D高斯模型的参数。:param sh_degree: 球谐函数的最大次数,用于控制颜色表示的复杂度。"""# 初始化球谐次数和最大球谐次数self.active_sh_degree = 0  # 当前激活的球谐次数,初始为0self.max_sh_degree = sh_degree  # 允许的最大球谐次数# 初始化3D高斯模型的各项参数self._xyz = torch.empty(0)  # 3D高斯的中心位置(均值)self._features_dc = torch.empty(0)  # 第一个球谐系数,用于表示基础颜色self._features_rest = torch.empty(0)  # 其余的球谐系数,用于表示颜色的细节和变化self._scaling = torch.empty(0)  # 3D高斯的尺度参数,控制高斯的宽度self._rotation = torch.empty(0)  # 3D高斯的旋转参数,用四元数表示self._opacity = torch.empty(0)  # 3D高斯的不透明度,控制可见性self.max_radii2D = torch.empty(0)  # 在2D投影中,每个高斯的最大半径self.xyz_gradient_accum = torch.empty(0)  # 用于累积3D高斯中心位置的梯度self.denom = torch.empty(0)  # 未明确用途的参数self.optimizer = None  # 优化器,用于调整上述参数以改进模型# 调用setup_functions来初始化一些处理函数self.setup_functions()def setup_functions(self):"""定义和初始化一些用于处理3D高斯模型参数的函数。"""# 定义构建3D高斯协方差矩阵的函数def build_covariance_from_scaling_rotation(scaling, scaling_modifier, rotation):L = build_scaling_rotation(scaling_modifier * scaling, rotation)actual_covariance = L @ L.transpose(1, 2)  # 计算实际的协方差矩阵symm = strip_symmetric(actual_covariance)  # 提取对称部分return symm# 初始化一些激活函数self.scaling_activation = torch.exp  # 用exp函数确保尺度参数非负self.scaling_inverse_activation = torch.log  # 尺度参数的逆激活函数,用于梯度回传self.covariance_activation = build_covariance_from_scaling_rotation  # 协方差矩阵的激活函数self.opacity_activation = torch.sigmoid  # 用sigmoid函数确保不透明度在0到1之间self.inverse_opacity_activation = inverse_sigmoid  # 不透明度的逆激活函数self.rotation_activation = torch.nn.functional.normalize  # 用于标准化旋转参数的函数

def build_scaling_rotation(s, r):"""构建3D高斯模型的尺度-旋转矩阵。:param s: 尺度参数。:param r: 旋转参数。:return: 尺度-旋转矩阵。"""L = torch.zeros((s.shape[0], 3, 3), dtype=torch.float, device="cuda")  # 初始化尺度矩阵R = build_rotation(r)  # 计算旋转矩阵# 设置尺度矩阵的对角线元素L[:, 0, 0] = s[:, 0]L[:, 1, 1] = s[:, 1]L[:, 2, 2] = s[:, 2]L = R @ L  # 应用旋转return Ldef strip_symmetric(sym):"""提取协方差矩阵的对称部分。:param sym: 协方差矩阵。:return: 对称部分。"""return strip_lowerdiag(sym)def strip_lowerdiag(L):"""从协方差矩阵中提取六个独立参数。:param L: 协方差矩阵。:return: 六个独立参数组成的张量。"""uncertainty = torch.zeros((L.shape[0], 6), dtype=torch.float, device="cuda")# 提取协方差矩阵的独立元素uncertainty[:, 0] = L[:, 0, 0]uncertainty[:, 1] = L[:, 0, 1]uncertainty[:, 2] = L[:, 0, 2]uncertainty[:, 3] = L[:, 1, 1]uncertainty[:, 4] = L[:, 1, 2]uncertainty[:, 5] = L[:, 2, 2]return uncertainty

分别用于构建 3D 高斯模型的尺度-旋转矩阵,并从协方差矩阵中提取其对称部分和独立参数。这一系列函数主要用于 3D 空间中的高斯分布建模,特别是通过旋转和缩放来控制高斯的形状和方向。

函数解析

1. build_scaling_rotation(s, r)

build_scaling_rotation 的作用是生成 3D 高斯模型的尺度-旋转矩阵,方法是首先创建一个对角尺度矩阵 LLL ,然后对其应用旋转矩阵 RRR。

  • 参数

    • s: 尺度参数,形状为 (batch_size, 3) 的张量,表示每个样本在 3 个维度上的尺度(宽度)。
    • r: 旋转参数,通常以四元数或欧拉角表示,用于生成 旋转矩阵 RRR。
  • 步骤

    1. 初始化张量 L:一个形状为 (batch_size, 3, 3) 的 3D 张量,全为零。
    2. 计算旋转矩阵 R:调用 build_rotation(r) 函数(假设在代码的其他部分定义),生成一个形状为 (batch_size, 3, 3) 的旋转矩阵。
    3. 设置尺度矩阵的对角元素:将 s 的每个维度赋值到 L 的对角线上(分别为 L[:, 0, 0], L[:, 1, 1], L[:, 2, 2])。
    4. 计算尺度-旋转矩阵:将旋转矩阵 R 与尺度矩阵 L 相乘,以应用旋转变换,得到最终的尺度-旋转矩阵 L
  • 返回值:返回 L,即应用旋转后的尺度矩阵,形状为 (batch_size, 3, 3)

2. strip_symmetric(sym)

strip_symmetric 函数用于提取协方差矩阵的对称部分。协方差矩阵通常是对称的,这一函数可以用来获取对称部分。

  • 参数

    • sym: 协方差矩阵,形状为 (batch_size, 3, 3)
  • 步骤

    1. 调用 strip_lowerdiag(sym),该函数提取协方差矩阵中的 6 个独立元素(下三角部分)来表示对称矩阵。
  • 返回值:返回协方差矩阵的对称部分的六个独立参数。

3. strip_lowerdiag(L)

strip_lowerdiag 用于从协方差矩阵 L 中提取独立参数(即下三角部分的 6 个独立值),表示协方差矩阵的对称部分。这样可以用更少的参数来表示矩阵。

  • 参数

    • L: 协方差矩阵,形状为 (batch_size, 3, 3)
  • 步骤

    1. 初始化 uncertainty:形状为 (batch_size, 6) 的张量,用来存储每个协方差矩阵的独立参数。
    2. 提取下三角元素:分别提取对角和非对角元素,存入 uncertainty 的不同位置。
      • uncertainty[:, 0]:取 L 的第一个对角元素 L[:, 0, 0]
      • uncertainty[:, 1]uncertainty[:, 2]:分别取 L[:, 0, 1]L[:, 0, 2]
      • uncertainty[:, 3]:取 L 的第二个对角元素 L[:, 1, 1]
      • uncertainty[:, 4]:取 L[:, 1, 2]
      • uncertainty[:, 5]:取 L 的第三个对角元素 L[:, 2, 2]
  • 返回值:返回 uncertainty 张量,包含六个独立参数,形状为 (batch_size, 6)

代码总结

这段代码构建了 3D 高斯模型的尺度-旋转矩阵,并通过提取协方差矩阵的对称部分,简化了矩阵的存储和计算。 build_scaling_rotation 通过结合旋转和缩放矩阵来生成高斯的尺度-旋转矩阵,而 strip_lowerdiagstrip_symmetric 则用于提取协方差矩阵的主要参数。这种方法在 3D 高斯建模中常用于表征形状、方向和尺度,减少了参数数量,提高了效率。

3.2 为3D Gaussion的各组参数创建  optimizer 以及lr_scheduler

def training_setup(self, training_args):"""设置训练参数,包括初始化用于累积梯度的变量,配置优化器,以及创建学习率调度器:param training_args: 包含训练相关参数的对象。"""# 设置在训练过程中,用于密集化处理的3D高斯点的比例self.percent_dense = training_args.percent_dense# 初始化用于累积3D高斯中心点位置梯度的张量,用于之后判断是否需要对3D高斯进行克隆或切分self.xyz_gradient_accum = torch.zeros((self.get_xyz.shape[0], 1), device="cuda")self.denom = torch.zeros((self.get_xyz.shape[0], 1), device="cuda")# 配置各参数的优化器,包括指定参数、学习率和参数名称l = [{'params': [self._xyz], 'lr': training_args.position_lr_init * self.spatial_lr_scale, "name": "xyz"},{'params': [self._features_dc], 'lr': training_args.feature_lr, "name": "f_dc"},{'params': [self._features_rest], 'lr': training_args.feature_lr / 20.0, "name": "f_rest"},{'params': [self._opacity], 'lr': training_args.opacity_lr, "name": "opacity"},{'params': [self._scaling], 'lr': training_args.scaling_lr, "name": "scaling"},{'params': [self._rotation], 'lr': training_args.rotation_lr, "name": "rotation"}]# 创建优化器,这里使用Adam优化器self.optimizer = torch.optim.Adam(l, lr=0.0, eps=1e-15)# 创建学习率调度器,用于对中心点位置的学习率进行调整self.xyz_scheduler_args = get_expon_lr_func(lr_init=training_args.position_lr_init*self.spatial_lr_scale,lr_final=training_args.position_lr_final*self.spatial_lr_scale,lr_delay_mult=training_args.position_lr_delay_mult,max_steps=training_args.position_lr_max_steps)

def get_expon_lr_func(lr_init, lr_final, lr_delay_steps=0, lr_delay_mult=1.0, max_steps=1000000):"""创建一个学习率调度函数,该函数根据训练进度动态调整学习率:param lr_init: 初始学习率。:param lr_final: 最终学习率。:param lr_delay_steps: 学习率延迟步数,在这些步数内学习率将被降低。:param lr_delay_mult: 学习率延迟乘数,用于计算初始延迟学习率。:param max_steps: 最大步数,用于规范化训练进度。:return: 一个函数,根据当前步数返回调整后的学习率。"""def helper(step):# 如果步数小于0或学习率为0,直接返回0,表示不进行优化if step < 0 or (lr_init == 0.0 and lr_final == 0.0):return 0.0# 如果设置了学习率延迟步数,计算延迟调整后的学习率if lr_delay_steps > 0:delay_rate = lr_delay_mult + (1 - lr_delay_mult) * np.sin(0.5 * np.pi * np.clip(step / lr_delay_steps, 0, 1))else:delay_rate = 1.0# 根据步数计算学习率的对数线性插值,实现从初始学习率到最终学习率的平滑过渡t = np.clip(step / max_steps, 0, 1)log_lerp = np.exp(np.log(lr_init) * (1 - t) + np.log(lr_final) * t)# 返回调整后的学习率return delay_rate * log_lerpreturn helper

3.3 从点云pcd 创建3D Gaussian

def create_from_pcd(self, pcd: BasicPointCloud, spatial_lr_scale: float):"""从点云数据初始化模型参数。:param pcd: 点云数据,包含点的位置和颜色。:param spatial_lr_scale: 空间学习率缩放因子,影响位置参数的学习率。"""# 将点云的位置和颜色数据从numpy数组转换为PyTorch张量,并传送到CUDA设备上self.spatial_lr_scale = spatial_lr_scalefused_point_cloud = torch.tensor(np.asarray(pcd.points)).float().cuda()  # (P, 3)fused_color = RGB2SH(torch.tensor(np.asarray(pcd.colors)).float().cuda())  # (P, 3)# 初始化存储球谐系数的张量,每个颜色通道有(max_sh_degree + 1) ** 2个球谐系数features = torch.zeros((fused_color.shape[0], 3, (self.max_sh_degree + 1) ** 2)).float().cuda()  # (P, 3, 16)features[:, :3, 0] = fused_color  # 将RGB转换后的球谐系数C0项的系数存入features[:, 3:, 1:] = 0.0  # 其余球谐系数初始化为0# 打印初始点的数量print("Number of points at initialisation : ", fused_point_cloud.shape[0])# 计算点云中每个点到其最近的k个点的平均距离的平方,用于确定高斯的尺度参数dist2 = torch.clamp_min(distCUDA2(torch.from_numpy(np.asarray(pcd.points)).float().cuda()), 0.0000001)  # (P,)scales = torch.log(torch.sqrt(dist2))[..., None].repeat(1, 3)  # (P, 3)# 初始化每个点的旋转参数为单位四元数(无旋转)rots = torch.zeros((fused_point_cloud.shape[0], 4), device="cuda")  # (P, 4)rots[:, 0] = 1  # 四元数的实部为1,表示无旋转# 初始化每个点的不透明度为0.1(通过inverse_sigmoid转换)opacities = inverse_sigmoid(0.1 * torch.ones((fused_point_cloud.shape[0], 1), dtype=torch.float, device="cuda"))  # (P, 1)# 将以上计算的参数设置为模型的可训练参数self._xyz = nn.Parameter(fused_point_cloud.requires_grad_(True))  # 位置self._features_dc = nn.Parameter(features[:, :, 0:1].transpose(1, 2).contiguous().requires_grad_(True))  # 球谐系数C0项self._features_rest = nn.Parameter(features[:, :, 1:].transpose(1, 2).contiguous().requires_grad_(True))  # 其余球谐系数self._scaling = nn.Parameter(scales.requires_grad_(True))  # 尺度self._rotation = nn.Parameter(rots.requires_grad_(True))  # 旋转self._opacity = nn.Parameter(opacities.requires_grad_(True))  # 不透明度self.max_radii2D = torch.zeros((self.get_xyz.shape[0]), device="cuda")  # 存储2D投影的最大半径,初始化为0
def RGB2SH(rgb):"""将RGB颜色值转换为球谐系数C0项的系数。:param rgb: RGB颜色值。:return: 转换后的球谐系数C0项的系数。"""return (rgb - 0.5) / C0

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/460657.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

一文讲明白大模型分布式逻辑(从GPU通信原语到Megatron、Deepspeed)

1. 背景介绍 如果你拿到了两台8卡A100的机器(做梦),你的导师让你学习部署并且训练不同尺寸的大模型,并且写一个说明文档。你意识到,你最需要学习的就是关于分布式训练的知识,因为你可是第一次接触这么多卡…

Python毕业设计选题:基于协同过滤的校园音乐推荐系统小程序-django+uniapp

开发语言:Python框架:djangouniappPython版本:python3.7.7数据库:mysql 5.7数据库工具:Navicat11开发软件:PyCharm 系统展示 管理员登录界面 管理员功能界面 用户管理 音乐信息管理 音乐类型管理 留言板管…

【python】OpenCV—findContours(4.4)

文章目录 1、功能描述2、代码实现3、完整代码4、结果展示5、涉及到的库函数6、参考 1、功能描述 找出物体轮廓,根据 PCA 计算特征值和特征向量,绘制特征值和特征向量,来初步展示物体的方向 2、代码实现 导入库函数,读入图片&am…

Jmeter实际应用

环境准备 JDK1.8Jmeter 5.6.3 下载地址Jmeter 插件 下载地址 放到lib/ext下 常用命令 # 启动 sh jmeter# 集群模式下启动节点,不启动用不了集群 sh jmeter-server#生成ssl需要的证书, 这里会要求输入个密码,是要在jmeter中用的 keytool -import -ali…

Javaweb 实验4 xml

我发现了有些人喜欢静静看博客不聊天呐, 但是ta会点赞。 这样的人呢帅气低调有内涵, 美丽大方很优雅。 说的就是你, 不用再怀疑哦 实验四 XML 目的: 安装和使用XML的开发环境认识XML的不同类型掌握XML文档的基本语法了解D…

C#界面设计--9--fatal error C1083: 无法打开包括文件:“jruparse.h”: No such file or directory

1、VS2008-编译时报错“fatal error C1083: 无法打开包括文件:“jruparse.h”: No such file or directory” 2、问题出现的原因及解决方法 1、如果要引入的这些,h文件跟.cpp在同一个目录下,就不会出现这种问题,检査在工程的include目录下是不是真的存…

【机器学习】 15. SVM 支撑向量机 support vector machine,拉格朗日,软边界,核函数

SVM 支撑向量机 support vector machine,拉格朗日,软边界,核函数 1. 超平面边界 margin of hyperplane2. 边界越大的超平面越好原因 3. 线性模型通过决策边界分类4. SVM的问题5. 拉格朗日乘子与SVM结合求最大边界6. SVM软边界和硬边界7. 非线…

SpringBoot获取resources目录下的文件

在 Spring Boot 项目中,获取 resources 目录中的文件路径通常涉及到访问类路径资源(classpath resources)。Spring Boot 提供了一些工具类和方法,可以方便地访问这些资源。以下是一些常见的方法: 首先,我们…

GitLab代码仓管理安装配置使用

Gitlab介绍 GitLab是一个基于Git的开源项目管理工具,它集成了版本控制、代码审查、持续集成(CI)/持续部署(CD)、自动化测试等多种功能,是一个完整的DevOps平台。以下是对GitLab的详细介绍: 一…

C#/WinForm 基于ffmpeg视频流转GIF

源码:https://gitee.com/feng-cai/screenshot-recording

Pinctrl子系统pinctrl_desc结构体进一步介绍

往期内容 本专栏往期内容: Pinctrl子系统和其主要结构体引入 input子系统专栏: 专栏地址:input子系统input角度:I2C触摸屏驱动分析和编写一个简单的I2C驱动程序 – 末片,有往期内容观看顺序 I2C子系统专栏:…

基于OSS搭建在线教育视频课程分享网站

OSS对象存储服务是海量、安全、低成本、高持久的存储服务。适合于存储大规模非结构化数据,如图片、视频、备份文件和容器/虚拟机镜像等。 安装nginx wget https://nginx.org/download/nginx-1.20.2.tar.gz yum -y install zlib zlib-devel gcc-c pcre-devel open…

研究轮腿运动学方案的看法

本文学习自电科中山柳同学的方案分享 遇到的问题: 1、轮毂输出力矩不足以配合腿部收敛机体姿态(即腿部关节输出和轮毂输出都被LQR拉大了,但是轮毂最大力矩不够用了) 可以引入MPC对LQR输出的反馈增益矩阵K 进行反向增益&#xf…

Linux学习_11

第十章管理Linux的联网 主要包括配置网络,通过域名访问主机,从网站瞎子啊文件,VMware三种网络模式 配置网络 概念 网络接口是指网络中的计算机或网络设备与其他设备实现通讯的进出口,一般是指计算机的网络接口即网卡设备 从RHEL7开…

VBto Converter是一款功能强大的工具,可让您快速轻松地将Microsoft Visual Basic 6.0项目转换

VBto Converter是一款功能强大的工具,可让您快速轻松地将Microsoft Visual Basic 6.0项目转换 1、简介2、官方网站3、本站下载(已汉化) 1、简介 VBto Converter V2.90 版本,是一款功能强大的工具,可让您快速轻松地将M…

巨好看的登录注册界面源码

展示效果 源码 <!DOCTYPE html> <html lang"en"><head><meta charset"UTF-8" /><meta http-equiv"X-UA-Compatible" content"IEedge" /><meta name"viewport" content"widthdevic…

突破挑战,创新前行 | 生信科技SOLIDWORKS 2025新品发布会·合肥站精彩回顾

2024年10月18日&#xff0c;由生信科技举办的首场SOLIDWORKS 2025新产品发布会在安徽合肥圆满落幕。现场邀请到制造业的专家学者们一同感受SOLIDWORKS 2025最新功能&#xff0c;探索制造业数字化转型之路。 合肥站活动日&#xff0c;由生信科技副总经理徐建开场。他以智造无界&…

【解决方案】微信小程序如何使用 ProtoBuf 进行 WebSocket 通信

前言 故事背景 简单说下背景&#xff0c;项目中需要用 ProtoBuf 协议转换请求参数&#xff0c;并通过 WebSocket 进行双向通信。重点&#xff01;一个是 web端&#xff08;Vue3 TS&#xff09;&#xff0c;一个是微信小程序端&#xff08;原生 JS&#xff09;。 剧情发展 …

Copilot一又成编程助手Top1,GitHub官宣接入Claude+Gemini!OpenAI的Canvas沦为备胎

Copilot一又成编程助手Top1&#xff0c;GitHub官宣接入ClaudeGemini&#xff01;OpenAI的Canvas沦为备胎 &#x1f31f; &#x1f44b; 大家好&#xff0c;我是猫头虎&#xff01;今天带大家来深度解读GitHub Copilot 的最新动态&#xff01;在第十届 GitHub 开发者大会上&…

三周精通FastAPI:24 OAuth2 实现简单的 Password 和 Bearer 验证

官网文档&#xff1a;https://fastapi.tiangolo.com/zh/tutorial/security/simple-oauth2/ OAuth2 实现简单的 Password 和 Bearer 验证 本章添加上一章示例中欠缺的部分&#xff0c;实现完整的安全流。 获取 username 和 password 首先&#xff0c;使用 FastAPI 安全工具获…