3DGS学习(六)—— 参数更新

参数更新

参考文章:3dgs中的数学推导

协方差矩阵的参数更新

  • 直接通过pytorch自带的更新机制,通过渲染后计算损失,只能更新2D协方差矩阵 Σ ′ \Sigma^\prime Σ,再通过公式逆推出3d空间协方差矩阵 Σ \Sigma Σ的值。该过程处理矩阵计算多且复杂,计算效率低下。
  • 为了提高计算效率,我们需要显示的表示 Σ \Sigma Σ,即利用前面学习到的将该矩阵拆分成旋转矩阵 R R R以及放缩矩阵 S S S
    Σ = R S S ⊤ R ⊤ \boldsymbol{\Sigma}=\boldsymbol{R}\boldsymbol{S}\boldsymbol{S}^\top\boldsymbol{R}^\top Σ=RSSR
  • 通过旋转四元数,我们可以进一步将要更新的R矩阵内的9个参数压缩到4个参数
    q = q r + q i ⋅ i + q j ⋅ j + q k ⋅ k R ( q ) = 2 ( 1 2 − ( q j 2 + q k 2 ) ( q i q j − q r q k ) ( q i q k + q r q j ) ( q i q j + q r q k ) 1 2 − ( q i 2 + q k 2 ) ( q j q k − q r q i ) ( q i q k − q r q j ) ( q j q k + q r q i ) 1 2 − ( q i 2 + q j 2 ) ) \begin{gathered}\mathbf{q}=q_r+q_i\cdot i+q_j\cdot j+q_k\cdot k\\\mathbf{R}\left(\mathbf{q}\right)=2\begin{pmatrix}\frac12-\left(q_j^2+q_k^2\right)&(q_iq_j-q_rq_k)&(q_iq_k+q_rq_j)\\(q_iq_j+q_rq_k)&\frac12-\left(q_i^2+q_k^2\right)&(q_jq_k-q_rq_i)\\(q_iq_k-q_rq_j)&(q_jq_k+q_rq_i)&\frac12-\left(q_i^2+q_j^2\right)\end{pmatrix}\end{gathered} q=qr+qii+qjj+qkkR(q)=2 21(qj2+qk2)(qiqj+qrqk)(qiqkqrqj)(qiqjqrqk)21(qi2+qk2)(qjqk+qrqi)(qiqk+qrqj)(qjqkqrqi)21(qi2+qj2)
  • 旋转四元数是一种用于表示三维空间中旋转的数学工具。它是四元数的一种特殊形式,由一个实部和三个虚部组成。

  • 旋转四元数通常表示为q = w + xi + yj + zk,其中w是实部,(x, y, z)是虚部,i、j、k是虚数单位。这里需要满足四元数的数学性质:i² = j² = k² = ijk = -1。

  • 旋转四元数的核心思想是,通过对旋转轴上的旋转角度进行编码,以及通过旋转轴的单位向量来表示旋转的方向。旋转四元数的实部(w)用于表示旋转角度的余弦值,而虚部(x, y, z)则表示旋转轴在单位向量上的三个分量。

  • 放缩矩阵更不需要记录整个矩阵的信息,只需要记录其在三个轴方向的缩放比即可。

综上所述,协方差矩阵的更新转变为更新旋转四元数 q q q和一个含缩放比信息的三维向量 s s s
3dgs推导了 q q q s s s的梯度,节约了自动微分的成本,具体可以参考3dgs原论文附录部分的梯度回传数学推导部分。
在这里插入图片描述

颜色的参数更新

官方代码中更新颜色部分的代码如下:

// Backward pass for conversion of spherical harmonics to RGB for
// each Gaussian.
__device__ void computeColorFromSH(int idx, int deg, int max_coeffs, const glm::vec3* means, glm::vec3 campos, const float* shs, const bool* clamped, const glm::vec3* dL_dcolor, glm::vec3* dL_dmeans, glm::vec3* dL_dshs)
{
	// Compute intermediate values, as it is done during forward
	glm::vec3 pos = means[idx];
	glm::vec3 dir_orig = pos - campos;
	glm::vec3 dir = dir_orig / glm::length(dir_orig);

	glm::vec3* sh = ((glm::vec3*)shs) + idx * max_coeffs;

	// Use PyTorch rule for clamping: if clamping was applied,
	// gradient becomes 0.
	glm::vec3 dL_dRGB = dL_dcolor[idx];
	dL_dRGB.x *= clamped[3 * idx + 0] ? 0 : 1;
	dL_dRGB.y *= clamped[3 * idx + 1] ? 0 : 1;
	dL_dRGB.z *= clamped[3 * idx + 2] ? 0 : 1;

	glm::vec3 dRGBdx(0, 0, 0);
	glm::vec3 dRGBdy(0, 0, 0);
	glm::vec3 dRGBdz(0, 0, 0);
	float x = dir.x;
	float y = dir.y;
	float z = dir.z;

	// Target location for this Gaussian to write SH gradients to
	glm::vec3* dL_dsh = dL_dshs + idx * max_coeffs;

	// No tricks here, just high school-level calculus.
	float dRGBdsh0 = SH_C0;
	dL_dsh[0] = dRGBdsh0 * dL_dRGB;
	if (deg > 0)
	{
		float dRGBdsh1 = -SH_C1 * y;
		float dRGBdsh2 = SH_C1 * z;
		float dRGBdsh3 = -SH_C1 * x;
		dL_dsh[1] = dRGBdsh1 * dL_dRGB;
		dL_dsh[2] = dRGBdsh2 * dL_dRGB;
		dL_dsh[3] = dRGBdsh3 * dL_dRGB;

		dRGBdx = -SH_C1 * sh[3];
		dRGBdy = -SH_C1 * sh[1];
		dRGBdz = SH_C1 * sh[2];

		if (deg > 1)
		{
			float xx = x * x, yy = y * y, zz = z * z;
			float xy = x * y, yz = y * z, xz = x * z;

			float dRGBdsh4 = SH_C2[0] * xy;
			float dRGBdsh5 = SH_C2[1] * yz;
			float dRGBdsh6 = SH_C2[2] * (2.f * zz - xx - yy);
			float dRGBdsh7 = SH_C2[3] * xz;
			float dRGBdsh8 = SH_C2[4] * (xx - yy);
			dL_dsh[4] = dRGBdsh4 * dL_dRGB;
			dL_dsh[5] = dRGBdsh5 * dL_dRGB;
			dL_dsh[6] = dRGBdsh6 * dL_dRGB;
			dL_dsh[7] = dRGBdsh7 * dL_dRGB;
			dL_dsh[8] = dRGBdsh8 * dL_dRGB;

			dRGBdx += SH_C2[0] * y * sh[4] + SH_C2[2] * 2.f * -x * sh[6] + SH_C2[3] * z * sh[7] + SH_C2[4] * 2.f * x * sh[8];
			dRGBdy += SH_C2[0] * x * sh[4] + SH_C2[1] * z * sh[5] + SH_C2[2] * 2.f * -y * sh[6] + SH_C2[4] * 2.f * -y * sh[8];
			dRGBdz += SH_C2[1] * y * sh[5] + SH_C2[2] * 2.f * 2.f * z * sh[6] + SH_C2[3] * x * sh[7];

			if (deg > 2)
			{
				float dRGBdsh9 = SH_C3[0] * y * (3.f * xx - yy);
				float dRGBdsh10 = SH_C3[1] * xy * z;
				float dRGBdsh11 = SH_C3[2] * y * (4.f * zz - xx - yy);
				float dRGBdsh12 = SH_C3[3] * z * (2.f * zz - 3.f * xx - 3.f * yy);
				float dRGBdsh13 = SH_C3[4] * x * (4.f * zz - xx - yy);
				float dRGBdsh14 = SH_C3[5] * z * (xx - yy);
				float dRGBdsh15 = SH_C3[6] * x * (xx - 3.f * yy);
				dL_dsh[9] = dRGBdsh9 * dL_dRGB;
				dL_dsh[10] = dRGBdsh10 * dL_dRGB;
				dL_dsh[11] = dRGBdsh11 * dL_dRGB;
				dL_dsh[12] = dRGBdsh12 * dL_dRGB;
				dL_dsh[13] = dRGBdsh13 * dL_dRGB;
				dL_dsh[14] = dRGBdsh14 * dL_dRGB;
				dL_dsh[15] = dRGBdsh15 * dL_dRGB;

				dRGBdx += (
					SH_C3[0] * sh[9] * 3.f * 2.f * xy +
					SH_C3[1] * sh[10] * yz +
					SH_C3[2] * sh[11] * -2.f * xy +
					SH_C3[3] * sh[12] * -3.f * 2.f * xz +
					SH_C3[4] * sh[13] * (-3.f * xx + 4.f * zz - yy) +
					SH_C3[5] * sh[14] * 2.f * xz +
					SH_C3[6] * sh[15] * 3.f * (xx - yy));

				dRGBdy += (
					SH_C3[0] * sh[9] * 3.f * (xx - yy) +
					SH_C3[1] * sh[10] * xz +
					SH_C3[2] * sh[11] * (-3.f * yy + 4.f * zz - xx) +
					SH_C3[3] * sh[12] * -3.f * 2.f * yz +
					SH_C3[4] * sh[13] * -2.f * xy +
					SH_C3[5] * sh[14] * -2.f * yz +
					SH_C3[6] * sh[15] * -3.f * 2.f * xy);

				dRGBdz += (
					SH_C3[1] * sh[10] * xy +
					SH_C3[2] * sh[11] * 4.f * 2.f * yz +
					SH_C3[3] * sh[12] * 3.f * (2.f * zz - xx - yy) +
					SH_C3[4] * sh[13] * 4.f * 2.f * xz +
					SH_C3[5] * sh[14] * (xx - yy));
			}
		}
	}

	// The view direction is an input to the computation. View direction
	// is influenced by the Gaussian's mean, so SHs gradients
	// must propagate back into 3D position.
	glm::vec3 dL_ddir(glm::dot(dRGBdx, dL_dRGB), glm::dot(dRGBdy, dL_dRGB), glm::dot(dRGBdz, dL_dRGB));

	// Account for normalization of direction
	float3 dL_dmean = dnormvdv(float3{ dir_orig.x, dir_orig.y, dir_orig.z }, float3{ dL_ddir.x, dL_ddir.y, dL_ddir.z });

	// Gradients of loss w.r.t. Gaussian means, but only the portion 
	// that is caused because the mean affects the view-dependent color.
	// Additional mean gradient is accumulated in below methods.
	dL_dmeans[idx] += glm::vec3(dL_dmean.x, dL_dmean.y, dL_dmean.z);
}
  • 输入参数包括:

idx: 代表当前高斯函数的索引;
deg: 指定球谐函数的阶数;
max_coeffs: 球谐函数的系数个数;
means: 存储每个高斯函数的均值向量;
campos: 相机位置;
shs: 存储每个高斯函数的球谐函数系数;
clamped: 存储每个高斯函数是否需要进行截断;
dL_dcolor: 目标颜色对 RGB 颜色空间的导数;
dL_dmeans: 目标颜色对高斯函数均值的导数;
dL_dshs: 目标颜色对球谐函数系数的导数。

  • 该函数主要实现以下过程:

计算相机与当前高斯函数均值之间的方向向量;
根据 PyTorch 规则,如果某个高斯函数需要进行截断,则其梯度为 0;
计算 RGB 颜色空间中的梯度;
计算 RGB 颜色空间中每个分量对坐标轴的偏导数;
根据球谐函数的定义,计算球谐函数系数与 RGB 颜色空间中每个分量之间的导数关系;
根据相机位置和方向向量,计算目标颜色对高斯函数均值的导数;
将高斯函数均值的导数累加到 dL_dmeans 中;

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

【Linux】云服务器的Redis被黑

📝个人主页:五敷有你 🔥系列专栏:Linux ⛺️稳中求进,晒太阳 攻击发现: 这个异常情况是在腾讯云被入侵后,短信提醒发现的。并没有系统的学习过关于服务器安防相关的知识,遇到…

三天学会阿里分布式事务框架Seata-SpringCloud Alibaba分布式基础案例搭建

锋哥原创的分布式事务框架Seata视频教程: 实战阿里分布式事务框架Seata视频教程(无废话,通俗易懂版)_哔哩哔哩_bilibili实战阿里分布式事务框架Seata视频教程(无废话,通俗易懂版)共计10条视频&…

10 在线逻辑分析仪的使用

在线逻辑分析仪简介 传统的 FPGA 板级调试是将逻辑分析仪连接到 FPGA 的 IO 引脚上 ,然后将内部信号引出至 IO 引脚,再进行板级调试,这种方法的缺点是我们需要一个逻辑分析仪,且还要在 PCB 中预留测试点。在线逻辑分析仪克服了以…

配电房轨道式巡检机器人方案

一、应用背景 在变电站、配电房、开关站等各种室内变配电场所内,由于变配电设备的数量众多、可能存在各类安全隐患,为了保证用电的安全可靠,都要进行日常巡检。 但目前配电房人工巡检方式有以下主要问题: 巡检工作量大、成本高 …

三、西瓜书——神经网络

一、神经元模型 在M-P神经网络模型中,神经元接 收到来自n个其他神经元传递过来的输入信号,这些输入信号通过带权重的连接(connection)进行传递,神经元接收到的总输入值将与神经元的阈值进行比较,然后通过“激活函数”(activation …

【数据结构】C语言实现二叉树的相关操作

树 定义 树(Tree)是 n (n > 0) 个结点的有限集 若 n 0,称为空树 若 n > 0,则它满足如下两个条件: 有且仅有一个特定的称为根(Root)的结点其余结点可分为 m(m>0) 个互不相交的有限…

第十三篇【传奇开心果系列】Python的文本和语音相互转换库技术点案例示例:Microsoft Azure的Face API开发人脸识别门禁系统经典案例

传奇开心果博文系列 系列博文目录Python的文本和语音相互转换库技术点案例示例系列 博文目录前言一、实现步骤和雏形示例代码二、扩展思路介绍三、活体检测深度解读和示例代码四、人脸注册和管理示例代码五、实时监控和报警示例代码六、多因素认证示例代码七、访客管理示例代码…

ES6 | (二)ES6 新特性(下) | 尚硅谷Web前端ES6教程

文章目录 📚迭代器🐇定义🐇工作原理🐇自定义遍历数据 📚生成器函数🐇声明和调用🐇生成器函数的参数传递🐇生成器函数案例 📚Promise📚Set🐇Set的定…

AI大预言模型——ChatGPT在地学、GIS、气象、农业、生态、环境应用

原文链接:AI大预言模型——ChatGPT在地学、GIS、气象、农业、生态、环境应用 一开启大模型 1 开启大模型 1)大模型的发展历程与最新功能 2)大模型的强大功能与应用场景 3)国内外经典大模型(ChatGPT、LLaMA、Gemini、DALLE、Midjourney、Stable Diff…

【论文阅读】微纳米气泡技术作为CO2-EOR和CO2地质储存技术的新方向:综述

Micro and nanobubbles technologies as a new horizon for CO2-EOR and CO2 geological storage techniques: A review 微纳米气泡技术作为CO2-EOR和CO2地质储存技术的新方向:综述 期刊信息:Fuel 2023 期刊级别:EI检索 SCI升级版工程技术1区…

解释一下前端框架中的虚拟DOM(virtual DOM)和实际DOM(real DOM)之间的关系。

聚沙成塔每天进步一点点 ⭐ 专栏简介 前端入门之旅:探索Web开发的奇妙世界 欢迎来到前端入门之旅!感兴趣的可以订阅本专栏哦!这个专栏是为那些对Web开发感兴趣、刚刚踏入前端领域的朋友们量身打造的。无论你是完全的新手还是有一些基础的开发…

从win11切换到ubuntu20的第1天

我不想做双系统,反正win11也没有意思,打游戏直接去网吧,所以电脑直接重装了ubuntu20,为什么不是ubuntu22?因为版本太新,很多东西不支持。为什么不装ubuntu18?因为我电脑装完了之后不支持外界显示…

通过大语言模型理解运维故障:评估和总结

张圣林 南开大学软件学院副教授、博士生导师 第六届CCF国际AIOps挑战赛程序委员会主席 在ATC、WWW、VLDB、KDD、SIGMETRICS等国际会议和JSAC、TC、TSC等国际期刊发表高水平论文50余篇。主持国家自然科学基金项目2项,横向项目13项(与华为、字节跳动、腾讯…

华为s5720s-28p-power-li-ac堆叠配置

叠物理约束: • 连线推荐示意图选用产品子系列中固定的一款设备做示例,与选择产品时指定型号的外观可能不同。示意图主要用于让用户了解相同子系列设备可以用作堆叠的端口的位置,以及使用不同的连线方式时如何连接设备上的端口。因此&#xf…

【Micropython教程】点亮第一个LED与流水灯

文章目录 前言MicroPython在线仿真GPIO的工作模式一、有哪些工作模式?1.1 GPIO的详细介绍1.2 GPIO的内部框图输入模式输出部分 一、machine.Pin类1.1 machine.Pin 类的构造对象1.2 machine.Pin 类的方法init方法value方法设置高低电平方法 二、延时函数 三、流水灯总…

2024年2月深度学习的论文推荐

我们这篇文章将推荐2月份发布的10篇深度学习的论文 Beyond A*: Better Planning with Transformers via Search Dynamics Bootstrapping. https://arxiv.org/abs/2402.14083 Searchformer是一个基于Transformer架构的人工智能模型,经过训练可以模拟A星寻路算法&a…

博途V18界面的各变量用途

在编程的时候会用到相关的变量包括: 1.在程序块中新建的“数据块” DB 。 在此建立的 变量数据块,它可以是自建在PLC数据类型的变量类型,也可以是各种标准的数据类型,且在DB数据块中的变量一般为全局变量,在整个项目…

nginx------------缓存功能 (六)

一、http 协议反向代理 (一)反向代理示例:缓存功能 缓存功能可以加速访问,如果没有缓存关闭后端服务器后,图片将无法访问,缓存功能默认关闭,需要开启。 ​ proxy_cache zone_name | off; 默认off #指明调…

[Tomcat] 控制台日志乱码,快速解决

启动tomcat之后,控制台打印的日志中出现了中文乱码的情况 解决方法 找到tomcat下的conf目录下的logging.properties文件,地址一般为:C:\apache-tomcat-9.0.17\conf 将logging.properties打开,将java.util.logging.ConsoleHandler…

向量数据库PGVECTOR,AI浪潮下崛起的新秀!

📢📢📢📣📣📣 哈喽!大家好,我是【IT邦德】,江湖人称jeames007,10余年DBA及大数据工作经验 一位上进心十足的【大数据领域博主】!😜&am…