【三维重建】SpotlessSplats:去除瞬态干扰物的三维高斯喷溅(3DGS)

在这里插入图片描述

代码:https://spotlesssplats.github.io
论文:https://arxiv.org/pdf/2406.20055
来源:DeepMind,多伦多大学,斯坦福大学,西蒙弗雷泽大学


提示:关注B站【方矩实验室】,查看视频讲解

文章目录

  • 摘要
  • 一、前言
  • 二、相关工作
    • 2.1 NeRF的鲁棒性
    • 2.2 Precomputed features
    • 2.3 Robustness in 3DGS
  • 三、Background
    • 3.1 3DGS的鲁棒优化
  • 四、method
    • 4.1 识别干扰物(distractors)
      • 4.1.1 空间聚类(Spatial clustering)
      • 4.1.2 时空聚类(Spatio-temporal clustering)
    • 4.2 3DGS的鲁棒性优化
      • 4.2.1 计划采样来进行预热(Warm up with scheduled sampling)
      • 4.2.2 基于图像的训练中的 Trimmed estimators(裁剪估计器)
      • 4.2.3 对“重置不透明度”的替代
      • 4.2.4 Appearance modeling (外观建模)
  • 五、实验结果
    • 5.1 无干扰物的三维重建
    • 5.2 基于利用率的剪枝的效果
    • 5.3 Ablation study
  • 六、代码讲解
  • 额外知识
    • 1.层次聚类(Agglomerative clustering)
    • 2.Lipschitz constant(普希茨常数)


摘要

三维高斯喷溅(3DGS)是一种最新的三维重建技术,提供了高效的训练和渲染速度,使其适用于实时应用。然而,目前的方法需要高度控制的环境——没有移动的人或风吹的元素,以及一致的照明——以满足3DGS的视图间一致性假设。这使得重建现实世界的捕获成为问题。我们提出了无斑点斑图,一种利用预训练和通用特征结合鲁棒优化来有效地忽略瞬态干扰物的方法。我们的方法实现了最先进的重建质量。

一、前言

  利用神经辐射场(NeRF)和最近的三维高斯喷溅(3DGS)从二维图像中重建三维场景一直是视觉研究的热点。目前的大多数方法都假设图像同时捕获,完美pose,无噪声。这简化了3D重建任务,但在现实世界中很少存在,移动物体(如人或宠物)、照明变化和其他虚假的光度不一致性会降低性能,限制了应用。

  在NeRF训练中,通过基于颜色残差的大小来降低加权或丢弃不一致的观察值,已经纳入了对异常值的鲁棒性。对于3DGS,自适应稠密化引入了颜色残差的variance,当直接应用来自健壮NeRF框架的现有思想时,影响这些瞬态的检测。

  SpotlessSplats(SLS),一个用于3DGS的三维场景重建框架,通过无监督检测训练图像中的异常值。我们没有在RGB空间中检测异常值,而是 利用了 text-to-image 模型中更丰富、学习到的特征空间。该特征嵌入的有意义的语义结构,更容易检测结构化干扰物的spatial support ,例如,与单个对象相关联。我们没有使用手动指定的鲁棒kernels 来进行异常值识别[40],而是利用特征空间中的自适应方法来检测异常值 。为此目的,我们在这个框架内考虑了两种方法 第一种方法是使用局部特征嵌入的非参数化聚类,来寻找结构化异常值的图像区域第二种方法使用MLP,以无监督的方式训练来预测特征空间中可能与干扰物相关的部分进一步引入了一种(互补的和通用的)稀疏化策略,与鲁棒优化兼容,提供类似的重建质量,减少2到4倍的飞溅量 ,即使在无干扰的数据集上,显著节省计算和内存。通过对随机捕获的场景[37,40]的具有挑战性的基准的实验,SLS在重建精度方面始终优于竞争方法。

  1. 一种自适应的、鲁棒的损失,利用 text-to-image的扩散特征,可靠地识别正常的捕获中的瞬态干扰物,消除了对光度误差的过拟合问题。
  2. 一种新的稀疏化方法与我们的鲁棒损失兼容,显著减少了高斯数量,在不损失保真度的情况下节省了计算和内存

二、相关工作

  神经辐射场(NeRF),由于其高质量的重建和新颖的三维场景视图合成而得到了广泛的关注。NeRF将场景表示为与视图相关的发射体。体渲染方程]的吸收-发射部分渲染。随后又进行了多次增强。快速训练和推理[8,28,46,54]、有限或单视图(s) [15,35,55]训练和同时姿态推理[20,22,50]使辐射场更接近实际应用。最近,3D高斯溅射(3DGS)[17]被提出作为一种基于原始的替代nerf,具有显著更快的渲染速度,同时保持高质量。三维高斯分布可以有效地栅格化使用阿尔法混合[59]。这种简化的表示利用了现代GPU硬件来促进实时渲染。3DGS的效率和简单性促使了该领域内的焦点转移,许多NeRF增强被快速移植到3DGS

2.1 NeRF的鲁棒性

  最初的NeRF论文对捕获设置做出了强有力的假设:场景需要是完全静态的,并且在整个捕获过程中照明应该保持不变。最近 ,NeRF已经扩展到对违反这些约束的非结构化“in the wild”捕获图像进行训练。两项有影响力的工作,NeRF-W [25]和RobustNeRF [40]解决了瞬态干扰物的问题,都使用光度误差作为指导。NeRF-W [25]建模了一个三维不确定性场渲染到二维异常掩模,降低了高误差像素的损失,以及一个防止退化解的正则化器。NeRF-W [25]还通过学习到的嵌入来建模全局外观,这对于在广泛变化的光照和大气条件下捕获的图像很有用。城市辐射场(URF)[36]和Block-NeRF [47]同样将学习到的外观嵌入应用于大规模重建。HA-NeRF [7]和Cross-Ray[53]模型的2D离群值掩模,而不是3D场,利用CNN或Transformer进行交叉射线相关。

  RobustNeRF [40]从鲁棒估计的角度来处理这个问题,使用二值权值由阈值渲染误差确定,并使用模糊核来反映属于干扰物的像素是空间相关的假设。然而,RobustNeRF和NeRF-W变体[7,53]都完全依赖于RGB残差,因此,它们经常用与背景相似的颜色错误地分类瞬态数据;参见图2中的稳健性mask。为了避免这种情况,以前的方法需要仔细调整超参数,即RobustNeRF中的模糊核大小和阈值,以及NeRF-W中的正则化器权重。相反,我们的方法使用文本到图像模型的丰富表示来进行语义离群值建模。这避免了直接的RGB错误监督,因为它依赖于特征空间的相似性来进行聚类。

在这里插入图片描述

  最近的NeRF On-the-go[37]发布了一个随意捕获的视频数据集。与我们的方法类似,它使用DINOv2 [31]的语义语义特征通过一个小MLP预测离群mask。然而,它也依赖于 structural rendering error的直接监督,导致超出或分割不足;参见图3。NeRF-HuGS [6]结合了来自COLMAP的鲁棒稀疏点云[43]的启发式方法,以及现成的语义分割来去除干扰物。这两种启发式方法在[37]数据集的严重瞬态occlusions下都失败了。

2.2 Precomputed features

  使用强大的预计算的视觉特征,如DINO [4,31],已经证明了推广到多个视觉任务的能力。DDPM扩散模型[13,39,45]因其从文本提示[30,34,38,41]中获得的逼真图像生成能力而引起了人们的关注。这些模型的内部特征已被证明是同样强大的,并能够推广到许多领域,如分割和关键点配准。

2.3 Robustness in 3DGS

  多个工作解决了对野外捕获数据的3DGS训练。SWAG [10]和GS-W [57]模型外观变化使用学习的全局和局部每个原型外观嵌入。类似地,WE-GS [49]使用一个图像编码器来学习对每个图像的颜色参数的适应。Wild-GS [52]学习了一个用于外观嵌入的空间三平面场。所有这些方法[49,52,57]都采用了像NeRFW [25]这样的干扰物的mask预测方法,通过预测二维干扰物mask来降低高误差渲染像素的权重。SWAG [10]学习每个高斯分布的每幅图像的不透明度,并将具有高不透明度方差的原型表示为瞬态。值得注意的是SWAG [10]和GS-W[57],当将额外的学习瞬态掩模应用于Phototourism scenes场景[44]时,它们比本地/全局外观建模没有或几乎没有改进。SLS专注于具有较长时间瞬变和最小外观变化的临时捕获,这在视频捕获中很常见,如数据集[37]。

三、Background

  三维高斯溅射(3DGS)将三维场景表示为三维各向异性高斯 G = G= G={ g i g_i gi}的集合。每个splat g i g_i gi,由一个均值 µ i µ_i µi,一个正半定协方差矩阵 Σ i Σ_i Σi,一个不透明度 α i α_i αi,并由球谐系数 c i c_i ci参数化。

  3D场景表示通过栅格化呈现到屏幕空间。我们表示W为透视变换矩阵,三维协方差的投影二维屏幕空间可以近似为: Σ ~ = J W Σ W T J T \tilde{Σ}=JWΣW^TJ^T Σ~=JWΣWTJT,J是投影矩阵的雅可比矩阵,它提供了一个用线性近似非线性投影的过程。

  为了确保Σ在整个优化过程中表示协方差(即正半定),协方差矩阵参数化为 Σ = R S S T R T Σ=RSS^TR^T Σ=RSSTRT,其中尺度S=diag (s)与s∈R3,旋转R从一个单位四元数q计算。一旦计算了屏幕空间中的分割位置和协方差,图像形成过程执行体积渲染作为alpapha混合,这反过来需要沿视图方向排序。请注意,与NeRF每次渲染一个像素不同,3DSG以一次向前传递的方式渲染整个图像。

  

3.1 3DGS的鲁棒优化

  与之前的作品[18,26,47]不同,我们没有对瞬态对象类、外观和/或形状进行假设。

  我们通过借鉴RobustNeRF来解决这个问题,通过识别输入图像中应该被mask的部分来消除干扰物。该问题简化为预测(无监督)每个训练图像的内部/外部点的maks { M n M_n Mn} n = 1 N ^N_{n=1} n=1N,并通过mask L1损失来优化模型:

在这里插入图片描述

  其中 I ^ n ( t ) \hat{I}^{(t)}_n I^n(t) 是在训练迭代(t)时的渲染结果。RobustNeRF 通过观察训练过程中的光度不一致来检测瞬态效应;即,具有大的损失值的图像区域。通过用 R n ( t ) = I n − I ^ n ( t ) R^{(t)}_n =I_n - \hat{I}^{(t)}_n Rn(t)=InI^n(t) 表示残差的图像(轻微滥用符号,因为1范数是沿颜色通道像素执行的),mask计算为:

在这里插入图片描述

  其中 1 1 1是一个指示函数(为真则返回1,否则为0),ρ是一个广义中位数,τ是一个超参数,控制cut-off percentile;B是一个(标准化)3×3box 滤波器,通过卷积(~)执行 a morphological dilation。直观地说,上面(2)总结的RobustNeRF [40]通过假设内部值/异常值是空间相关的,扩展了trimmed robust estimator[9]。我们发现,直接将[40]的想法应用到3DGS中,即使不受如图2中所示的误导性颜色残余情况的限制,也不能有效地去除异常值。相反,为了适应3DGS的表现和训练过程中的差异,需要进行一些调整(4.2节);

四、method

  以上方法中的干扰物mask 是基于新视图的光度误差而建立的。相反,我们建议根据干扰物的语义来识别它们,在训练过程中,识别其的再次出现。我们把语义看作是从一个自监督的二维基础模型(如[48])计算出来的特征映射。从训练图像中去除干扰物的过程,转化为识别可能导致大光度误差的特征子空间的过程。举个例子,一只狗在静态场景中散步。要么在每张图像(4.1.1节),要么或更广泛地说,在数据集中(4.1.2节)中识别“狗”的像素(可能是重建中出现问题的原因),并自动从优化中删除它们。SpotlessSplats旨在减少对局部颜色残差的离群值检测和对颜色误差的过拟合,而强调依赖像素之间的语义特征相似性,也称为“clustering”。

4.1 识别干扰物(distractors)

  给定输入图像{ I n I_n In} n = 1 N ^N_{n=1} n=1N,使用 Stable Diffusion提取特征图{ F n F_n Fn} n = 1 N ^N_{n=1} n=1N。这个预处理步骤在训练开始之前执行一次,使用其计算 inlier/outlier masks M ( t ) M^{(t)} M(t);我们删除图像索引n以简化符号,因为训练过程涉及每批一个图像。现在详细介绍检测outliers 的两种不同的方法:

4.1.1 空间聚类(Spatial clustering)

  预处理阶段,额外对图像区域进行无监督聚类。与超像素技术[14,21]类似,我们将图像过度分割成C个空间连接组件的固定基数集合;参见“聚类特征”图2。具体说,在特征图 F F F上执行层次聚类[2011年],其中每个像素都连接到它周围的8个像素。将像素p分配给聚类c表示为 C [ c , p ] C[c,p] C[c,p]∈{ 0 , 1 0,1 0,1},并将聚类初始化为每个像素其自身聚类。融合簇间特征方差最少的集群(collapsing those that cause the least amount of inter-cluster feature variance differential before/post collapse)。当C=100集群仍然存在时,集群将终止( Clustering terminates when C=100 clusters remain)。

  然后,从公式(2)的mask内部像素的百分比,计算出簇c是一个内部像素的概率:
在这里插入图片描述

  然后将簇标签传播回像素:

在这里插入图片描述

使用 M a g g ( t ) M^{(t)}_{agg} Magg(t),而不是 M ( t ) M^{(t)} M(t),作为 inlier/outlier的mask来训练(1)中的3DGS模型。这个模型配置指定为“SLS-agg

4.1.2 时空聚类(Spatio-temporal clustering)

  第二种方法是训练一个分类器,根据像素的相关特征来决定像素是否应该被(1)优化。为此,我们使用一个带有参数θ的MLP,从像素特征中预测每个像素的inlier概率:

在这里插入图片描述

  分类器参数 θ ( t ) θ^{(t)} θ(t)与3DGS优化同时更新。H用1×1卷积实现,MLP和3DGS交替优化。MLP分类器损失为:
在这里插入图片描述

在这里插入图片描述
λ=0.5,U和L是由当前残差的mask计算出的自监督标签:

在这里插入图片描述

  换句话说,我们只在像素上直接监督分类器,这样我们就可以根据重构残差来确定 inlier
status,否则我们就严重依赖于特征空间中的语义相似性;见图4。为了进一步正则化H,将相似的特征映射到相似的概率,我们通过 L r e g L_{reg} Lreg最小化它的 Lipschitz constant[文献23]。

在这里插入图片描述

  然后使用 M m l p ( t ) M^{(t)}_{mlp} Mmlp(t),而不是 M ( t ) M^{(t)} M(t),作为 inlier/outlier的mask来训练(1)中的3个DGS。我们将此模型配置指定为“SLS-mlp”

4.2 3DGS的鲁棒性优化

  直接将任何鲁棒的mask 技术应用于3DGS,会导致mask 过拟合到一个过早的3DGS模型(见4.2.1节),比如基于图像的训练(4.2.2节),或3DGS的密集化策略(见4.2.3节)使得inlier estimator产生偏差。下面我们提出了解决方案。

4.2.1 计划采样来进行预热(Warm up with scheduled sampling)

  逐步应用mask很重要,因为初始残差是随机的。如果我们使用学习到的聚类来mask,这是双重正确的,因为MLP在优化的早期不会收敛,并随机预测mask。此外,直接使用 outlier mask 往往导致 quickly overcommit to outliers,防止有价值的错误的反向传播,并从这些区域学习。我们通过将每个像素的mask策略,制定为基于mask的伯努利分布的采样来缓解这种情况:

在这里插入图片描述

  其中,α是一个阶梯指数调度器( staircase exponential scheduler),从1到0,提供了一个热身。这使得我们仍然可以在我们不确定的区域中稀疏地采样梯度,从而可以更好地分类离群值。

  

4.2.2 基于图像的训练中的 Trimmed estimators(裁剪估计器)

  [40]实现了一个修剪后的估计器,其基本的假设是每个minibatch(平均)包含相同比例的异常值。这个假设在3DGS训练运行中被打破了,其中每个minibatch都是一个完整的图像,而不是从训练图像集中随机抽取的一个像素集。这给实现(2)的广义中值带来了挑战,因为异常值的分布在图像之间是有偏颇的

  我们通过跟踪多个训练批次上的残差量级来解决:将残差的magnitudes离散为B个直方图buckets,宽度等于渲染误差的下界( 1 0 − 3 10^{−3} 103)。我们通过对bucket population的有折扣的更新,来升级每次迭代中每个bucket的似然,类似于快速中值滤波方法[32]。这保持了残差分布的移动估计,内存消耗不变,从中我们可以提取出广义中值 ρ ρ ρ作为直方图总体中的 τ τ τ 分位数

4.2.3 对“重置不透明度”的替代

  原始GS每M次迭代,会重置所有高斯分布的不透明度opacity reset处理两个问题:首先,在具有挑战性的数据集中,在相机附近的优化容易积累高斯分布,常被称为floater。这很难处理,因为它迫使相机光线尽早饱和于透光率,因此梯度没有机会流通到场景的遮挡部分。opacity reset降低了所有高斯分布的不透明度,这样梯度就可以沿着整个射线再次流动第二,opacity reset控制高斯数量。将不透明度重置为一个低值,允许(永远无法恢复到更高不透明度的GS)通过自适应密度控制机制进行修剪。

  然而,opacity reset干扰了残差分布跟踪,导致残影在opacity reset 后的迭代中变大。简单的禁用并不能work,因为是优化必须的。根据文献[11], 我们采用基于利用率的修剪(UBP:utilization-based pruning)我们跟踪渲染的颜色相对于每个高斯 g g g的投影位置 x g x_g xg的梯度 。与3D位置相比,计算关于投影位置的导数,允许一个更少的内存密集型的GPU实现,同时提供了一个与[Bayes’ Rays: Uncertainty quantification in neural radiance fields. CVPR, 2024]中类似的度量。其中,利用率 utilization定义为:

在这里插入图片描述

  我们在图像全局 (W×H)来平均该指标,在前一组 ∣ N T ( t ) ∣ = 100 |N_T(t)|=100 NT(t)=100张图像中,每100步计算一次。当 u g < κ u_g<κ ug<κ, with κ = 1 0 − 8 κ = 10^{−8} κ=108时,裁剪高斯。基于利用率的剪枝替换opacity reset,实现了两个原始目标,同时减轻了对残差分布跟踪的干扰。基于利用率的剪枝通过使用更少的高斯原型显著地压缩了场景表示,同时即使在无离群值的场景中也能实现高重建质量;参见第5.2节。它还能有效地处理floater(见图10)。floater的利用率很低,因为他们参与渲染很少的视图。此外,使用(11)中所示的masked derivatives, 可以去除在 warm-up阶段的 any splat that has leaked through the robust mask。

4.2.4 Appearance modeling (外观建模)

.
  原始GS假设场景的图像(包括干扰物)在光度上是完全一致的,无法应用于自动曝光和白平衡。SpotlessSplats结合文献[36]的方案,适用于文献[17]的球谐表示的视图依赖的颜色。详细的,共同优化了每个输入摄像机视图的latent z n ∈ R 64 z_n∈R^{64} znR64,并通过MLP将其映射到作用于谐波系数 c c c 的线性变换:

在这里插入图片描述

  其中 ⚪ 是 Hadamard 乘积(矩阵的逐元素相乘),b模型改变了图像的亮度,a提供了表达能力来补偿白平衡。在优化过程中,可训练的参数还包括 θ Q θ_Q θQ和{ z n z_n zn}。这种简化的模型可以有效地防止 z n z_n zn在按图像调整时过度解释干扰物,就像在一个更简单的GLO [NeRF in the Wild]中发生的那样;参见Rematas等人的[ Urban Radiance Fields ]进行分析。

  

  

五、实验结果

  数据集。我们在随机捕获的 RobustNeRF [40] 和 NeRF on-the-go[37]数据集上评估。RobustNeRF数据集包括四个充满干扰和无干扰训练分割的场景。 ‘Crab’ 和 ‘Yoda’场景具有不同的干扰物,不是在一个休闲视频中捕获的。NeRF on-the-go数据集有6个场景,有三个水平的瞬态干扰物遮挡(低、中、高)和一个单独的干净测试集用于定量比较。

  基线。三维高斯喷射方法尚未广泛解决无干扰物重建的问题。现有方法主要关注全局外观变化,如亮度变化[10,19,49],而不是关注为此任务策划的随机捕获数据集。此外,这些方法还没有公开可用的源代码。因此,我们与普通的3DGS方法和稳健的NeRF方法进行了比较。我们比较了最先进的NeRF方法,NeRFon-go[37],NeRF-hugs[6]和RobustNeRF[40],MipNeRF-360

  指标。PSNR、SSIM和LPIPS的重建指标(LPIPS指标使用标准化的VGG特征)。NeRF-HuGS [6]报告来自AlexNet特性的LPIPS指标;为了公平比较,我们计算并报告其发布的VGG LPIPS指标。

  实施细节。模型都经过了30k次迭代的训练。我们关闭不透明度重置,在第8000步,只重置非扩散球谐系数到0.001。这确保了在MLP训练的早期阶段泄露的任何干扰物都不会被建模为视图依赖效应。我们每500步到15000步,每100步运行UBP。对于MLP训练,我们使用具有0.001学习率的Adam优化器。我们从SD v2.1的第2个上采样层计算图像特征,去噪时间步长为261,和一个空提示符中计算图像特征。Tang等人[48]发现这种配置对分割和关键点匹配任务最有效。我们将degree 20的位置编码拼接作为MLP的输入。

5.1 无干扰物的三维重建

  RobustNeRF [40] 和 NeRF on-the-go评估我们的方法。在图5定量地显示了SLS-mlp在RobustNeRF数据集上优于所有稳健的基于nerf的基线。对原始3DGS的改进,性能更接近理想的干净模型,特别是在“Yoda”和“Android”上。定性结果表明,原始3DGS试图将干扰物建模为noisy的floater((‘Yoda’, ‘Statue’))或视角依赖效应(“Android”)或两者的混合物(“Crab”)。NeRF-HuGS [6]使用基于分割的掩模显示s signs of over masking(去除四个场景中的静态部分),或under-mask in challenging sparsely sampled views letting in transient objects(“Crab”)。

  图3和图6中,对NeRF on-the-go数据集进行了类似的分析。对于低遮挡场景,来自COLMAP [42]点云的原始3DGS的鲁棒初始化,特别是RANSAC对异常值的拒绝,足以产生良好的重建质量。然而,随着干扰物密度的增加,3DGS重建质量下降,定性结果显示干扰物瞬态泄漏。此外,定性结果显示,NeRF在工作时没有去除训练早期阶段的一些干扰物((‘Patio’, ‘Corner’, ‘mountain’ and ‘Spot’),这显示出与渲染错误过拟合的进一步迹象。这也可以看到在细节的over-masking(‘Patio High’)或更大的结构(“喷泉”)被完全去除。

在这里插入图片描述

在这里插入图片描述

5.2 基于利用率的剪枝的效果

  在我们所有的实验中,使我们提出的基于利用的修剪(UBP)(Sec。4.2.3),将高斯数从4×减少到6×。这种压缩意味着启用UBP的训练时间至少减少了2×,在推理期间减少了3×。图10显示,启用UBP可能会略微降低定量测量值,但在实际应用中,最终的渲染效果更干净,漂浮物更少(例如,图像的左下角)。类似的观察结果表明,PSNR和LPIPS等指标可能不能像渲染的视频那样清晰地完全反映飞蚊群的存在。考虑到高斯数的大幅减少,我们提出UBP作为一种适用于杂乱和干净的数据集的压缩技术。图7显示,在干净的MipNeRF360 [2]数据集上,使用UBP而不是不透明度重置,在保持渲染质量的同时,将高斯数从2×减少到4.5×

5.3 Ablation study

  在图8中,我们比较了SLS的性能与其他健壮的掩蔽技术的进展。该进展始于简单地应用一个鲁棒过滤器(2),然后应用SLS-agg,最后在SLS-mlp中使用MLP。我们证明了SLS-agg和SLS-mlp都能够有效地从重建的场景中去除干扰物,同时保持对场景的最大覆盖范围。此外,在图9和图10中,我们减少了我们在架构设计和第4.2节中提出的调整中的选择。图9显示,使用一个MLP而不是一个小的CNN(都大约有30K参数,和两个非线性激活)可以更好地适应微妙的瞬变,如阴影。选择正则化器权重的λ似乎没有什么影响。在凝聚聚类中,更多的聚类通常会得到更好的结果,在100个聚类后收益减少。图10进一步说明了UBP在去除泄漏的干扰物方面的有效性。我们的其他适应能力,GLO,热身阶段和伯努利抽样都显示出了改进。

在这里插入图片描述

六、代码讲解

# 1.渲染图像-------------------------------------------------------------------
renders, alphas, info = self.rasterize_splats(camtoworlds=camtoworlds,Ks=Ks,width=width,height=height,sh_degree=sh_degree_to_use,near_plane=cfg.near_plane,far_plane=cfg.far_plane,image_ids=image_ids,render_mode="RGB+ED" if cfg.depth_loss else "RGB",
)
colors, depths = renders[..., 0:3], renders[..., 3:4]
# 2.robust loss(loss_type)---------------------------------------------------
error_per_pixel = torch.abs(colors - pixels)           # torch.Size(1, 377, 503, 3)
pred_mask = self.robust_mask( error_per_pixel, self.running_stats["avg_err"]=1)                                                      
# 像素误差小于阈值,或邻居中至少一个误差小于阈值,则为1,否则为 0。具体代码为:def robust_mask(self, error_per_pixel: torch.Tensor, loss_threshold: float) -> torch.Tensor:epsilon = 1e-3error_per_pixel = error_per_pixel.mean(axis=-1, keepdims=True)error_per_pixel = error_per_pixel.squeeze(-1).unsqueeze(0)is_inlier_pixel = (error_per_pixel < loss_threshold).float()window_size = 3channel = 1window = torch.ones((1, 1, window_size, window_size), dtype=torch.float) / (window_size * window_size)                                                                                # 每个像素是否有至少一个邻居,误差小于阈值if error_per_pixel.is_cuda:window = window.cuda(error_per_pixel.get_device())window = window.type_as(error_per_pixel)has_inlier_neighbors = F.conv2d(is_inlier_pixel, window, padding=window_size // 2, groups=channel)has_inlier_neighbors = (has_inlier_neighbors > 0.5).float()is_inlier_pixel = ((has_inlier_neighbors + is_inlier_pixel) > epsilon).float()pred_mask = is_inlier_pixel.squeeze(0).unsqueeze(-1)  return pred_mask if cfg.semantics:sf = data["semantics"].to(device)                  # (1,1280,50,50)sf = nn.Upsample(size=(colors.shape[1], colors.shape[2]),mode="bilinear",
)(sf).squeeze(0)                               # # (1,1280,377, 503)pos_enc = get_positional_encodings(colors.shape[1], colors.shape[2], 20
).permute((2, 0, 1))                           # torch.Size([80, 377, 503])sf = torch.cat([sf, pos_enc], dim=0)           # (1,1360, 377, 503)
sf_flat = sf.reshape(sf.shape[0], -1).permute((1, 0))    # (189631, 1360)
self.spotless_module.eval()
pred_mask_up = self.spotless_module(sf_flat)   # MLP+sigmoid(1360->1)
pred_mask = pred_mask_up.reshape(1, colors.shape[1], colors.shape[2], 1
)                                              # torch.Size([1, 377, 503, 1])# 计算 lower and upper bound masks for spotless mlp loss
lower_mask = self.robust_mask(error_per_pixel, self.running_stats["lower_err"]
)
upper_mask = self.robust_mask(error_per_pixel, self.running_stats["upper_err"]
)alpha = np.exp(cfg.schedule_beta * np.floor((1 + step) / 1.5))   # alpha 值在01之间变化,表示当前训练的"温度",用于控制后续的随机采样过程
pred_mask = torch.bernoulli( torch.clip(alpha + (1 - alpha) * pred_mask.clone().detach(),min=0.0, max=1.0, ))rgbloss = (pred_mask.clone().detach() * error_per_pixel).mean()
ssimloss = 1.0 - self.ssim(pixels.permute(0, 3, 1, 2), colors.permute(0, 3, 1, 2))
loss = rgbloss * (1.0 - cfg.ssim_lambda) + ssimloss * cfg.ssim_lambdaif self.mlp_spotless:self.spotless_module.train()spot_loss = self.spotless_loss(pred_mask_up.flatten(), upper_mask.flatten(), lower_mask.flatten())reg = 0.5 * self.spotless_module.get_regularizer()spot_loss = spot_loss + regspot_loss.backward()
# 3.update_running_stats(info)        #----------------------cfg = self.cfg# normalize grads to [-1, 1] screen spaceif cfg.absgrad:grads = info["means2d"].absgrad.clone()else:grads = info["means2d"].grad.clone()grads[..., 0] *= info["width"] / 2.0 * cfg.batch_sizegrads[..., 1] *= info["height"] / 2.0 * cfg.batch_sizeself.running_stats["hist_err"] = (0.95 * self.running_stats["hist_err"] + info["err"])mid_err = torch.sum(self.running_stats["hist_err"]) * cfg.robust_percentileself.running_stats["avg_err"] = torch.linspace(0, 1, cfg.bin_size + 1)[torch.where(torch.cumsum(self.running_stats["hist_err"], 0) >= mid_err)[0][0]]lower_err = torch.sum(self.running_stats["hist_err"]) * cfg.lower_boundupper_err = torch.sum(self.running_stats["hist_err"]) * cfg.upper_boundself.running_stats["lower_err"] = torch.linspace(0, 1, cfg.bin_size + 1)[torch.where(torch.cumsum(self.running_stats["hist_err"], 0) >= lower_err)[0][0]]self.running_stats["upper_err"] = torch.linspace(0, 1, cfg.bin_size + 1)[torch.where(torch.cumsum(self.running_stats["hist_err"], 0) >= upper_err)[0][0]]
# 如果iter大于500且为100倍数 step > cfg.refine_start_iter and step % cfg.refine_every == 0
grads = self.running_stats["grad2d"] / self.running_stats["count"].clamp_min(1)# 4.grow GSs------------------------------------------------------------------is_grad_high = grads >= cfg.grow_grad2d                     # "高梯度" GS:2D梯度是否大于等于阈值cfg.grow_grad2dis_small = (torch.exp(self.splats["scales"]).max(dim=-1).values<= cfg.grow_scale3d * self.scene_scale )            # 0.01*1.77                                    # "小尺度" GS:3D尺度self.splats["scales"] 是否小于cfg.grow_scale3d * self.scene_scaleis_dupli = is_grad_high & is_small                          # 同时满足             n_dupli = is_dupli.sum().item()self.refine_duplicate(is_dupli)                             # 对is_dupli标记的GS进行复制扩大,包括复制参数、优化器状态以及一些统计量is_split = is_grad_high & ~is_smallis_split = torch.cat([is_split,# new GSs added by duplication will not be splittorch.zeros(n_dupli, device=device, dtype=torch.bool),])n_split = is_split.sum().item()                              # 计算那些点要splitself.refine_split(is_split)                                  # 复制了原有GS,并基于原有GS的quad和scale随机扰动生成新的GSprint(f"Step {step}: {n_dupli} GSs duplicated, {n_split} GSs split. "f"Now having {len(self.splats['means3d'])} GSs.")# 4.prune GSs-------------------------------------------------------------is_prune = torch.sigmoid(self.splats["opacities"]) < cfg.prune_opa     # 0.0005
# 5. optimize
for optimizer in self.optimizers:optimizer.step()optimizer.zero_grad(set_to_none=True)
for optimizer in self.pose_optimizers:optimizer.step()optimizer.zero_grad(set_to_none=True)
for optimizer in self.app_optimizers:optimizer.step()optimizer.zero_grad(set_to_none=True)
for optimizer in self.spotless_optimizers:optimizer.step()optimizer.zero_grad(set_to_none=True)
for scheduler in schedulers:scheduler.step()# 5.Save the mask image
# 保存模型权重 checkpoint
if step in [i - 1 for i in cfg.save_steps] or step == max_steps - 1:      # 在设置的7000或者30k保存一次mem = torch.cuda.max_memory_allocated() / 1024**3                     # 占GPU 4.9GBstats = {"mem": mem,"ellapsed_time": time.time() - global_tic,"num_GS": len(self.splats["means3d"]),}with open(f"{self.stats_dir}/train_step{step:04d}.json", "w") as f:json.dump(stats, f)torch.save({"step": step,"splats": self.splats.state_dict(),},  f"{self.ckpt_dir}/ckpt_{step}.pt")# self.splats.state_dict()共包含5部分:'means3d', 'opacities', 'quats', 'scales', 'sh0', 'shN'
维度分别为(N3)(N1)(N,4)(N,3)(N,1,3(n,15,3)
 
 

  







d \sqrt{d} d 1 8 \frac {1}{8} 81 x ˉ \bar{x} xˉ x ^ \hat{x} x^ x ~ \tilde{x} x~ ϵ \epsilon ϵ
ϕ \phi ϕ


额外知识

1.层次聚类(Agglomerative clustering)

  层次聚类顾名思义就是按照某个层次对样本集进行聚类操作,这里的层次实际上指的就是某种距离定义。
  层次聚类最终的目的是消减类别的数量,所以在行为上类似于树状图由叶节点逐步向根节点靠近的过程,这种行为过程又被称为“自底向上”。
  更通俗的,层次聚类是将初始化的多个类簇看做树节点,每一步迭代,都是将两两相近的类簇合并成一个新的大类簇,如此反复,直至最终只剩一个类簇(根节点)。
  与层次聚类相反的是分裂聚类(divisive clustering),又名 DIANA(Divise Analysis),它的行为过程为“自顶向下”。

在这里插入图片描述

  聚类过程:

1.数据准备;
2.计算数据集中各样本之间的距离(相似度信息);
3.使用 连接函数(linkage function)将样本进行分组形成层次聚类数(分组依据是上一步计算出来的距离信息),距离相近的样本会被链接在一起;
4.决定在什么地方将层次聚类树截断成多个聚类。
  

  


2.Lipschitz constant(普希茨常数)

对抗样本:在分类器中,引起错误预测的不可察觉的扰动输入。

在这里插入图片描述

一、用Lipschitz常量来度量和控制网络的不稳定性
二、Lipschitz常量与网络鲁棒的关系,从而加强型的鲁棒性
三、平衡网络的表达能力(准确率)和稳定性


定义

K 0 K_0 K0 限制模型的输出值,不会有太极端的变化:

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述
控制模型的平滑

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

在这里插入图片描述
在这里插入图片描述

在这里插入图片描述

在这里插入图片描述
在这里插入图片描述

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

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

相关文章

11.怎么做好一个动态标签页

效果 步骤 1.在Elementui找一个标签页组件 复制粘贴到代码 2.将他写活 将很多页面需要用的方法和变量写入store editableTabsValue: 2,editableTabs: [{title: 首页,name: index,},],addTab(state, tab) {if (state.editableTabs.findIndex(item > item.title tab.titl…

LVGL系列2--linux + lvglv8 + vscode 移植

LVGL系列 一、LVGL移植 LVGL系列1–AT32移植LVGL_V8具体步骤 LVGL系列2–linux lvglv8 vscode 移植 二、输入设备 LVGL系列3–纯物理(外部)按键&#xff0c;数字键盘控制控件 文章目录 LVGL系列一、LVGL移植二、输入设备 一、新建文件夹并克隆源码官方仓库 7.11.0官方仓库…

【AI/算法类】OPPO 2025届秋招笔试题(B卷)

目录 1. 第一题2. 第二题3. 第三题 ⏰ 时间&#xff1a;2024/08/10 &#x1f504; 输入输出&#xff1a;ACM格式 ⏳ 时长&#xff1a;2h 本试卷还有选择题部分&#xff0c;但这部分比较简单就不再展示。 1. 第一题 小O有一个正整数 x x x&#xff0c;他想知道&#xff0c;第…

抽卡机小程序,开启全新拆卡乐趣

近段时间&#xff0c;盲盒卡牌市场异常火爆&#xff0c;最近爆火的“小马宝莉”系列卡牌就深受消费者的喜爱&#xff0c;受到了广泛关注&#xff0c;同时也推动了卡牌市场的快速发展&#xff01;盲盒卡牌拥有隐藏款卡牌和限量款卡牌&#xff0c;具有非常大的收藏价值&#xff0…

使用Java调用Apache commons-text求解字符串相似性实战

目录 前言 一、字符串距离的几种计算方法 1、Levenshtein 距离 2、Overlap Coefficient计算 3、Q-gram Matching 4、余弦相似性计算 二、基于余弦相似性的基地名称对比 1、加载百科中的基地信息列表 2、设置忽略词列表 3、将数据库地名和Excel进行对比 三、总结 前言…

从力扣中等+困难题+表白HTML测试 -- 文心快码(Baidu Comate)

0 写在前面 官网地址&#xff1a;Baidu Comate Step1 打开文心快码&#xff08;Baidu Comate&#xff09;官网&#xff0c;点击「免费使用」/「下载安装」 Step2 可以根据官网步骤快速唤起VS Code&#xff1b; 也可以直接在VS Code、Visual Studio扩展管理搜索“文心快码”/…

如何用OceanBase实现HBase架构升级

随着数据量的爆炸性增长&#xff0c;特别是半结构化和非结构化数据的涌现&#xff0c;传统关系型数据库如 MySQL 遭遇了前所未有的挑战。这一背景下&#xff0c;为非结构化数据管理而生的 NoSQL 数据库&#xff0c;以及旨在解决海量数据存储难题的分布式技术应运而生&#xff0…

导出word格式的Javadoc(可用于快速生成项目详细设计文档)

导出word格式的Javadoc ​ 最近要编写项目详细设计文档&#xff0c;作为程序员当然想看看有没有能够自动生成的办法&#xff0c;生成详细设计文档&#xff0c;然后再在生成的基础上略做修改就好了&#xff08;偷懒大法~&#xff09;&#xff0c;还真有&#xff0c;特此分享&am…

理解Pytorch中的collate_fn函数

PyTorch中的DataLoader是最常用的类之一&#xff0c;这个类有很多参数&#xff08;14 个&#xff09;&#xff0c;但大多数情况下&#xff0c;你可能只会使用其中的三个&#xff1a;dataset、shuffle 和 batch_size。其中collate_fn是比较少用的函数&#xff0c;这对初学者来说…

Linux线程间通信学习记录(线程同步)

0.线程间通信的方法 &#xff08;1&#xff09;.全局变量&#xff08;要结合同步机制&#xff09; &#xff08;2&#xff09;.信号量 &#xff08;3&#xff09;.P操作 &#xff08;4&#xff09;.V操作 一.线程同步 同步&#xff1a;指的是多个任务按照约定的先后次序相互…

Visual C++ 2010 学习版

这个版本很好用。 在这里放一个链接&#xff0c;做个备份。 这个版本是承前启后的版本&#xff0c;非常的重要。 一、使用VC2010 这个版本创建的解决方案可以在VS2010~VS2022版本中打开&#xff0c;反之也行。 二、使用VC2010 可以编绎VC6.0 ~VC2008的项目。可以使用现成的…

灵办AI助手Chrome插件全面评测:PC Web端的智能办公利器

探索灵办AI助手在Mac OS上的高效表现&#xff0c;支持多款主流浏览器&#xff0c;助你轻松应对办公挑战 文章目录 探索灵办AI助手在Mac OS上的高效表现&#xff0c;支持多款主流浏览器&#xff0c;助你轻松应对办公挑战摘要引言开发环境介绍核心功能评测1. 网页翻译与双语对照 …

Rancher 使用 Minio 备份 Longhorn 数据卷

0. 概述 Longhorn 支持备份到 NFS 或者 S3, 而 MinIO 就是符合 S3 的对象存储服务。通过 docker 部署 minio 服务&#xff0c;然后在 Longhorn UI 中配置备份服务即可。 1. MinIO 部署 1.1 创建备份目录 mkdir -p /home/longhorn-backup/minio/data mkdir -p /home/longhor…

RCE的另外一些绕过练习

目录 被过滤了flag怎么办 方法 结果 过滤了flag、php、system 方法一 结果 ​编辑 方法二 过滤了很多但是主要的就是过滤了空格 和 注意一下这个就行 方法一 方法二 相对于上面一道题来说多过滤了一个括号 方法一 被过滤了flag怎么办 <?php error_reportin…

Python3网络爬虫开发实战(10)模拟登录(需补充账号池的构建)

文章目录 一、基于 Cookie 的模拟登录二、基于 JWT 模拟登入三、账号池四、基于 Cookie 模拟登录爬取实战五、基于JWT 的模拟登录爬取实战六、构建账号池 很多情况下&#xff0c;网站的一些数据需要登录才能查看&#xff0c;如果需要爬取这部分的数据&#xff0c;就需要实现模拟…

K8S - ConfigMap的简介和使用

什么是configMap Kubernetes中的ConfigMap 是用于存储非敏感数据的API对象&#xff0c;用于将配置数据与应用程序的镜像分离。ConfigMap可以包含键值对、文件或者环境变量等配置信息&#xff0c;应用程序可以通过挂载ConfigMap来访问其中的数据&#xff0c;从而实现应用配置的…

ubuntu20 lightdm无法自动登录进入桌面

现象&#xff1a;在rk3568的板子上自己做了一个Ubuntu 20.04的桌面系统。配置lightdm自动登录桌面&#xff0c;配置方法如下&#xff1a; $ vim /etc/lightdm/lightdm.conf [Seat:*] user-sessionxubuntu autologin-userusername #修改成自动登录的用户名 greeter-show-m…

38-PCB布局实战实战及优化

1.先对布局好的器件进行锁定 1.根据模块化布局 2.电容尽量靠近ic附近&#xff0c;可以起到很好的滤波效果 3.复位按键尽量摆在容易按键的地方&#xff0c;比如周围 。。。。 最后进行对齐

【OCR 学习笔记】二值化——局部阈值方法

二值化——局部阈值方法 自适应阈值算法Niblack算法Sauvola算法 自适应阈值算法 自适应阈值算法1用到了积分图&#xff08;Integral Image&#xff09;的概念。积分图中任意一点 ( x , y ) (x,y) (x,y)的值是从图左上角到该点形成的矩形区域内所有值的和。即&#xff1a; I (…

模板[C++]

目录 1.&#x1f680;泛型编程&#x1f680; 2.&#x1f680;函数模板&#x1f680; 2.1 ✈️函数模板概念✈️ 2.2 ✈️函数模板格式✈️ 2.3✈️函数模板的原理✈️ 2.4 ✈️函数模板的实例化✈️ 2.5 ✈️模板参数的匹配原则✈️ 3.&#x1f680;类模板&#x1f680…