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

这篇具有很好参考价值的文章主要介绍了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原论文附录部分的梯度回传数学推导部分。
3dgs 优化参数更新,3dgs,3d,学习

颜色的参数更新

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

// 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 中;文章来源地址https://www.toymoban.com/news/detail-838341.html

到了这里,关于3DGS学习(六)—— 参数更新的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • UTAustin最新提出!无相机姿态40秒重建3DGS方法

    作者:Zhiwen Fan | 编辑:3DCV 添加微信:dddvision,备注:3D高斯,拉你入群。文末附行业细分群 标题:InstantSplat: Unbounded Sparse-view Pose-free Gaussian Splatting in 40 Seconds 链接:https://arxiv.org/pdf/2403.20309.pdf 本文介绍了一种名为InstantSplat的高效框架,用于从稀疏无位姿的图像中快速重建

    2024年04月27日
    浏览(36)
  • 球谐函数的一些理解(基于3DGS)+Unity的可视化

    1.背景 读3DGS的相关文章的时候提到了一些球谐函数的概念,有些不理解,结合下面的文章做一些扩展 2.参考链接 球谐函数介绍(Spherical Harmonics) - 知乎 (zhihu.com) 球谐函数一:基础理论 - 知乎 (zhihu.com) 3.细节 这里是整篇文章的最关键的举例子解释,但是由于对极坐标不太了解

    2024年04月08日
    浏览(72)
  • 实验笔记之——Ubuntu20.04配置nvidia以及cuda并测试3DGS与SIBR_viewers

    之前博文测试3DGS的时候一直用服务器进行开发,没有用过笔记本,本博文记录下用笔记本ubuntu20.04配置过程~ 学习笔记之——3D Gaussian Splatting源码解读_3dgs运行代码-CSDN博客 文章浏览阅读3.2k次,点赞34次,收藏62次。高斯模型的初始化,初始化过程中加载或定义了各种相关的

    2024年04月15日
    浏览(43)
  • 3d max省时插件CG MAGIC功能中的材质参数可一键优化!

    渲染的最终结果就是为了让渲染效果更加真实的体现。 对于一些操作上,可能还是费些时间,VRay可以说是在给材质做加法的路上越走越远,透明度、凹凸、反射等等参数细节越做越多。 对于材质参数调节的重要性大家都心里有数的。 VRay材质系统的每一次加法和更加精细的

    2024年02月12日
    浏览(37)
  • 【04-提升模型性能:集成学习与超参数优化】

      在前几篇博文中,我们已经介绍了一些机器学习的基础知识、Scikit-learn的核心工具与技巧,以及如何评估模型性能。本篇博文将重点讲解两个可以显著提升机器学习模型性能的高级策略:集成学习和超参数优化。   集成学习是一种策略,通过组合多个学习算法来获得比

    2024年04月29日
    浏览(39)
  • 【解决(几乎)任何机器学习问题】:超参数优化篇(超详细)

    这篇文章相当长,您可以添加至收藏夹,以便在后续有空时候悠闲地阅读。 有了优秀的模型,就有了优化超参数以获得最佳得分模型的难题。那么,什么是超参数优化呢?假设您的机器学习项⽬有⼀个简单的流程。有⼀个数据集,你直接应⽤⼀个模型,然后得到结 果。模型

    2024年02月21日
    浏览(45)
  • 【深度学习PyTorch入门】6.Optimizing Model Parameters 优化模型参数

    现在我们有了模型和数据,是时候通过优化数据上的参数来训练、验证和测试我们的模型了。训练模型是一个迭代过程;在每次迭代中,模型都会对输出进行猜测,计算其猜测中的误差( 损失 ),收集相对于其参数的导数的误差(如我们在上一节中看到的),并使用梯度下

    2024年01月24日
    浏览(61)
  • optuna,一个好用的Python机器学习自动化超参数优化库

    🏷️ 个人主页 :鼠鼠我捏,要死了捏的主页  🏷️ 付费专栏 :Python专栏 🏷️ 个人学习笔记,若有缺误,欢迎评论区指正   超参数优化是机器学习中的重要问题,它涉及在训练模型时选择最优的超参数组合,以提高模型的性能和泛化能力。Optuna是一个用于自动化超参数优

    2024年02月20日
    浏览(49)
  • 学习笔记:C++环境下OpenCV的findContours函数的参数详解及优化

    这个是Visual Studio2019版本在OpenCV环境配置好后所显示的 6个参数 ,也即为全部参数 但是, 常用参数仅有四个 (参见程序里的第二行注释)  参数1    image  : 单通道图像矩阵。待提取轮廓的图像,可以是灰度图, 常用的是二值图 (C++中可选择使用Canny,拉普拉斯等边缘检测算法

    2024年02月07日
    浏览(40)
  • 探索人工智能 | 模型训练 使用算法和数据对机器学习模型进行参数调整和优化

    模型训练是指 使用算法和数据对机器学习模型进行参数调整和优化 的过程。模型训练一般包含以下步骤:数据收集、数据预处理、模型选择、模型训练、模型评估、超参数调优、模型部署、持续优化。 数据收集是指为机器学习或数据分析任务收集和获取用于训练或分析的数

    2024年02月12日
    浏览(59)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包