当前位置: 首页 > article >正文

3D Gaussian Splatting 代码层理解之Part3

最后,内容到达了高斯泼溅过程中最有趣的阶段:渲染!这一步可以说是最关键的,因为它决定了模型的真实性。然而,它也可能是最简单的。在本系列的 Part1 和 Part2,文章演示了如何将 Raw 3D椭球转换为可渲染的格式,但现在我们实际上必须完成这项工作并渲染到一组固定的像素上。作者使用 CUDA 开发了一个快速渲染引擎,这可能有点难以理解。因此,首先浏览 Python 中的代码是有益的,为了清晰起见,使用简单的 for 循环。对于那些渴望深入了解的人来说,所有必要的代码都可以在我们的 GitHub上找到。

继续讨论如何渲染每个单独的像素。从上一篇文章中,我们有了所有必要的组件:2D 点、相关颜色、协方差、排序的深度顺序、2D 中的逆协方差、每个 splat 的最小和最大 x 和 y 值以及相关的不透明度。有了这些组件,就可以渲染每一个像素。对于给定特定的像素坐标,我们按照相对于相机平面的泼溅深度顺序(投影到相机平面,然后按深度排序)遍历所有3D椭球,直到达到饱和阈值。对于每个 splat,我们首先检查像素坐标是否在3D椭球最小和最大 x 和 y 值定义的边界内。此检查确定我们是应该继续渲染还是忽略对应这些坐标的 splat。接下来,我们使用 splat 均值、splat 协方差和像素坐标计算像素坐标处的高斯 splat 强度。

def compute_gaussian_weight(
   pixel_coord: torch.Tensor,  # (1, 2) tensor
   point_mean: torch.Tensor,
   inverse_covariance: torch.Tensor,
) -> torch.Tensor:


   difference = point_mean - pixel_coord
   power = -0.5 * difference @ inverse_covariance @ difference.T
   return torch.exp(power).item()

我们将此权重乘以 splat 的不透明度,以获得一个名为 alpha 的参数。在将此新值添加到像素之前,我们需要检查是否已超过饱和度阈值。如果像素已经饱和,我们不希望当前 splat 后面其他 splat 影响像素着色并使用计算资源。因此,这里使用一个阈值,允许我们在超过该阈值时停止渲染。在实践中,我们从 1 开始将饱和阈值乘以 min(0.99, (1- alpha))  得到一个新值。如果此值小于阈值 (0.0001),我们将停止渲染该像素并认为它已完成。如果没有,我们将添加由saturation * (1 - alpha)值加权的颜色,并将饱和度更新为 new_saturation = old_saturation * (1 - alpha)。最后,我们遍历每个像素(或实际中的每个 16x16 图块)并进行渲染。完整的代码如下所示。

def render_pixel(
       self,
       pixel_coords: torch.Tensor,
       points_in_tile_mean: torch.Tensor,
       colors: torch.Tensor,
       opacities: torch.Tensor,
       inverse_covariance: torch.Tensor,
       min_weight: float = 0.000001,
   ) -> torch.Tensor:
       total_weight = torch.ones(1).to(points_in_tile_mean.device)
       pixel_color = torch.zeros((1, 1, 3)).to(points_in_tile_mean.device)
       for point_idx in range(points_in_tile_mean.shape[0]):
           point = points_in_tile_mean[point_idx, :].view(1, 2)
           weight = compute_gaussian_weight(
               pixel_coord=pixel_coords,
               point_mean=point,
               inverse_covariance=inverse_covariance[point_idx],
           )
           alpha = weight * torch.sigmoid(opacities[point_idx])
           test_weight = total_weight * (1 - alpha)
           if test_weight < min_weight:
               return pixel_color
           pixel_color += total_weight * alpha * colors[point_idx]
           total_weight = test_weight
       # in case we never reach saturation
       return pixel_color

http://www.kler.cn/a/402256.html

相关文章:

  • SpringBoot 集成 Sharding-JDBC(一):数据分片
  • self-host a private Docker registry
  • 学习笔记023——Ubuntu中设置Java项目的 jar 包自启动
  • STM32单片机CAN总线汽车线路通断检测-分享
  • Linux下,修改环境变量的几种方法
  • oracle配置
  • Spring Boot参数处理秘籍:从手动到自动的华丽蜕变
  • css:浮动
  • 服务器上部署并启动 Go 语言框架 **GoZero** 的项目
  • C++ —— 剑斩旧我 破茧成蝶—C++11
  • macOS 的目录结构
  • 苹果ASA归因对接以及API接入
  • Linux高阶——1116—环形队列生产者消费者
  • 优选算法 - 4 ( 链表 哈希表 字符串 9000 字详解 )
  • 【Android】线程池的解析
  • 【西瓜书】机器学习的模型评估
  • Spark RDD 中的 repartition 和 coalesce 是两种常用的分区调整算子的异同点
  • MMaction2:常见问题解答
  • 【AI+教育】一些记录@2024.11.16
  • 从0开始学习机器学习--Day26--聚类算法