【NeRF】(一)NeRF论文学习笔记

NeRF学习笔记

概述:

  1. 重建:根据目前有的不同角度二维图片,重建三维物体。

    用 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 颜色值和体素密度 。

  2. 训练兼渲染:由 Volume Rendering 生成预测的 2D image。

    • 让摄像机光线穿过场景,生成一组采样的3D点
    • 利用这些点及其对应的二维观察方向作为神经网络的输入,产生一组颜色和密度的输出
    • 使用经典的体积渲染技术,将这些颜色和密度积累到一个二维图像中
    • 预测的 2D image 和 ground truth image 之间算 L2 loss,继而再对MLP进行优化。
    image-20230514134217989

总体过程如下:

img

1 实现过程

1.1 相机参数:如何通过不同角度的照片得出输入数据

流程总结:

  • 数据预处理

    • 给定一组图片,利用colmap软件得到外参内参

    • 之后将上面的colmap格式转化成llff格式,此时共有17个参数(12个外参、3个内参、2个范围表示)

  • 输入

    • 取成像平面中某一位置(对应的real像素值是已知的),与相机位置的连线构成一条射线,先得到在相机坐标系下的射线方向向量,之后利用外参逆矩阵(c2w)转换到世界坐标系下。
    • 在最近和最远距离内采样 n 个点,得到三维的位置参数,构成n个五维向量即为输入。

补充知识点:

  1. 齐次坐标系

    如果一个点在无穷远处,这个点的坐标将会 ( ∞ , ∞ ) (\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)

  2. 相机坐标系:

    img

    为了建立3D空间点到相机平面的映射关系以及多个相机之间的相对关系,我们会对每一个相机定义一个局部的相机坐标系。下图为常见的坐标系定义习惯。

    img
  3. 相机的内外参数

    • 相机外参

      相机外参是一个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)矩阵,即相机外参的逆矩阵,其作用是把相机坐标系的点变换到世界坐标系。

      img

      c2w矩阵的值直接描述了相机坐标系的朝向和原点:

      img
    • 相机内参

      相机的内参矩阵将相机坐标系下的3D坐标映射到2D的图像平面,这里以针孔相机(Pinhole camera)为例介绍相机的内参矩阵K:

      img

      内参矩阵K包含4个值,其中fx和fy是相机的水平和垂直焦距(对于理想的针孔相机,fx=fy)。焦距的物理含义是相机中心到成像平面的距离,长度以像素为单位。cx和cy是图像原点相对于相机光心的水平和垂直偏移量。cx,cy有时候可以用图像宽和高的1/2近似,实际在使用中,内参只记录三个值 ( F , H , W ) (F,H,W) (F,H,W)

  4. 由colmap到llff:

    imgs2poses.py来实现

  5. 3D空间射线怎么构造

    img

    首先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) (icx,jcy,f)(0,0,0)=(icx,jcy,f),因为是向量,我们可以把整个向量除以焦距f归一化z坐标,得到 ( i − c x f , j − c y f , 1 ) (\frac{i-c_x}{f},\frac{j-c_y}{f},1) (ficx,fjcy,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来完成,结构如下:

image-20230514151206071

其中 ( θ , ϕ ) (\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} tiU[tn+Ni1(tftn),tn+Ni(tftn)](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=1NTi(1exp(σiδi))ci,whereTi=exp(j=1i1σjδj)(2)
这样我们就能得到图片上每个像素点的颜色。

详细过程可看:体渲染公式推导

1.4 优化点

  1. 位置编码
    γ ( 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(2L1πp),cos(2L1π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)

  2. 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=1Ncwici,wi=Ti(1exp(σ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=rR[ 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)的损失,以便可以利用来自粗网络的权值分布在精细网络中分配样本。

参考文献和资料
[1]:NeRF: Representing Scenes as Neural Radiance Fields for View Synthesis
[2]:NeRF代码解读-相机参数与坐标系变换 - 陈冠英的文章 - 知乎
[3]:“图形学小白”友好的NeRF原理透彻讲解

猜你喜欢

转载自blog.csdn.net/weixin_62012485/article/details/130815797