GRAF: Generative Radiance Fields for 3D-Aware Image Synthesis

GRAF: Generative Radiance Fields for 3D-Aware Image Synthesis

Abstract

虽然二维生成对抗网络能够实现高分辨率的图像合成,它们在很大程度上缺乏对三维世界和图像形成过程的理解。因此,它们不能提供对相机视点或物体姿态的精确控制为了解决这个问题,最近的几种方法利用基于中间体素的表示可微渲染相结合。然而,现有的方法要么产生较低的图像分辨率,要么在分离相机和场景属性方面出现不足,例如,物体的身份可能随视点而变化在本文中,我们提出了一个辐射场的生成模型,该模型最近被证明是成功地用于单个场景的新视图合成。基于体素的表示相比,辐射场并不局限于三维空间的粗糙离散化,但允许解开摄像机和场景属性,同时在存在重建模糊性的情况下优雅地退化。通过引入一个多尺度的基于补丁的鉴别器,我们演示了高分辨率图像的合成,同时仅从未曝光的二维图像训练我们的模型。我们系统地分析了我们的方法在几个具有挑战性的合成和真实世界的数据集。我们的实验表明,辐射场是生成图像合成的一个强大的表示,导致三维一致的模型渲染高保真。

3 Method

我们考虑了三维感知图像合成的问题,生成高保真图像的任务,同时提供对相机旋转和平移的显式控制。我们主张用它的辐射场来表示一个场景,这样一个连续的表示尺度很好。图像分辨率和内存消耗,同时允许基于物理和无参数的投影映射。在下面,我们首先简要回顾了神经辐射场(NeRF)[36],它构成了所提出的生成辐射场(GRAF)模型的基础。

3.1 Neural Radiance Fields

3.2 Generative Radiance Fields

在这项工作中,我们感兴趣的是辐射场作为三维感知图像合成表示。与[36]相比,我们不假设单个场景有大量的摆姿势的图像。相反,我们的目标是学习一个模型,通过未曝光图像的训练来合成新的场景。更具体地说,我们利用一个对抗性框架来训练辐射场的生成模型(GRAF)。

 

图2显示了对我们的模型的概述。生成器Gθ相机矩阵K相机姿态ξ二维采样模式ν形状/外观代码zs∈Rm/za∈Rn作为输入,并预测图像补丁P鉴别器Dφ合成的补丁P与从真实图像i提取的补丁P进行比较。在推断时,我们预测每个图像像素的一个颜色值。然而,在训练时,这是太贵了。因此,我们预测一个固定大小的K×K像素的补丁,它被随机缩放和旋转,以为整个辐射场提供梯度

 

3.2.1 Generator

我们从姿态分布pξ中采样相机姿态ξ=[R|t]。在我们的实验中,我们使用在上半球均匀分布的相机位置,相机面向坐标系的原点。根据数据集的不同,我们也会均匀地改变相机到原点的距离。我们选择K,使主点在图像的中心。

 

ν=(u,s)决定了我们要生成的虚拟K×K补丁P(u,s)的中心u=(u,v)∈R2和尺度s∈R+。这使我们能够使用一个独立于图像分辨率的卷积鉴别器。我们从图像域Ω的均匀分布中随机抽取补丁中心u∼U(Ω)从均匀分布的s∼U([1,S])中随机抽取补丁尺寸s,其中S=min(W,H)/K,W和H表示目标图像的宽度和高度。此外,我们确保整个补丁都在图像域Ω内。形状和外观变量zsza分别来自形状和外观分布zspszaps绘制。在我们的实验中,我们对ps和pa都使用了一个标准的高斯分布

 

它描述了patch在图像域Ω中的每个像素的位置,如图3所示。请注意,这些坐标是实数,而不是离散的整数,这允许我们连续地计算辐射场。相应的3D射线P(u,s)相机姿态ξ内在K唯一确定。我们用r表示像素/射线索引,用dr表示归一化的三维射线射线数R表示,其中在训练中R=K2,在推理中R=WH

 

 

 

 

 

条件辐射场gθ的网络结构如图4所示。我们首先从x的位置编码形状编码zs中计算一个形状编码h密度头σθ将该编码转换为体积密度σ。为了预测3D位置x处的颜色c,我们将h与d的位置编码和外观代码za连接起来,并将得到的向量传递给一个颜色头cθ。我们独立于视点d和外观代码za来计算σ,以鼓励多视图的一致性同时分离形状和外观。这鼓励网络分别使用潜在代码zs和za来建模形状和外观,并允许在推理过程中分别操作它们。更正式地说,我们有:

 

所有的映射(hθ、cθ和σθ)都是使用具有ReLU激活的全连接网络来实现的。为了避免符号混乱,我们使用相同的符号θ来表示每个网络的参数

 

给定沿射线r的所有点的颜色和体积密度{(cir,σir)},我们使用等式 (3).中的体积渲染操作符得到射线r对应像素的颜色cr∈R3结合所有R射线的结果,我们将预测的斑片表示为p,如图2所示。

3.2.2 Discriminator

 

鉴别器Dφ是实现为一个卷积神经网络(见附件)将预测的补丁P与从数据分布pD中提取的真实图像I中提取的补丁P进行比较。为了从真实图像I中提取一个K×K补丁,我们首先从我们在上面用于绘制生成器补丁的相同的分布pν中绘制ν=(u,s)。然后,我们通过使用双线性插值法在二维图像坐标P(u,s)处查询I,对真实的patch P进行采样。下面,我们使用Γ(I,ν)来表示这种双线性采样操作。请注意,我们的鉴别器类似于PatchGAN[21],除了我们允许连续位移u和缩放s,而PatchGAN使用s=1。更重要的是,我们并不是基于s对真实图像I进行降采样,而是在稀疏位置查询I,以保留高频细节,见图3。

在实验中,我们发现一个具有共享权重的鉴别器对所有的补丁都是足够的,即使这些补丁是在不同尺度的随机位置采样的。请注意,比例尺决定了补丁的接受域。为了便于训练,我们首先从更大的接受域开始,以捕捉全局环境。然后,我们逐步采样具有较小的接受域的补丁,以细化局部细节。

3.2.3 Training and Inference

 

我们在我们的鉴别器中使用光谱归一化[37]和实例归一化[65],并使用RMSprop[27]训练我们的方法,生成器和鉴别器的学习率分别为0.0005和0.0001。在推理时,我们随机抽取zs、za和ξ,并预测图像中所有像素的颜色值。关于网络架构的详细信息可以在附件中找到。

5 Conclusion

我们引入了生成辐射场(GRAF)用于高分辨率三维感知图像合成。我们证明,与基于体素的方法相比,我们的框架能够生成具有更好的多视图一致性的高分辨率图像。然而,我们的研究结果仅限于具有单个对象的简单场景。我们相信,结合归纳偏差,例如,深度图或对称性,将允许将我们的模型扩展到未来更具挑战性的现实世界场景。

  • 1
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 3
    评论
以下是用C++实现拓扑排序的代码: ```c++ #include <iostream> #include <vector> #include <queue> template <typename T, typename WGT_T> std::vector<typename DASS::graf<T, WGT_T>::size_type> topsort(const DASS::graf<T, WGT_T>& g) { // 初始化入度为 0 的结点队列 std::queue<typename DASS::graf<T, WGT_T>::size_type> q; std::vector<typename DASS::graf<T, WGT_T>::size_type> in_degree(g.size(), 0); for (typename DASS::graf<T, WGT_T>::size_type u = 0; u < g.size(); ++u) { for (const auto& e : g[u]) { ++in_degree[e.v]; } } for (typename DASS::graf<T, WGT_T>::size_type u = 0; u < g.size(); ++u) { if (in_degree[u] == 0) { q.push(u); } } // 执行拓扑排序 std::vector<typename DASS::graf<T, WGT_T>::size_type> order; while (!q.empty()) { typename DASS::graf<T, WGT_T>::size_type u = q.front(); q.pop(); order.push_back(u); for (const auto& e : g[u]) { --in_degree[e.v]; if (in_degree[e.v] == 0) { q.push(e.v); } } } // 如果存在环,则说明无法进行拓扑排序 if (order.size() != g.size()) { throw std::runtime_error("The graph contains a cycle"); } return order; } ``` 使用方法如下: ```c++ DASS::graf<int, int> g(6); g[0].emplace_back(1, 1); g[0].emplace_back(2, 1); g[1].emplace_back(3, 1); g[2].emplace_back(3, 1); g[2].emplace_back(4, 1); g[3].emplace_back(5, 1); g[4].emplace_back(5, 1); std::vector<DASS::graf<int, int>::size_type> order = topsort(g); for (auto u : order) { std::cout << u << " "; } // 输出:0 2 1 4 3 5 ``` 上述代码中,我们使用了一个队列来存储入度为 0 的结点,然后依次访问队列中的结点并将其从图中删除。如果存在环,则说明无法进行拓扑排序,我们在最后抛出了一个运行时错误。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值