武邑网站建设价格,aaa免费服务器,传统门户网站有哪些,手机微信登入网站一、引言#xff1a;为什么 3DGS 需要 FastGS#xff1f;#xff08;动机#xff09;1.1 3D Gaussian Splatting 的成功与瓶颈3D Gaussian Splatting#xff08;3DGS#xff09;通过显式三维高斯表示与可微分的 splatting 渲染方式#xff0c;在新视角合成任务中取得了极…一、引言为什么 3DGS 需要 FastGS动机1.1 3D Gaussian Splatting 的成功与瓶颈3D Gaussian Splatting3DGS通过显式三维高斯表示与可微分的 splatting 渲染方式在新视角合成任务中取得了极高的渲染效率与画质表现。相比于 NeRF 等体渲染方法3DGS 在训练速度与推理速度上具有显著优势。然而在训练过程中vanilla 3DGS 也暴露出了一些结构层面的瓶颈问题densify 过程高度依赖单视角的梯度信息容易在局部视角下过度增密prune 策略主要依赖 opacity 和尺度等静态阈值缺乏对长期贡献度的判断高斯数量随训练轮数快速膨胀带来显著的计算与显存开销从本质上看3DGS 的结构优化densify / prune是一种“单视角、局部、贪心”的策略。1.2 FastGS 的核心思想多视图一致性为了解决上述问题FastGS 并没有改变 3DGS 的基本表示方式或 CUDA 渲染流程而是将优化重点放在了densify 与 prune 的决策机制上。FastGS 的核心思想是一个 Gaussian 是否值得被保留或细化不应只由某一个视角的瞬时梯度决定而应由多个视角下的长期重建一致性来判断。一句话总结FastGS 用多视图一致性重新定义了 densify 与 prune。由此引出了 FastGS 中两个关键概念VCDView-consistent Densification与 VCPView-consistent Pruning。二、FastGS 中的 VCD 与 VCP 是什么2.1 两个关键概念FastGS 的核心贡献可以概括为以下两个概念VCDView-consistent Densification只有在多个视角中反复参与高误差区域的 Gaussian才被认为是真正需要 densify 的对象。VCPView-consistent Pruning对那些在多个视角下长期造成重建失败、但对整体渲染质量贡献有限的 Gaussian进行优先剪枝。需要特别强调的一点是VCD 与 VCP 构成了 FastGS 与 vanilla 3DGS 的本质分界线。2.2 FastGS 的整体算法流程概览从整体流程上看FastGS 的训练与结构优化可以概括为以下步骤从训练视角池中随机采样多个相机视角在每个视角下进行渲染并计算光度误差构建高误差像素区域metric map统计每个 Gaussian 在多视角中的误差参与情况基于多视图一致性分数执行 densifyVCD与 pruneVCPVCD 与 VCP 的具体实现流程在代码层面FastGS 的多视图一致性逻辑主要由以下两个核心函数完成compute_gaussian_score_fastgs负责从多视角中统计每个 Gaussian 的一致性评分densify_and_prune_fastgs基于上述评分执行结构优化操作三、VCD / VCP 的信息来源compute_gaussian_score_fastgs本章重点讲清楚一个问题FastGS 中“多视角一致性分数”究竟是怎么计算出来的3.1 函数整体作用说明先用一句话定性compute_gaussian_score_fastgs的作用是从多个视角统计每个 Gaussian 在高误差区域中出现的频率用于指导 densify 和 prune。换句话说这个函数不直接修改 Gaussian而是为后续的VCDView-consistent Densification和VCPView-consistent Pruning提供决策依据。def compute_gaussian_score_fastgs(camlist, gaussians, pipe, bg, args, DENSIFY False): Compute multi-view consistency scores for Gaussians to guide densification. For each camera in camlist the function renders the scene and computes a photometric loss and a binary metric map of high-error pixels. It accumulates per-Gaussian counts of views that flagged the Gaussian and a weighted photometric score across views. Args: camlist (list): list of viewpoint camera objects to render from. gaussians: current Gaussian representation (model/state) used for rendering. pipe: rendering pipeline/context required by render. bg: background used for rendering. args: runtime config containing thresholds (e.g. loss_thresh). DENSIFY (bool): whether to compute and return the importance score used for densification. If False, only the pruning score is computed. Returns: importance_score (Tensor): per-Gaussian integer counts of how many views marked the Gaussian as high-error (floor-averaged across views). This output is only returned if DENSIFY is True. pruning_score (Tensor): normalized (0..1) per-Gaussian score used to prioritize densification (higher means worse reconstruction consistency). 计算 FastGS 的多视角一致性评分 核心思想 - 从多个视角渲染 - 找出高误差像素区域 - 统计哪些 Gaussian 在多个视角下反复参与高误差区域 - 用于 densify / prune 决策 # 统计每个 Gaussian 被多少个视角标记为“高误差相关” full_metric_counts None # 统计每个 Gaussian 的加权光度误差 full_metric_score None for view in range(len(camlist)): my_viewpoint_cam camlist[view] # 第一次普通渲染用于计算误差 render_image render_fastgs(my_viewpoint_cam, gaussians, pipe, bg, args.mult)[render] # 当前视角的整体光度误差标量计算该视角的整体重建质量 E(photo,j) photometric_loss compute_photometric_loss(my_viewpoint_cam, render_image) gt_image my_viewpoint_cam.original_image.cuda() get_flag True # 获取逐像素 L1 误差热力图 l1_loss_norm get_loss(render_image, gt_image) # 构造 metric map高于阈值的像素记为 1 # 表示这些区域是“重建失败区域” metric_map (l1_loss_norm args.loss_thresh).int() # 第二次渲染携带 metric_map # renderer 内部会统计每个 Gaussian # 在多少“高误差像素”中被使用 # 第二次渲染get_flag True似乎可以用来计数 render_pkg render_fastgs(my_viewpoint_cam, gaussians, pipe, bg, args.mult, get_flag get_flag, metric_map metric_map) # 每个 Gaussian 在该视角下 # 参与高误差像素的次数 accum_loss_counts render_pkg[accum_metric_counts] # 累积多视角的“命中次数”densify 用 if DENSIFY: if full_metric_counts is None: full_metric_counts accum_loss_counts.clone() else: full_metric_counts accum_loss_counts # 累积多视角的“加权光度误差”prune 用pure基本上就是在densify基础上乘以一个photometric_loss # VCP是删除损失photometric_loss不大但是误差像素多的点也就是基本上对渲染质量没有贡献的点 # pruning_score是出现于高误差区域accum_metric_counts且该视角整体误差还很大photometric_loss #pruning_score 大 “在很多视角里都失败” if full_metric_score is None: full_metric_score photometric_loss * accum_loss_counts.clone() else: full_metric_score photometric_loss * accum_loss_counts # 将 pruning score 归一化到 [0,1] pruning_score (full_metric_score - torch.min(full_metric_score)) / (torch.max(full_metric_score) - torch.min(full_metric_score)) if DENSIFY: # importance_score Gaussian 在多少个视角中 # 被认为是“高误差相关”的平均次数向下取整 importance_score torch.div(full_metric_counts, len(camlist), rounding_modefloor) else: importance_score None # 返回 # importance_score → 决定 densifyclone / split # pruning_score → 决定 prune return importance_score, pruning_score3.2 多视角渲染与误差区域构建在compute_gaussian_score_fastgs中会对每一个采样到的视角执行一次完整的误差分析流程具体步骤如下对每个视角进行一次普通渲染得到该视角下的重建图像计算 photometric loss表示该视角整体的重建误差水平计算逐像素 L1 loss得到像素级的误差热力图构造误差区域metric_mapmetric_map (l1_loss_norm args.loss_thresh).int()3.3 利用 CUDA rasterization 统计 Gaussian–误差像素关联这一部分是FastGS 的核心亮点。在 FastGS 中每个视角都会进行第二次渲染并显式设置第二次渲染get_flag True在这次渲染过程中统计逻辑并不发生在 Python 层而是被嵌入到了 CUDA rasterization 内核中。具体来说在CUDA kernel内部会执行如下统计对每个 Gaussian统计它参与了多少个高误差像素最终得到的结果是accum_metric_counts表示该 Gaussian 在当前视角下参与高误差像素的次数你可以重点强调一句FastGS 并不是在 Python 层逐 Gaussian 统计而是将统计逻辑嵌入到 rasterization CUDA 内核中完成。这也是 FastGS 能在引入多视角一致性分析的同时依然保持高效率的重要原因。3.4importance_score与pruning_score的定义FastGS 最终会为每个 Gaussian 计算两个关键分数分别对应VCD与VCP。1importance_scoreVCD定义形式为importance_score floor(full_metric_counts / num_views)含义说明一个 Gaussian在多少个视角中被认为是“高误差相关”用于 densifyVCD2pruning_scoreVCP其累积方式为full_metric_score photometric_loss * accum_metric_counts归一化后含义pruning_score较大表示该 Gaussian在多个视角中且整体重建质量较差持续参与高误差区域用于 pruneVCP四、VCD / VCP 的执行层densify_and_prune_fastgs在前一章中我们已经详细解释了FastGS 中多视角一致性分数是如何计算得到的。本章将进一步回答一个更关键的问题当这些分数被计算出来之后FastGS 是“如何真正作用于 Gaussian 结构的”换句话说这一章关注的是importance_score与pruning_score是如何被用于实际的 densifyVCD与 pruneVCP操作从而改变 Gaussian 的数量、分布与尺度也正是在这一执行层中FastGS 与 vanilla 3DGS 的差异被真正“落实”为可观察的训练行为。def densify_and_prune_fastgs(self, max_screen_size, min_opacity, extent, radii, args, importance_score None, pruning_score None): # 剪枝 Densification and Pruning based on FastGS criteria: 1. The gaussians candidate for densification are selected based on the gradient of their position first. 2. Then, based on their average metric score (computed over multiple sampled views), they are either densified (cloned) or split. This is our main contribution compared to the vanilla 3DGS. 3. Finally, gaussians with low opacity or very large size are pruned. FastGS 的 densify prune 主逻辑函数 核心思想与 vanilla 3DGS 的区别 1. 先用高斯中心位置的梯度筛选“确实需要细化”的候选高斯 2. 再用 FastGS 的多视角一致性指标importance_score 对 densify 候选进行二次筛选VCDView-consistent Densification 3. 最后结合 opacity / 尺寸约束 多视角失败指标pruning_score 执行剪枝VCPView-consistent Pruning # # 1. 计算位置梯度的平均值和 vanilla 3DGS 一致 # # xyz_gradient_accum: 训练过程中累计的 xyz 梯度 # denom: 累计次数或归一化因子 grad_vars self.xyz_gradient_accum / self.denom # 防止出现 NaN如某些高斯没有被采样到 grad_vars[grad_vars.isnan()] 0.0 # 保存当前渲染得到的 2D 半径用于后续 prune 判断 self.tmp_radii radii # 绝对梯度版本常用于 split 判断更敏感 grads_abs self.xyz_gradient_accum_abs / self.denom grads_abs[grads_abs.isnan()] 0.0 # # 2. 基于梯度阈值筛选 densify 候选第一道门 # # grad_thresh位置梯度足够大说明该高斯对重建误差敏感 grad_qualifiers torch.where(torch.norm(grad_vars, dim-1) args.grad_thresh, True, False) # grad_abs_thresh用于 split 的更激进梯度阈值 grad_qualifiers_abs torch.where(torch.norm(grads_abs, dim-1) args.grad_abs_thresh, True, False) # # 3. 基于高斯尺度区分 clone / splitvanilla 3DGS 规则 # # 尺度较小的高斯更适合 clone复制 clone_qualifiers torch.max(self.get_scaling, dim1).values args.dense*extent # 尺度较大的高斯更适合 split分裂成多个小高斯 split_qualifiers torch.max(self.get_scaling, dim1).values args.dense*extent # 同时满足“梯度大 尺度小”的 clone 候选 all_clones torch.logical_and(clone_qualifiers, grad_qualifiers) # 同时满足“梯度大abs 尺度大”的 split 候选 all_splits torch.logical_and(split_qualifiers, grad_qualifiers_abs) # # 4. FastGS 核心多视角一致性 densifyVCD # # importance_score 来自 compute_gaussian_score_fastgs # 表示一个 Gaussian 在多个视角中 # 反复参与“高误差像素区域”的平均次数 # # 只有多视角一致“确实有问题”的高斯才允许 densify # This is our multi-view consisent metric for densification # We use this metric to further filter the candidates for densification, which is similar to taming 3dgs. metric_mask importance_score 5 # 在传统 densify 候选的基础上all_clones再加一层多视角一致性过滤metric_mask # 实际 clone 的 mask metric_mask all_clones self.densify_and_clone_fastgs(metric_mask, all_clones) # 实际 split 的 mask metric_mask all_splits self.densify_and_split_fastgs(metric_mask, all_splits) # # 5. 基础剪枝规则vanilla 3DGS # # 低 opacity 的高斯基本不贡献颜色可直接删除 prune_mask (self.get_opacity min_opacity).squeeze() if max_screen_size:#如果有设置最大屏幕尺寸 # 屏幕空间半径过大渲染开销大 / 异常 big_points_vs self.max_radii2D max_screen_size # 世界空间尺度过大可能是异常高斯 big_points_ws self.get_scaling.max(dim1).values 0.1 * extent # 合并所有传统 prune 条件prune_mask先确定“允许被删”的大集合这一步 不看多视角你在物理/渲染层面就已经很可疑了 prune_mask torch.logical_or(torch.logical_or(prune_mask, big_points_vs), big_points_ws) # # 6. FastGS 核心多视角一致性剪枝VCP # # pruning_score 越大表示该高斯在多视角下持续造成重建失败 # 这里将其翻转成“保留得分” # scores 1 - pruning_score翻转语义 # scores大表示更加可靠 scores 1 - pruning_score # 理论上可以删除的点数量 to_remove torch.sum(prune_mask) # 实际删除预算更保守避免一次删太多导致质量震荡只删“可删集合”的一半剩下的留给下一轮避免一次性删掉大量高斯导致画质瞬间崩掉 # 所以引入remove_budget删除预算这个是不是某些3D GS优化方法采用的呢 remove_budget int(0.5 * to_remove) # 使用带权随机采样而不是直接阈值一刀切 # 权重 ~ 1 / scores → pruning_score 大的更容易被删 # The budget is not necessary for our method. if remove_budget: n_init_points self.get_xyz.shape[0] padded_importance torch.zeros((n_init_points), dtypetorch.float32) # 只对现存高斯赋权重 padded_importance[:scores.shape[0]] 1 / (1e-6 scores.squeeze()) selected_pts_mask torch.zeros_like(padded_importance, dtypebool, devicecuda) # 所以还是找prune_score大的点对吗。按权重随机采样需要删除的高斯索引根据 padded_importance 作为权重随机抽 remove_budget 个索引权重大 → 更容易被抽中 sampled_indices torch.multinomial(padded_importance, remove_budget, replacementFalse) selected_pts_mask[sampled_indices] True # 同时满足传统 prune 多视角失败优先的点才真正删除 # 传统prune(prune_mask),selected_pts_mask多视角失败优先的点 final_prune torch.logical_and(prune_mask, selected_pts_mask) self.prune_points(final_prune) # # 7. 重置不透明度 opacity稳定训练防止“单个高斯遮天蔽日” # # 将 opacity 上限截断到 0.8防止个别高斯过度遮挡 # inverse_sigmoid从真实空间映射回优化参数空间 opacities_new inverse_sigmoid(torch.min(self.get_opacity, torch.ones_like(self.get_opacity)*0.8)) # 用新的 opacity tensor 替换优化器中的参数并重置动量 optimizable_tensors self.replace_tensor_to_optimizer(opacities_new, opacity) self._opacity optimizable_tensors[opacity] # 清理临时变量 tmp_radii self.tmp_radii self.tmp_radii None # 释放 CUDA 缓存避免显存碎片化 torch.cuda.empty_cache()4.1 第一层沿用 3DGS 的梯度筛选在正式引入多视角一致性机制之前FastGS并没有推翻 3DGS 原有的 densify 逻辑而是选择在其基础上进行增强。具体来说FastGS 仍然保留了 3DGS 中以梯度为核心的结构优化思想主要体现在两个方面基于位置梯度筛选 densify 候选基于 Gaussian 尺度区分 clone / split 行为基于位置梯度的候选筛选在训练过程中3DGS 会持续累积每个 Gaussian 在三维空间位置上的梯度若某个 Gaussian 的位置梯度较大→ 说明当前区域对重建误差高度敏感→ 该位置可能需要更高的表示精度FastGS 同样采用这一准则首先通过位置梯度阈值筛选出一批“确实有必要被细化”的 Gaussian 候选。基于尺度的 clone / split 区分在通过梯度筛选之后FastGS 继续沿用 3DGS 的尺度判定规则尺度较小的 Gaussian→ 通过clone复制进行 densify尺度较大的 Gaussian→ 通过split分裂生成多个更小的 Gaussian这一规则保证了 densify 行为在几何意义上的合理性避免盲目复制或分裂。强调一点FastGS 并不是对 3DGS 的“推倒重来”而是在保留其梯度驱动结构优化合理性的前提下引入新的判据进行约束和修正。4.2 VCD多视图一致 densifyFastGS 的核心改进在完成基于梯度与尺度的初步筛选之后FastGS 引入了其最关键的改进之一VCDView-consistent Densification多视图一致 densify。其核心判据可以概括为一行代码metric_mask importance_score threshold逻辑只有在多个视角下反复失败的 Gaussian才允许 densify对比 3DGS3DGS单视角梯度大 → densifyFastGS梯度大 多视角一致失败→ densify4.3 VCP多视图一致 pruneFastGS 核心VCPView-consistent Pruning的目标是在不破坏画质稳定性的前提下更稳、更准地删掉“多视角下持续表现不佳”的 Gaussian。整体可以分三步理解Step 1构造传统prune_maskopacity / 尺度FastGS 首先沿用 3DGS 的经典剪枝逻辑得到一批“允许被删”的候选集合opacity 很低几乎不贡献颜色/透明度屏幕空间半径过大渲染开销大/异常世界空间尺度过大可能是异常高斯可以理解为prune_mask先圈定一个“物理层面可疑”的大集合这一步不看多视角一致性。Step 2引入pruning_score多视角一致失败程度接下来FastGS 使用compute_gaussian_score_fastgs得到的pruning_scorepruning_score越大→ 表示该 Gaussian 在多个视角中持续参与高误差区域→ 且这些视角的整体重建质量较差→ 属于“多视角一致失败”的高斯为了便于“保留/删除”的语义转换代码中常写scores 1 - pruning_score一句总结FastGS 并非“直接删pruning_score最大的点”而是通过带权随机采样实现稳定、渐进的结构收缩。4.4remove_budget的作用稳定性设计在 FastGS 的 VCP 设计中remove_budget是一个非常关键、但容易被忽略的稳定性机制因此值得单独拿出来说明。为什么不一次删完如果在某一轮迭代中将所有满足 prune 条件的 Gaussian 一次性删除很容易导致场景结构突然发生剧烈变化局部区域高斯密度骤降重建质量瞬间下降甚至训练发散这种现象可以理解为结构震荡structural oscillation。remove_budget的作用remove_budget的核心思想是“宁可慢一点删也不要一次删太多。”它的具体作用包括限制单次 prune 的数量只删除“可删集合”的一部分例如一半让结构调整更加平滑给后续 densify / 优化留出修正空间提升整体训练稳定性防止因结构骤变导致的画质抖动一个重要结论这种**“带预算的渐进 prune”策略**已在多种3DGS 加速 / 稀疏化工作中被证明更稳定、更可靠FastGS 在此基础上结合了多视角一致性使其效果进一步增强。五、FastGS vs 3DGS从 VCD / VCP 角度的本质区别总结从 VCDView-consistent Densification和 VCPView-consistent Pruning的角度来看FastGS 并不是简单的工程加速而是对 3DGS 结构优化逻辑的一次系统性升级。5.1 Densify 机制对比3DGS单视角驱动基于局部梯度大小容易受到偶然视角误差的影响FastGS多视角一致性驱动VCD梯度大且多视角一致失败更精准地 densify“真正有问题”的区域5.2 Prune 机制对比3DGS基于硬阈值opacity / 尺度删除策略相对激进易产生结构震荡FastGS多视角一致性 pruneVCP结合多视角失败评分带权概率采样删除预算控制删除过程更稳、更渐进5.3 训练行为差异综合来看FastGS 在训练过程中表现出明显不同的行为特征高斯数量增长更慢训练时间显著降低重建质量保持甚至在部分场景中提升从 VCD / VCP 的角度看FastGS 的核心优势在于用多视角一致性换取更少的高斯、更稳定的训练、更高的效率。六、心得先进行VCD多视图一致的致密化再进行VCP多视图一致的剪枝两者是先后顺序而不是if else的并行关系。且VCP 一般很少删除 VCD 新增的点了解到如果大量删除 VCD 新增的点可能是代码出了问题。在传统 densify 候选的基础上all_clones再加一层多视角一致性过滤metric_mask# 在传统 densify 候选的基础上all_clones再加一层多视角一致性过滤metric_mask # 实际 clone 的 mask metric_mask all_clones self.densify_and_clone_fastgs(metric_mask, all_clones) # 实际 split 的 mask metric_mask all_splits self.densify_and_split_fastgs(metric_mask, all_splits)同时满足传统 prune 多视角失败优先的点才真正删除final_prune torch.logical_and(prune_mask, selected_pts_mask) self.prune_points(final_prune)