NeRF学习笔记
概述:
-
重建:根据目前有的不同角度二维图片,重建三维物体。
用 MLP 网络学 Scene Representation,以实现 输入源图像对应的三维空间坐标和相机视角 ( x , y , z , θ , ϕ ) (x,y,z,\theta,\phi) (x,y,z,θ,ϕ);输出 ( R , G , B , σ ) (R,G,B,\sigma) (R,G,B,σ) ,分别表示RGB 颜色值和体素密度 。
-
训练兼渲染:由 Volume Rendering 生成预测的 2D image。
- 让摄像机光线穿过场景,生成一组采样的3D点
- 利用这些点及其对应的二维观察方向作为神经网络的输入,产生一组颜色和密度的输出
- 使用经典的体积渲染技术,将这些颜色和密度积累到一个二维图像中
- 预测的 2D image 和 ground truth image 之间算 L2 loss,继而再对MLP进行优化。
总体过程如下:
1 实现过程
1.1 相机参数:如何通过不同角度的照片得出输入数据
流程总结:
-
数据预处理
-
给定一组图片,利用colmap软件得到外参内参
-
之后将上面的colmap格式转化成llff格式,此时共有17个参数(12个外参、3个内参、2个范围表示)
-
-
输入
- 取成像平面中某一位置(对应的real像素值是已知的),与相机位置的连线构成一条射线,先得到在相机坐标系下的射线方向向量,之后利用外参逆矩阵(c2w)转换到世界坐标系下。
- 在最近和最远距离内采样 n 个点,得到三维的位置参数,构成n个五维向量即为输入。
补充知识点:
-
齐次坐标系
如果一个点在无穷远处,这个点的坐标将会 ( ∞ , ∞ ) (\infty,\infty) (∞,∞),在欧氏空间中,这就变得没有意义。如果使用齐次坐标,平行线在透视空间的无穷远处交于一点,这样就实现了对于无穷点的表示。
简而言之,齐次坐标就是用N+1维来代表N维坐标
我们可以在一个2D笛卡尔坐标末尾加上一个额外的变量w来形成 2D齐次坐标。因此,一个在笛卡尔坐标系下的点 ( X , Y ) (X, Y) (X,Y)在齐次坐标里面变成了 ( x , y , w ) (x,y,w) (x,y,w),并且有:
X = x w ; Y = y w X=\frac{x}{w};Y=\frac{y}{w} X=wx;Y=wy
例如笛卡尔坐标系下(1,2),在齐次坐标系中可以表示为(1,2,1),如果点(1,2)移动到无限远处,在笛卡尔坐标下它变为 ( ∞ , ∞ ) (\infty,\infty) (∞,∞),然后它的齐次坐标表示为(1,2,0)。注意这样的话,我们可以不用 ” ∞ \infty ∞" 来表示一个无穷远处的点了。另外注意方向向量的齐次坐标第四维等于0,点坐标第四维等于1。
参考:什么是齐次坐标系?为什么要用齐次坐标系? - 知乎 (zhihu.com)
-
相机坐标系:
为了建立3D空间点到相机平面的映射关系以及多个相机之间的相对关系,我们会对每一个相机定义一个局部的相机坐标系。下图为常见的坐标系定义习惯。
-
相机的内外参数
-
相机外参
相机外参是一个4x4的矩阵 M,其作用是将世界坐标系的点 P w o r l d = [ x , y , z , 1 ] P_{world}=[x,y,z,1] Pworld=[x,y,z,1] 变换到相机坐标系 P c a m e r a = M P w o r l d P_{camera}=MP_{world} Pcamera=MPworld下。我们也把相机外参叫做world-to-camera (w2c)矩阵。而NeRF主要使用camera-to-world (c2w)矩阵,即相机外参的逆矩阵,其作用是把相机坐标系的点变换到世界坐标系。
c2w矩阵的值直接描述了相机坐标系的朝向和原点:
-
相机内参
相机的内参矩阵将相机坐标系下的3D坐标映射到2D的图像平面,这里以针孔相机(Pinhole camera)为例介绍相机的内参矩阵K:
内参矩阵K包含4个值,其中fx和fy是相机的水平和垂直焦距(对于理想的针孔相机,fx=fy)。焦距的物理含义是相机中心到成像平面的距离,长度以像素为单位。cx和cy是图像原点相对于相机光心的水平和垂直偏移量。cx,cy有时候可以用图像宽和高的1/2近似,实际在使用中,内参只记录三个值 ( F , H , W ) (F,H,W) (F,H,W)
-
-
由colmap到llff:
由imgs2poses.py来实现
-
3D空间射线怎么构造
首先3D像素点的x和y坐标是2D的图像坐标 (i, j)减去光心坐标 (cx,cy),然后z坐标其实就是焦距f (因为图像平面距离相机中心的距离就是焦距f)。所以我们就可以得到射线的方向向量是 ( i − c x , j − c y , f ) − ( 0 , 0 , 0 ) = ( i − c x , j − c y , f ) (i-c_x,j-c_y,f)-(0,0,0)=(i-c_x,j-c_y,f) (i−cx,j−cy,f)−(0,0,0)=(i−cx,j−cy,f),因为是向量,我们可以把整个向量除以焦距f归一化z坐标,得到 ( i − c x f , j − c y f , 1 ) (\frac{i-c_x}{f},\frac{j-c_y}{f},1) (fi−cx,fj−cy,1)
参考:NeRF代码解读-相机参数与坐标系变换 - 陈冠英的文章 - 知乎
1.2 MLP
由 ( x , y , z , θ , ϕ ) (x,y,z,\theta,\phi) (x,y,z,θ,ϕ)到 ( R , G , B , σ ) (R,G,B,\sigma) (R,G,B,σ)由MLP来完成,结构如下:
其中 ( θ , ϕ ) (\theta,\phi) (θ,ϕ)只会影响颜色值而不影响密度 σ \sigma σ,所以采用了这样的结构。
1.3 体积渲染及离散化
对于一张图片上的每一个像素点,我们首先根据相机位姿生成一条射线,之后在一条射线上
[
t
n
,
t
f
]
[t_n,t_f]
[tn,tf]之间等分成n份进行采样:
t
i
∼
U
[
t
n
+
i
−
1
N
(
t
f
−
t
n
)
,
t
n
+
i
N
(
t
f
−
t
n
)
]
(1)
t_i\sim\mathcal{U}\bigg[t_n+\frac{i-1}{N}(t_f-t_n),t_n+\frac{i}{N}(t_f-t_n)\bigg] \tag{1}
ti∼U[tn+Ni−1(tf−tn),tn+Ni(tf−tn)](1)
之后2D图片上对应位置的颜色可以离散化计算:
C
^
(
r
)
=
∑
i
=
1
N
T
i
(
1
−
exp
(
−
σ
i
δ
i
)
)
c
i
,
where
T
i
=
exp
(
−
∑
j
=
1
i
−
1
σ
j
δ
j
)
(2)
\hat{C}(\mathbf{r})=\sum\limits_{i=1}^N T_i(1-\exp(-\sigma_i\delta_i))\mathbf{c}_i,\text{where}T_i=\exp\left(-\sum\limits_{j=1}^{i-1}\sigma_j\delta_j\right) \tag{2}
C^(r)=i=1∑NTi(1−exp(−σiδi))ci,whereTi=exp(−j=1∑i−1σjδj)(2)
这样我们就能得到图片上每个像素点的颜色。
详细过程可看:体渲染公式推导
1.4 优化点
-
位置编码
γ ( p ) = ( sin ( 2 0 π p ) , cos ( 2 0 π p ) , ⋯ , sin ( 2 L − 1 π p ) , cos ( 2 L − 1 π p ) ) (3) \gamma(p)=\left(\sin\left(2^0\pi p\right),\cos\left(2^0\pi p\right),\cdots,\sin\left(2^{L-1}\pi p\right),\cos\left(2^{L-1}\pi p\right)\right)\tag{3} γ(p)=(sin(20πp),cos(20πp),⋯,sin(2L−1πp),cos(2L−1πp))(3)
把输入的值进行傅里叶级数分解,便于提取其中的高维特征,神经网络会达到更好的效果。其中, L = 10 L=10 L=10用于 ( x , y , z ) (x,y,z) (x,y,z)三个坐标值, L = 4 L=4 L=4用于方向向量 γ ( d ) \gamma(\mathbf{d}) γ(d)
-
Hierarchical volume sampling
进行两次采样(coarse和fine)
-
第一次coarse均匀采样( N c N_c Nc = 64),用公式(3)来表示出颜色,稍微变化一下形式:
C ^ c ( r ) = ∑ i = 1 N c w i c i , w i = T i ( 1 − exp ( − σ i δ i ) ) (4) \hat{C}_c(\mathbf{r})=\sum\limits_{i=1}^{N_c}w_ic_i,w_i=T_i(1-\exp(-\sigma_i\delta_i))\tag{4} C^c(r)=i=1∑Ncwici,wi=Ti(1−exp(−σiδi))(4)
这样就得出了每个采样点的权重。之后进行归一化: w ^ i = w i / ∑ j = 1 N c w j \hat{w}_i=^{w_i}/\sum_{j=1}^{N_c}w_j w^i=wi/∑j=1Ncwj,这样就表示成了一个分段的常数概率密度函数PDF。
-
第二次fine采样,在第一次采样得出的PDF上进行逆变换采样( N f = 128 N_f=128 Nf=128),之后用总的采样点( N c + N f N_c+N_f Nc+Nf)训练网络,得到 C ^ f ( r ) \hat{C}_f(\mathbf{r}) C^f(r)
采样完成后进行训练,损失函数是:
L = ∑ r ∈ R [ ∥ C ^ c ( r ) − C ( r ) ∥ 2 2 + ∥ C ^ f ( r ) − C ( r ) ∥ 2 2 ] \mathcal{L}=\sum\limits_{\mathbf{r}\in\mathcal{R}}\left[\left\|\hat{C}_c(\mathbf{r})-C(\mathbf{r})\right\|_2^2+\left\|\hat{C}_f(\mathbf{r})-C(\mathbf{r})\right\|_2^2\right] L=r∈R∑[ C^c(r)−C(r) 22+ C^f(r)−C(r) 22]
虽然最终的渲染来自 C ^ f ( r ) \hat{C}_f(\mathbf{r}) C^f(r),但我们也最小化了 C ^ c ( r ) \hat{C}_c(\mathbf{r}) C^c(r)的损失,以便可以利用来自粗网络的权值分布在精细网络中分配样本。文章来源:https://www.toymoban.com/news/detail-455960.html -
参考文献和资料
[1]:NeRF: Representing Scenes as Neural Radiance Fields for View Synthesis
[2]:NeRF代码解读-相机参数与坐标系变换 - 陈冠英的文章 - 知乎
[3]:“图形学小白”友好的NeRF原理透彻讲解文章来源地址https://www.toymoban.com/news/detail-455960.html
到了这里,关于【NeRF】(一)NeRF论文学习笔记的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!