Wander's Whisper

--'Just do something,give destiny a reason to stir.'

NeRF

Wander's avatar

nerf

前言

鸽了很久并经历了一个期末周之后,本blog再次更新,这次的主题是3D/4D领域大名鼎鼎的NeRF。这次主要是学习的ECCV 2022 Tutorial—Neural Volumetric Rendering for Computer Vision,并且这次的三位主讲人正是NeRF的三位一作,也是很正统了。

PartI

NeRF 是什么?

NeRF全称是Neural Radiance Fields,是一种用于新视角合成(Novel View Synthesis)的先进技术。简单来说,它可以从一组静态的、在不同视角拍摄的二维图片中,学习并重建出一个逼真的三维场景。然后,你就可以从这个三维场景中渲染出任何你想要的、全新的二维视角图片,甚至可以制作出流畅的相机运镜动画。

  • 核心目标: 新视角合成(当然功能远远不止于此)

  • 输入: 从不同角度拍摄的同一个场景的多张二维图片,以及这些图片对应的相机位置和朝向参数。

  • 输出: 一个能够在该场景中渲染出任意新视角的模型。

NeRF 的核心原理

NeRF的核心思想是使用一个全连接的深度神经网络(通常是多层感知机,MLP,后面我们会发现mlp may be not necessary)来隐式地表示一个连续的三维场景。

将场景表示为辐射场

这个神经网络学习的是一个从三维空间点和二维观察方向到该点颜色和密度的映射。

输入:

  • 一个三维点的坐标 (x,y,z)(x, y, z)

  • 一个二维的观察方向 (θ,ϕ)(\theta, \phi)

关于这几个参数的详细定义,和体渲染时如何导出的问题可以参考原论文https://arxiv.org/pdf/2003.08934

输出:

  • 该点的颜色(Color) (R,G,B)(R, G, B)

  • 该点的体密度(Volume Density) σ\sigma

这个函数 F(x,y,z,θ,φ)>(R,G,B,σ)F(x, y, z, θ, φ) -> (R, G, B, σ) 就是所谓的“神经辐射场”。体密度 σ\sigma 可以理解为光线在该点被“挡住”的概率,或者说该点有多“实”。更具体地,我们把σ\sigma定义为该位置出现一个“粒子”的概率,对于实心的物体,我们当然认为σ=1\sigma=1,空白认为σ=0\sigma=0,而对于那些如烟雾之类的半透明物质,我们认为该物质是有一些随机运动的粒子所构成,每个位置出现粒子的概率介于0-1之间。

位置编码 (Positional Encoding)

由过去的研究表明,mlp虽然在理论上能拟合一切函数,但是总倾向于拟合那些更光滑,更“低频”的函数,这使得渲染后的图像会出现模糊。这里的直觉是,如果两个点挨得很近,mlp会认为这两个点的输出也相差不多,这对于边缘上的点来说,就带来了模糊问题。(具体理论分析详见Neural Tangent Kernel: Convergence and generalization in neural networks

为了让神经网络能够学习到场景中的高频细节(比如精细的纹理,突变的边缘),NeRF对输入的坐标和方向进行了“位置编码”,将其映射到更高维度的空间。这使得模型能够更好地捕捉场景的细节变化。

正余弦编码

最简单的,就是类似transformer的原始编码技术,正余弦编码 γ(p)=(sin20πp,cos20πp,,sin2L1πp,cos2L1πp)γ(p) = (sin2^0πp , cos 2^0πp , ··· , sin2^{L−1}πp , cos 2^{L−1}πp) 对三个维度分别按上式进行编码,最后能使得原本很近的点在高维空间中被拉开。

Feature grid

在深度学习end-to-end的时代,我们当然希望位置编码也可以学习 (learnable)。最直接的思路是,学习正弦函数的相位和频率但它存在 全局干扰(Global dependency) 的问题:当你优化场景的一处细节,会无意中改变全空间的频率分布。为了追求更快的速度,我们开始使用特征网络:

不再用公式算,而是直接在空间格子(Voxel)里存特征。这让优化变成了“局部”的,训练速度瞬间提升百倍。

解决块状感:通过“三线性插值 + 激活函数”,即便是离散的格子也能渲染出极其平滑锐利的边缘。

压缩的艺术

3D 网格非常吃显存,本章介绍了三种主流的压缩方案:

稀疏性 (Sparsity):删掉没有物体的空房间。

低秩近似 (Low Rank):如 TensoRF,将 3D 立方体拆解为 2D 平面和 1D 向量的乘积,极大地节省了内存。

字典/哈希方法 (Dictionary/Hash):如 Instant-NGP,用哈希表映射特征。这是目前最强的技术方案,它通过“多层哈希结构”化解了冲突,实现了极速训练。

体渲染 (Volume Rendering)

当我们要从某个新的虚拟相机视角渲染一张图片时,NeRF使用了经典的“体渲染”技术。

光线投射:

从虚拟相机的每个像素中心,向场景中投射一条光线。

沿光线采样:

在这条光线上,均匀或非均匀地采集一系列三维采样点。

查询网络:

对于每一个采样点,将其坐标和光线的观察方向输入到已经训练好的NeRF神经网络中,得到该点的颜色 (R,G,B)(R, G, B) 和体密度 σ\sigma

颜色积分:

最后,沿着光线将所有采样点的颜色和密度进行积分(在实践中是离散求和),计算出该光线最终到达相机的颜色。密度越高的点,对最终颜色的贡献权重就越大。

这个积分公式大致如下:

C(r)=T(t)σ(r(t))c(r(t),d)dtC(r) = ∫ T(t) * σ(r(t)) * c(r(t), d) dt 其中 T(t)T(t) 是光线从起点到 tt 点的透射率(即没有被遮挡的概率,可由σ\sigma算出,具体推导见tutorial,用到了一点分析的技巧)。这个积分实际上也可以理解为光线第一次撞到的粒子的颜色的期望。

Notes:这里也并不非得要是颜色,可以换成任意一种属性,对任一种属性进行渲染。比如说对期望深度进行渲染就得到了depth map。

训练过程

NeRF的训练过程就是优化神经网络的权重,使其能够准确地表示给定的场景。

损失函数:

训练时,从一个已知的训练视角渲染一张图片,然后将渲染出的图片与该视角下真实的图片进行比较。损失函数就是这两张图片之间每个像素颜色值的均方误差(Mean Squared Error)。

优化:

通过反向传播算法,不断调整神经网络的权重,使得渲染出的图片与真实图片越来越接近。

NeRF的优缺点

优点

高质量和真实感: NeRF可以生成非常逼真、细节丰富的新视角图像。

连续表示: 场景是连续表示的,理论上可以渲染出无限多个新视角。

视图一致性: 在不同视角之间切换时,场景的几何和外观保持高度一致。

缺点

训练和渲染速度慢: 原始的NeRF需要很长的时间来为单个场景训练一个模型,并且渲染新视角的速​​度也很慢。

需要精确的相机位姿: 输入的图片需要有准确的相机内外参数,这在实际应用中可能难以获取。

静态场景: 原始NeRF只能处理静态场景。

泛化能力差: 为一个场景训练的模型不能直接用于另一个场景。

NeRF 的应用和发展

由于NeRF的巨大潜力,学术界和工业界涌现了大量的改进和扩展工作,主要集中在:

提升速度: Plenoxels, Instant-NGP等工作极大地提升了训练和渲染速度。

动态场景: D-NeRF, Nerfies等工作使其能够处理动态和变形的场景。

大规模场景: Block-NeRF等工作能够重建城市级别的巨大场景。

可编辑性: 允许用户对重建的三维场景进行编辑。

减少输入依赖: 从更少甚至单张图片重建场景。

应用领域:

3D内容创作(游戏、电影)

虚拟现实(VR)和增强现实(AR)

电子商务(产品360度展示)

自动驾驶(场景模拟)

数字人与元宇宙

Comments

NeRf给我最大的启发是在神经网络的用途上,一开始入门是从卷积开始到transformer(gpt,vit),神经网络主要起到一个特征提取和信息融合的作用(从强到弱的归纳偏置),这部分就可解释性比较差,我们无法定义这些神经网络究竟在拟合什么样的一个函数,真正起到了什么功能。而 在diffusion中,我们是人为定义了一整个扩散的过程,然后用一个神经网络去估计噪声,这是有明确含义的。再到NeRf这里,我们直接用神经网络去拟合物体坐标到属性的映射,也是具有明确含义的。这说明神经网络的设计还是从需求出发,要拟合怎样的函数就设计怎样的神经网络,并不仅仅局限于特征提取啊,attention啊这样的功能,也算是拓宽了思路。

PartII

D-NeRF

既然nerf可以较好地表征静态的3D scene,很自然地,我们会问是否可以拓展到4D?最直接的思路是将原本5维的输入增加一个时间维度,变成6维。但是我们思考一下会发现,这个方案有一些本质的问题

  • 场景越复杂,直接映射需要的网络参数就越巨大,且极难收敛。因为场景中存在极多的冗余,很多地方在不同时间点是不变的。
  • 网络不知道 t=1t=1 时刻的手和 t=2t=2 时刻的手是同一个东西。它可能会在 t=1t=1 学习一只红色的手,在 t=2t=2 学习一只蓝色的手。因为对于网络来说,tt 只是一个普通的输入维度,它没有“物体应该保持长相不变”的概念。这会导致渲染出来的视频出现严重的闪烁 (Flickering)。
  • 网络知道这一秒这里是红色的,下一秒那里是红色的,但不知道是“这块红色”挪到了“那个地方”。无法提取物体的运动速度、加速度。无法做运动追踪、慢动作插帧。

故而D-NeRF给出了一个方法:学习形变场,即学习那个Δx\Delta x。这个思路似乎在深度学习出现过很多次了,学习残差好像就是更简单。

算法架构:双网络解耦

D-NeRF 不直接学习 (x,y,z,t)Color(x, y, z, t) \to Color,而是通过两个子网络协同工作:

模块名称输入输出角色
变形网络 (Deformation MLP)当前点坐标 x\mathbf{x}, 时间 tt位置偏移量 Δx\Delta \mathbf{x}搬运工:负责计算点在 tt 时刻挪动了多少。
标准网络 (Canonical MLP)变换后的坐标 x+Δx\mathbf{x} + \Delta \mathbf{x}颜色 c\mathbf{c}, 密度 σ\sigma仓库:负责存储物体在“初始状态”下的几何和外观。

核心数学思想

对于空间中任意一点在时刻 tt 的状态,其渲染方程可以表达为: M(x,t)=Ψcanonical(x+Δx,whereΔx=Φdeformation(x,t))M(x,t)=Ψ_ {canonical}(x+Δx,where Δx=Φ _{deformation}(x,t))

三大技术亮点

  • 利用时间冗余 (Temporal Redundancy):

不需要为每一帧单独建模。通过强制所有时间帧共享同一个“标准空间”,极大减少了参数量,并保证了物体在运动过程中外观的一致性(不会闪烁)。

  • 单视角 4D 重建 (Single-view Reconstruction):

核心逻辑:只要物体自己在动,即便相机不动,D-NeRF 也能通过时间轴收集物体的不同部位(如转身后的背部),拼凑成一个完整的 3D 模型。

  • 光影建模:

变形模拟光影:D-NeRF 并不显式计算阴影变化。它通过微小的坐标拉伸(Warping),将当前点映射到标准空间中颜色较暗或较亮的区域,从而“借用”颜色来模拟阴影和高光。

局限性

  • 拓扑突变难处理:如果物体发生了断裂、融合(如水滴分离),单纯的坐标偏移映射很难表达。以及光影变换我认为也有些问题,因为原文中作者虽然说可以“借用别处的阴影”,但是这在本质上违反了模型“场景中物体不出现或消失”的假设。

  • 计算压力大:每一条光线的采样点都要跑两次 MLP,导致训练和渲染速度极慢。

  • 物理真实感:光影变化本质上是由于空间拉伸实现的,导出 Mesh 时可能会在表面产生微小的几何畸变。