NeRF必读:PixelNeRF
Posted Rick0xFFFFFF
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了NeRF必读:PixelNeRF相关的知识,希望对你有一定的参考价值。
NeRF必读:PixelNeRF
前言
NeRF从2020年发展至今,仅仅三年时间,而Follow的工作已呈井喷之势,相信在不久的将来,NeRF会一举重塑三维重建这个业界,甚至重建我们的四维世界(开头先吹一波)。NeRF的发展时间虽短,有几篇工作却在我研究的领域开始呈现万精油趋势:
- PixelNeRF----泛化法宝
- MipNeRF----近远景重建
- NeRF in the wild----光线变换下的背景重建
- Neus----用NeRF重建Surface
- Instant-NGP----多尺度Hash编码实现高效渲染
今天我们就来学习将NeRF泛化的万精油:PixelNeRF。
概述
总体来说PixelNeRF有以下两点比较厉害:
- 利用稀疏输入构建三维场景表达。
- 可以基于category泛化三维场景表达(在张三李四上训练,给张王五的照片就能生成王五了,但给张哈士奇不一定能行得通)。
背景
NeRF将空间中的一点
x
∈
R
3
\\mathbfx\\in \\mathbbR^3
x∈R3在方向
d
\\mathbfd
d上的观测结果描述为:
f
(
x
,
d
)
=
(
σ
,
c
)
f(\\mathbfx,\\mathbfd)=(\\sigma,\\mathbfc)
f(x,d)=(σ,c)
通过对函数inference出的
(
σ
,
c
)
(\\sigma,\\mathbfc)
(σ,c)积分就能渲染出2D图像:
C
^
(
r
)
=
∫
t
n
t
f
T
(
t
)
σ
(
t
)
c
(
t
)
d
t
\\mathbf\\hatC(r)=\\int^t_f_t_nT(t)\\sigma(t)\\mathbfc(t)dt
C^(r)=∫tntfT(t)σ(t)c(t)dt
其中
T
(
t
)
=
exp
(
−
∫
t
n
t
σ
(
s
)
d
s
)
T(t)=\\exp(-\\int^t_t_n\\sigma(s)ds)
T(t)=exp(−∫tntσ(s)ds)表示透射率,离镜头越远,透射率越低。
至于Loss就简单了:
L
=
∑
r
∈
R
3
∥
C
^
(
r
)
−
C
(
r
)
∥
2
2
\\mathcalL=\\sum_r \\in \\mathbbR^3\\Vert \\mathbf\\hatC(r)-\\mathbfC(r)\\Vert^2_2
L=r∈R3∑∥C^(r)−C(r)∥22
PixelNeRF指出了NeRF的不足:
NeRF的每个scene都是单独训练的,scene与scene之间并不能共享知识,这对于神经网络这种可以共享先验知识的模型来说是极大的浪费,PixelNeRF的提出希望能弥补这一缺憾。
Image-conditioned NeRF
为了解决NeRF不能共享scenes之间的知识的问题,作者提出了一种Image-conditioned的架构,该架构由两个组件构成:
- 1个全连接的图像编码器 E E E,该编码器给出的图像特征将与原图像逐像素对齐。
- 1个类NeRF的网络结构,给定空间位置 x \\mathbfx x和相应的编码特征 E ( I ) x E(I)_x E(I)x, NeRF网络输出该点的 ( σ , c ) (\\sigma,\\mathbfc) (σ,c)。
具体来说,结合下图与公式,就可以对PixelNeRF有一个非常清晰的认知:
首先该图分为三部分,分别是:
- CNN对图像进行编码
- NeRF网络inference: ( x , d , I ) → ( c , σ ) (\\mathbfx,d,I) \\rightarrow(\\mathbfc,\\sigma) (x,d,I)→(c,σ)
- Volume Rendering
CNN Encoder:编码图像得到一个feature 图,WHF, F是feature数量,将输出结果命名为 W W W, π \\pi π是一个将3维空间的点 x x x映射到二维图像上的点(u,v)的映射函数,则 W ( π ( x ) ) W(\\pi(x)) W(π(x))就表示三维点 x \\mathbfx x对应的二维像素的feature了
NeRF Network:
f
(
γ
(
x
)
,
d
;
W
(
π
(
x
)
)
)
=
(
σ
,
c
)
f(\\gamma(\\mathbfx),\\mathbfd;\\mathbfW(\\pi(x)))=(\\sigma,\\mathbfc)
f(γ(x),d;W(π(x)))=(σ,c)
其中 γ ( x ) \\gamma(\\mathbfx) γ(x)是position encoding。
Volume Rendering:和经典NeRF一致。
Incorporating Multiple Views
作者希望通过融合多视角下的观测来构建出更为逼真的三维表达。 如何融合呢?对于一个世界坐标系下的query point
x
\\mathbfx
x ,以及它的view direction
d
\\mathbfd
d, 给定N个相机视角,以及它的位姿:
P
(
i
)
=
[
R
(
i
)
t
(
i
)
]
\\mathbfP^(i)=[\\mathbfR^(i)\\space \\mathbft^(i)]
P(i)=[R(i) t(i)]
通过位姿变换,就可以求解出每个相机坐标系下
x
x
x的位姿了:
x
(
i
)
=
P
(
i
)
x
,
d
(
i
)
=
R
(
i
)
d
\\mathbfx^(i)=\\mathbfP^(i)\\mathbfx, \\space \\mathbfd^(i)=\\mathbfR^(i)\\mathbfd
x(i)=P(i)x, d(i)=R(i)d
作者在此将NeRF做了一个层级划分,采用了PointNet之类的思想,先通过一个initial layers(命名为
f
1
f_1
f1)获得一个中间向量:
V
(
i
)
=
f
1
(
γ
(
x
(
i
)
)
,
d
(
i
)
;
W
(
i
)
)
\\mathbfV^(i)=f_1(\\gamma(\\mathbfx^(i)),\\mathbfd^(i);\\mathbfW^(i))
V(i)=f1(γ(x(i)),d(i);W(i))
随后利用pooling 操作
ψ
\\psi
ψ将多个中间向量融合在一起:
(
σ
,
c
)
=
f
2
(
ψ
(
V
(
1
)
)
,
ψ
(
V
(
2
)
)
,
.
.
.
,
ψ
(
V
(
n
)
)
)
(\\sigma,\\mathbfc)=f_2(\\psi(\\mathbfV^(1)),\\psi(\\mathbfV^(2)),...,\\psi(\\mathbfV^(n)))
(σ,c)=f2(ψ(V(1)),ψ(V(2)),...,ψ(V(n)))
Result
效果不错:
好多文章都在用PixelNeRF: SceneRF, AutoRF等等,强推!要是喜欢本文就点个赞吧~
参考文献
Yu, Alex, et al. “pixelnerf: Neural radiance fields from one or few images.” Proceedings of the IEEE/CVF Conference on Computer Vision and Pattern Recognition. 2021.
辐射神经场算法——Wild-NeRF / Mipi-NeRF / BARF / NSVF / Semantic-NeRF / DSNeRF
辐射神经场算法——NeRF++ / Wild-NeRF / Mipi-NeRF / BARF / NSVF / Semantic-NeRF
辐射神经场算法——NeRF++ / Wild-NeRF / Mip-NeRF / BARF /NSVF / Semantic-NeRF / DSNeRF
原始的NeRF虽然效果很惊艳,但是其一个场景少则一两天的训练速度,以及对于输入图像质量和位姿的要求却不尽人意,因此,在NeRF提出来很短的时间内就衍生出了各种基于NeRF优化的方法,本文主要是对这些方法进行一个简单总结,但是建议先了解原始NeRF的算法原理再来阅读本博客,对于原始NeRF算法的介绍可以参考博客辐射神经场算法——NeRF算法详解
1. NeRF++
NeRF++原论文名为《NeRF++: Analyzing and Improving Nerual Radiance Fileds》,该论文主要包括两部分:一部分是分析了原始NeRF具备的Shape-Radiance Ambiguity问题,另一部分是提出了一个解决室外360度开放场景的渲染方案。
首先针对Shape-Radiance Ambiguity问题,作者做了如下一个实验:
作者先使用一个球形的模型去训练NeRF中的
σ
\\sigma
σ,然后再使用上左中的GT training view去训练NeRF中的
c
\\boldc
c,在相同视角下进行预测时发现即使在错误的
σ
\\sigma
σ分布下仍然能输出较好的图像质量,但是一旦更换视角(GT test view)就会输出如上左图的结果。造成该现象的原因正是View-Dependent的网络设计。但是如果我们一旦修改网络设计,将采样点的位置
x
x
x和方向
d
\\boldd
d都从网络的第一层输入的话,网络整体效果就会下降,如下图所示:
文章的第二部分介绍的室外360度开放场景的一种解决方案,在原始NeRF中,对于Front-View的开放场景,使用的一种名为NDT坐标系的方式(可以简单理解为逆深度),但是对于360度的开放场景NDT坐标系是搞不定的,因此作者提出了将360度开放场景的渲染分为两部分通过两个NeRF进行渲染,如下所示:
规定一个球体
B
=
(
x
,
y
,
z
)
:
x
2
+
y
2
+
z
2
=
1
B=\\left\\(x, y, z): \\sqrtx^2+y^2+z^2=1\\right\\
B=(x,y,z):x2+y2+z2=1:
球体内保持欧拉坐标系
(
x
,
y
,
z
)
(x, y, z)
(x,y,z),使用原始的NeRF用于渲染前景部分;
球体外通过一个四维向量
(
x
′
,
y
′
,
z
′
,
1
/
r
)
\\left(x^\\prime, y^\\prime, z^\\prime, 1 / r\\right)
(x′,y′,z′,1/r)表示,用于渲染背景部分,其中
x
′
2
+
y
′
2
+
z
′
2
=
1
x^\\prime 2+y^\\prime 2+z^\\prime 2=1
x′2+y′2+z′2=1用于表示方向,
0
<
1
/
r
<
1
0<1 / r<1
0<1/r<1用于表示距离,并且
x
′
,
y
′
,
z
′
∈
[
−
1
,
1
]
,
1
/
r
∈
[
0
,
1
]
x^\\prime, y^\\prime, z^\\prime \\in[-1,1], 1 / r \\in[0,1]
x′,y′,z′∈[−1,1],1/r∈[0,1],用于进行背景渲染的NeRF输入为
(
x
′
,
y
′
,
z
′
,
1
/
r
)
\\left(x^\\prime, y^\\prime, z^\\prime, 1 / r\\right)
(x′,y′,z′,1/r),输出则是
σ
out
,
c
out
\\sigma_\\text out , \\mathbfc_\\text out
σout ,cout .
那么接下来的问题就是当我们给定一个像素的射线
r
=
o
+
t
d
\\mathbfr=\\mathbfo+t \\mathbfd
r=o+td,当采样点位于球体外时如何求得四维向量
(
x
′
,
y
′
,
z
′
,
1
/
r
)
\\left(x^\\prime, y^\\prime, z^\\prime, 1 / r\\right)
(x′,y′,z′,1/r)呢?如下图所示:
我们给定不同采样点
p
\\mathbfp
p得到不同的半径
r
r
r,那么如果获得
x
′
,
y
′
,
z
′
x^\\prime, y^\\prime, z^\\prime
x′,y′,z′呢?上图中点
a
=
o
+
t
a
d
\\mathbfa=\\mathbfo+t_a \\mathbfd
a=o+tad,我们令
∣
o
+
t
a
d
∣
=
1
\\left|\\mathbfo+t_a \\mathbfd\\right|=1
∣o+tad∣=1就可以求得点
a
\\mathbfa
a的坐标,同理点
b
=
o
+
t
b
d
\\mathbfb=\\mathbfo+t_b \\mathbfd
b=o+tbd可以通过
d
T
(
o
+
t
b
d
)
=
0
\\mathbfd^T\\left(\\mathbfo+t_b \\mathbfd\\right)=0
dT(o+tbd)=0求得,那么我们根据
ω
=
arcsin
∣
b
∣
−
arcsin
(
∣
b
∣
⋅
1
r
)
\\omega=\\arcsin |\\mathbfb|-\\arcsin \\left(|\\mathbfb| \\cdot \\frac1r\\right)
ω=arcsin∣b∣−arcsin(∣b∣⋅r1)即可以对点
a
\\mathbfa
a方向进行渲染既可以得到点
p
\\mathbfp
p的方向
x
′
,
y
′
,
z
′
x^\\prime, y^\\prime, z^\\prime
x′,y′,z′,其实就是一个很简单的几何求解。解决了这个问题后就可以给出最后NeRF++的计算公式:
C
(
r
)
=
∫
t
=
0
t
′
σ
(
o
+
t
d
)
⋅
c
(
o
+
t
d
,
d
)
⋅
e
−
∫
s
=
0
t
σ
(
o
+
s
d
)
d
s
d
t
⏟
(i)
+
e
−
∫
s
=
0
t
′
σ
(
o
+
s
d
)
d
s
⏟
(ii)
⋅
∫
t
=
t
′
∞
σ
(
o
+
t
d
)
⋅
c
(
o
+
t
d
,
d
)
⋅
e
−
∫
s
=
t
′
t
σ
(
o
+
s
d
)
d
s
d
t
⏟
(iii)
.
\\beginaligned \\mathbfC(\\mathbfr)=& \\underbrace\\int_t=0^t^\\prime \\sigma(\\mathbfo+t \\mathbfd) \\cdot \\mathbfc(\\mathbfo+t \\mathbfd, \\mathbfd) \\cdot e^-\\int_s=0^t \\sigma(\\mathbfo+s \\mathbfd) d s d t_\\text (i) \\\\ &+\\underbracee^-\\int_s=0^t^\\prime \\sigma(\\mathbfo+s \\mathbfd) d s_\\text (ii) \\cdot \\underbrace\\int_t=t^\\prime^\\infty \\sigma(\\mathbfo+t \\mathbfd) \\cdot \\mathbfc(\\mathbfo+t \\mathbfd, \\mathbfd) \\cdot e^-\\int_s=t^\\prime^t \\sigma(\\mathbfo+s \\mathbfd) d s d t_\\text (iii) . \\endaligned
C(r)=(i)
∫t=0t′σ(o+td)⋅c(o+td,d)⋅e−以上是关于NeRF必读:PixelNeRF的主要内容,如果未能解决你的问题,请参考以下文章
论文笔记:Depth-supervised NeRF: Fewer Views and Faster Training for Free