内容导读

3D 深度学习一直是机器视觉领域的难点,为了准确高效地建立场景的立体模型,得到相对真实的渲染成果,行业内的一些大厂先后开源了自己的研发成果。

本文首发自微信公众号「PyTorch 开发者社区」

随着计算机视觉领域相关技术的发展,针对 2D 图像的处理效率和精度得到了显著地提升。

但是现实环境中,物体多以 3D 立体结构的形式存在,如何准确地提升 AI 系统对复杂现实环境的感知和理解能力,正确处理 3D 图像, 正在成为日趋关键的技术难点。

2019 年 Facebook AI 发布 Mesh R-CNN 模型进行 3D 目标检测与形状预测

2020 年 1 月 23 日,Facebook AI 发布了 PyTorch3D v0.1.0 版本。PyTorch3D 是 PyTorch 中经过优化的、高效、可重用组件库,它具有 3 大突出特点:高效、模块化和可微分,旨在简化在 PyTorch 中进行 3D 深度学习的难度。

PyTorch3D 中提供了 3D 算子和渲染两大组件。

在 3D 算子中,Fit Mesh 可以利用 3D 损失函数,把初始的通用形状变形为目标形状,并借助一些规则让目标形状变得更为流畅。 而 3D 算子中的光束平差法(Bundle Adjustment),则提供了 camerastransformsso3 共计 3 个 API,根据给定相机的视角,形成对照相机视角的映射,从而推断场景的 3D 结构。

渲染则包括纹理网格渲染器(Render Textured Meshes)、DensePose 网格渲染器(Render DensePose Meshed)、彩色点云渲染器(Render Colored Pointclouds)等, 借助这些渲染器,可以进一步优化形成的场景 3D 结构。

2020 年 2 月 6 日,PyTorch3D 相关代码在 GitHub 开源。经过 5 个版本的迭代后,2021 年 2 月 9 日,PyTorch3D 发布第 6 个公开版本 v0.4.0,** 新增隐函数、立体渲染和 NeRF 重新实现等功能,**为 3D 深度学习研究提供了更迅速、更灵活的开源库。

图为 PyTorch3D logo,由 PyTorch3D 的隐式立体渲染器生成的

隐式形状渲染(Implicit Shape Rendering)

隐式形状渲染是指基于输入场景的新视角,生成 3D 场景的真实渲染,其核心思想是利用神经网络与可微分渲染,重建 3D 场景表面的隐式形态, 这使得仅依靠 2D 视图就可以学习 3D 场景中的几何形状。

进行隐式形状渲染需要几个关键组件,包括数据卷的抽象类(abstraction for volume data)以及可微分的隐式形状渲染器。

为了让行业从业者更容易地针对隐式形状渲染进行尝试,PyTorch3D 已经为用户提供了一系列常用的 3D 算子(3D operators)和损失函数,以及一个模块化、可微分的渲染 API。 在指出核心可重用组件的同时,也提供了这些组件经验证的、标准化实现方法。

在 PyTorch3D v0.4.0 中,包括 5 个支持隐式形状渲染的新特性:

1、新增数据卷结构(Volumes data structure),支持 3D 卷的批处理和坐标框架之间的转换;

2、新增多个光线纹理实现方法:

GridRaysampler

MonteCarloRaysampler

NDCGridRaysampler

3、新增多个 Raymarcher 实现方法:

AbsorptionOnlyRaymarcher

EmissionAbsorptionRaymarcher

4、新增隐式渲染器(ImplicitRenderer)和体积渲染器(VolumeRenderer)API,构成 Raysampler 和 Raymarcher

5、新增多个效用函数,如点云到体积的可微分转换。

利用 PyTorch3D 生成的甜甜圈 3D 图像

要使用这些新组件,可以借助一个模块化、文档完备的 NeRF 重新实现。
NeRF 是一个深度学习模型, 由 Google Research 团队开发,旨在借助神经辐射场(Neural Radiance Fields)表示场景,从而进行视图合成(View Synthesis)。
NeRF 仅使用非结构化图像集合,就能合成复杂的 3D 场景图。

而改良版的 NeRF 重新实现,性能得到了极大提升,在保证输出图像质量的同时,比正式版本运行得更快。

使用 PyTorch3D 的 NeRF 重新实现功能,生成了形状和光影复杂的 3D 图像示例

教程(Fit Textured Volume)

我们基于 PyTorch3D GitHub 官方教程 Fit Textured Volume,进行了汉化和整理,演示如何在 PyTorch3D 中,利用可微分立体渲染,依据给定场景的一组视图,预测场景的立体结构。

用 Raymarching 构建场景 3D 立体结构

本教程将介绍:

  • 如何创建一个可微分的立体渲染器;
  • 如何创建一个立体模型(包括如何使用 Volumes 类);
  • 使用可微分的立体渲染器,根据图像拟合立体结构;
  • 将预测的立体结构可视化。

备注:限于篇幅有限,本文仅展示部分代码,完整代码请移步:

https://openbayes.com/console/openbayes/containers/oAYzp70wwPk/overview

0. 安装和导入模块

确保已安装 torchtorchvision

如果没有安装 pytorch3d ,请使用以下代码安装。

1. 生成场景及 mask 的图像

以下代码将生成本次训练数据。它会通过 fit_textured_mesh.ipynb 教程,从多个角度渲染奶牛图像,并返回以下内容:

一系列由奶牛网格渲染器生成的图像及其剪影的张量;与所有摄像机镜头一一对应的渲染器。

备注:在 generate_cow_renders 函数中实现网格渲染的工作原理请参考:
fit_textured_mesh.ipynb

target_cameras, target_images, target_silhouettes = generate_cow_renders(num_views=40)
print(f'Generated {len(target_images)} images/silhouettes/cameras.')

2. 初始化体积渲染器

初始化体积渲染器会从目标图像的每个像素发出一条射线,并沿射线采样一组间隔均匀的点。与每个射线点相对应的密度值和色值,可通过查询场景的体积模型中的相应位置获得。
渲染器由一个 raymarcher 和一个 raysampler 构成。

raysampler 负责从图像像素中发射射线,并沿着射线对点进行取样。此处使用的是 NDCGridRaysampler ,它符合标准的 PyTorch3D 坐标网格规范。

raymarcher 获得射线采样的密度和颜色,并将所有射线渲染成光线源像素的颜色和不透明度值。此处使用的是 EmissionAbsorptionRaymarcher ,它实现了标准的 Emission-Absorption Raymarching 算法。

# render_size 表示渲染图像各个边的像素大小,将其设置为与目标图像尺寸一致
# 也就是说将其渲染成与基准图像一样的尺寸
render_size = target_images.shape[1]# 渲染场景以(0,0,0)为中心,被限定在一个边长约等于 3.0 (国际单位)的边框内。
volume_extent_world = 3.0# 1) 实例化 raysampler
# 此处 NDCGridRaysampler 会生成一矩形图像网格的射线,其坐标遵循 pytorch3d 坐标规定
# 由于此处设定的体积是 128^3,因此取样 n_pts_per_ray=150
# 大致相当于每个体素都有一个射线点
# 进一步设置 min_depth=0.1,因为相机平面内的所有表面都超过了 0.1 单位
raysampler = NDCGridRaysampler(image_width=render_size,image_height=render_size,n_pts_per_ray=150,min_depth=0.1,max_depth=volume_extent_world,
)# 2) 实例化 raymarcher.
# 此处用的是标准 EmissionAbsorptionRaymarcher
# 它会沿着每条射线前进
# 将每条射线都渲染成一个单一的 3D 颜色向量和一个不透明度标量
raymarcher = EmissionAbsorptionRaymarcher()# 最后,用 raysampler 和 raymarcher 实例化体积渲染器
renderer = VolumeRenderer(raysampler=raysampler, raymarcher=raymarcher,
)

3. 初始化体积模型

接下来实例化场景的体积模型。这会使得 3D 空间量化为体积像素,其中每个体素都用体素 RGB 颜色的 3D 向量,和描述体素不透明度的密度标量(范围在[0-1]之间,数字越大不透明越高)来表示。

为了保证密度和颜色的取值范围在 [0-1] 之间,我们会在对数空间中表示体积颜色和密度。模型运行 forward 函数时, log-space 值会通过 sigmoid 函数传递,从而使得 log-space 值处于正确的取值范围。

此外, VolumeModel 还包含渲染器对象。这个对象在整个优化过程中保持不变。

本部分代码还定义了 huber 损失函数,它可以计算出渲染色和 mask 之间的差异。

4. 体积拟合

这一步,我们用可微分渲染来进行体积拟合。

为了拟合体积,我们从 target_camera 的视角进行渲染,并将渲染结果与观察到的 target_imagestarget_silhouettes 进行对比。

这种对比是通过评估的 target_images/rendered_imagestarget_silhouettes/rendered_silhouettes 之间的平均 huber(smooth-l1)误差来完成的。

5. 将优化后的场景体积进行可视化

最后,旋转场景体积的 y 轴,从多个视点进行渲染,将优化后的体积进行可视化。

def generate_rotating_volume(volume_model, n_frames = 50):logRs = torch.zeros(n_frames, 3, device=device)logRs[:, 1] = torch.linspace(0.0, 2.0 * 3.14, n_frames, device=device)Rs = so3_exponential_map(logRs)Ts = torch.zeros(n_frames, 3, device=device)Ts[:, 2] = 2.7frames = []print('Generating rotating volume ...')for R, T in zip(tqdm(Rs), Ts):camera = FoVPerspectiveCameras(R=R[None], T=T[None], znear = target_cameras.znear[0],zfar = target_cameras.zfar[0],aspect_ratio = target_cameras.aspect_ratio[0],fov = target_cameras.fov[0],device=device,)frames.append(volume_model(camera)[..., :3].clamp(0.0, 1.0))return torch.cat(frames)with torch.no_grad():rotating_volume_frames = generate_rotating_volume(volume_model, n_frames=7*4)image_grid(rotating_volume_frames.clamp(0., 1.).cpu().numpy(), rows=4, cols=7, rgb=True, fill=True)
plt.show()

6. 结论

本教程中演示了如何优化场景的 3D 立体构造,使已知视点的体积渲染与每个视点的观测图像相匹配。

教程中的渲染是使用 NDCGridRaysamplerEmissionAbsorptionRaymarcher 构成的 PyTorch3D 立体渲染器完成的。

为 2D 图像构建有纹理的立体形状

完整教程请查看: https://openbayes.com/console/openbayes/containers/oAYzp70wwPk/overview

参考:

https://ai.facebook.com/blog/-introducing-pytorch3d-an-open-source-library-for-3d-deep-learning/

https://github.com/facebookresearch/pytorch3d

PyTorch3D 立体隐式形状渲染:教你构建场景 3D 结构相关推荐

  1. PCL_Implicit Shape Model_隐式形状模型 ISM

    http://pointclouds.org/documentation/tutorials/implicit_shape_model.php 英文文档 本教程让我们学会implicit shape ...

  2. 教你构建MySQL主从结构,实现基于SSL加密的主从同步机制。

    实验环境RHEL6.4 admin1.tuchao.com    192.168.1.201    主服务器 admin2.tuchao.com    192.168.1.202    从服务器 先在 ...

  3. mysql主从同步加密_教你构建MySQL主从结构,实现基于SSL加密的主从同步机制

    实验环境RHEL6.4 admin1.tuchao.com    192.168.1.201    主服务器 admin2.tuchao.com    192.168.1.202    从服务器 先在 ...

  4. scala基础之隐式转换

    一 隐式转换 隐式转换函数,也被称作隐式视图,它是可以把一种类型转换成另外一种类型,进而可以使用另外一种类型的属性和方法,从而满足表达式的要求 语法格式:implicit def 函数名(参数名:参数 ...

  5. 14-Scala之隐式转换

    1.为什么要隐式转换 我们经常引入第三方库,但当我们想要扩展新功能的时候通常是很不方便的,因为我们不能直接修改其代码.scala提供了隐式转换机制和隐式参数帮我们解决诸如这样的问题. Scala中的隐 ...

  6. Scala篇—implicit隐式入门

    Scala篇-implicit隐式入门 一.implicit概述 1.简介 2.为什么需要implicit 3.隐式转换机制 4.隐式转换规则 5.使用implicit须知 二.Demo示例 1.隐式 ...

  7. “3D几何与视觉技术”全球在线研讨会第五期~隐式3D形状表示学习

    前几周跟大家分享了 3DGV 在线研讨会: "3D几何与视觉技术"全球在线研讨会(9月2日到12月16日) "3D几何与视觉技术"全球在线研讨会第二期 &quo ...

  8. react ——withRouter——页面隐式传值—嵌套路由——渲染方式——自定义导航组件

    withRouter import {Route,Switch,withRouter} from "react-router-dom" withRouter高阶组件增强组件--获取 ...

  9. 将隐式神经表示(INR)用于2D图像

    ©PaperWeekly 原创 · 作者 | 张一帆 学校 | 中科院自动化所博士生 研究方向 | 计算机视觉 以图像为例,其最常见的表示方式为二维空间上的离散像素点.但是,在真实世界中,我们看到的世 ...

最新文章

  1. python中文读音ndarray-numpy中的ndarray方法和属性
  2. PL/SQL 数据库连接工具的下载、安装与使用实例演示
  3. CF39C-Moon Craters【dp】
  4. java获取数组穷举_被BAT疯抢的Java工程师,都是怎么拿到年薪50W的offer
  5. oracle 索引 lob 迁移,Oracle 11g到19c迁移TB级lob表的酸爽
  6. GNS3 1.5.2 无法上传文件的解决办法
  7. ubantu20刷新DNS缓存的命令
  8. 自制solidworks图框步骤_SolidWorks教你如何快速制作工程图模板
  9. android 对话框窗口,Android 对话框详解(一)
  10. SEO自动外链工具推荐:站群推广利器SEO,在线批量发外链让新站快速收录
  11. 【git】git+码云上传代码
  12. K8S 创建 Deployment
  13. 28岁学Java晚不晚?快30学java还来得及吗?
  14. 1134: 字符串转换
  15. 关于C语言中“x++”和“++x”的问题
  16. wchar_t 转换 string std::string 转换 wchar_t
  17. 使用JSP从服务器下载文件的示例
  18. java json 中文_java读取json数据中文乱码解决
  19. 硬件电路(3)设计篇----为什么栅极型推挽电路不用上P下N?
  20. 黑客攻防从入门到精通 第7章及后文

热门文章

  1. 记一次Mysql数据恢复
  2. 读《猫城记》 | 人间失格
  3. 四巨头音源500GB合集-Spectrasonics omnisphere | Keyscape | Trilian | Stylus RMX 2020
  4. 使用Python中内置tkinter模块做一个简易的计算器
  5. ACPI相关(8)- ACPI Platform Error Interfaces
  6. 问卷中多选题如何分析?
  7. Net::OICQ 还可以登录qq
  8. Rust应用调用C语言动态库
  9. 驾照理论考试android应用
  10. 站长爆料:大量黑产利用高权重网站霸屏引流