對于NeRF,可以先回顧NeRF神經輻射場ECCV2020;
首先,我們需要準備多張從不同角度拍攝的同一場景的2D圖像,然后用COLMAP估計與相機相關的參數
,通過COLMAP可以得到場景的稀疏重建結果,其輸出文件包括相機內參,相機外參和3D點的信息,然后進一步利用LLFF開源代碼中的imgs2poses文件將內外參整合到一個文件poses_boudns.npy中,假設該場景有
N NN張圖像,則poses_boudns.npy存儲了一個形狀為 N × 17 N\times17 N×17的數組,對于每一行,即每張圖像,存儲以下信息:
* 該文件記錄了相機的內參:包括圖片分辨率(圖片高度與寬度)、焦距,共3個維度;
* 外參:包括世界坐標到相機坐標轉換的平移矩陣 t ∈ R 3 × 1 \textbf{t}\in R^{3\times1} t∈R3×1與旋轉矩陣 R
∈ R 3 × 3 \textbf{R}\in R^{3\times3}R∈R3×3,共3+9=12維;
通常,三維場景或3D對象上的每個點 ( x , y , z ) (x,y,z) (x,y,z)
是在世界坐標下定義的。坐標1下的位置變換到坐標2下的位置可以利用線性變換完成。
* 另外還有光線的始發深度和終止深度,共2維(COLMAP根據粗略重建的場景大小范圍確定光線的深度范圍);
論文中提到MLP的輸入是 ( x , y , z , θ , ? ) (x,y,z,\theta,\phi) (x,y,z,θ,?)
是什么,和相機內參外參有什么聯系?要明白這個問題,先要理解坐標變換。
總的來說,坐標變換的目的在于將不同視角下視角特定的坐標系投影到一個統一的世界坐標中進行三維重建,見get_rays_np函數。首先,我們在像素坐標下進行網格點采樣,得到特定分辨率圖像的各個像素點坐標。
然后,進行像素坐標到相機坐標的變換。像素坐標到相機坐標的變換屬于投影變換的逆變換,即2D點到3D的變化,即我們需要根據像素點的坐標 ( u , v )
(u,v)(u,v)計算該像素點在相機坐標系下的三維坐標 ( x c , y c , z c ) (x_c,y_c,z_c) (xc?,yc?,zc?);
然后,我們進行相機坐標到世界坐標的轉換得到光線始發點與方向向量:
*
首先因為相機坐標與世界坐標的坐標原點不一致,要解決這個問題只需要將相機坐標進行平移即可進行對齊,實現平移的方式在是相機坐標系下減去一個平移矩陣,即相機外參中的平移矩陣
t \textbf{t}t;
*
此外,由于相機坐標與世界坐標的各個軸的朝向也是不同的,因此需要進一步通過旋轉來對齊坐標軸的朝向,實現旋轉的方式是在平移對齊坐標原點之后的基礎上進行旋轉,即與相機外參中的旋轉矩陣
R \textbf{R}R的逆做矩陣乘法;最后我們得到 r o \textbf{r}_{o} ro?(像素是光線渲染的, r o \textbf{r}_{o}
ro?相當于是世界坐標下的當前光線出發位置,詳情看圖1)和得到 r d \textbf{r}_{d} rd?(世界坐標下,當前光線的方向);
現在,我們通過了相機的內外參數將像素坐標轉換為了統一的世界坐標下的光線始發點與方向,結合深度 t t t
(范圍在光線的始發深度和終止深度內),可以得到當前光線上任意一點的位置 r ( t ) = r o + t r d
\textbf{r}(t)=\textbf{r}_{o}+t\textbf{r}_{d}r(t)=ro?+trd?;
*
圖1:觀察a,可以看到圖像,相機,真實場景的對應關系。相機射出光線穿過當前圖像的某個像素,我們從像素坐標開始(即圖像),然后獲得該像素在相機坐標下的位置,又獲得在世界坐標下的位置,此時的位置為光線的發出點
r o \textbf{r}_{o}ro?,結合光線的方向 r d \textbf{r}_{d} rd?
(相機連接該像素的方向),我們就能追蹤該光線上的每個點。
所以實際上,NeRF的MLP并不是5D的輸入 ( x , y , z , θ , ? ) (x,y,z,\theta,\phi) (x,y,z,θ,?),而是
r ( t ) \textbf{r}(t)r(t)(在世界坐標下看還是 ( x , y , z ) (x,y,z) (x,y,z))和標準化處理的 r d
\textbf{r}_{d}rd?(對應觀察方向 ( θ , ? ) (\theta,\phi) (θ,?),但 r d \textbf{r}_{d} rd?
是三維的);
渲染時,我們沿著 r d \textbf{r}_{d} rd?采樣出很多 r ( t ) \textbf{r}(t) r(t)
,對這些點上的MLP輸出的RGB結果求和作為最終的RGB。
注意NeRF中所說的觀察方向,嚴格來說,是相機連接某個像素的方向,因為我們要沿著這個方向去渲染得到像素的值。
今日推薦