OpenMVS中的PatchMatch算法筆記

本文主要記錄多視立體幾何中傳統(tǒng)算法使用得較廣的一個開源框架OpenMVS的一些實現(xiàn)流程、算法細節(jié)等,重點針對稠密重建部分,使用的是PatchMatch的方法,SGM的部分暫時不涉及。

基本流程

pipeline2.png

主要的數(shù)據(jù)結(jié)構(gòu)

OpenMVS在整個稠密重建這一塊,主要有幾個比較大的數(shù)據(jù)結(jié)構(gòu),分別是Scene,DenseDepthMapData及DepthEstimator,PatchMatchCUDA。前兩個為數(shù)據(jù)類,后兩個為深度估計的操作類,分別對應(yīng)CPU的實現(xiàn)和CUDA版本的實現(xiàn)。Scene主要是存儲輸入(相機內(nèi)外參,圖像,稀疏點云等)輸出(稠密點云)的,DenseDepthMapData主要是存儲中間過程的各個視角的深度圖。


scene.png
DenseDepthMapData.png

具體模塊介紹

Neighbor的選擇:SelectViews

多視幾何最核心的思想是確定同一個三維點在不同視角下的對應(yīng)像素,再利用三角法可以估計出深度信息。因此,對于每個reference圖像找到可以用來做重建的共視圖像就是首要的一步。在OpenMVS中,有多個數(shù)據(jù)結(jié)構(gòu)中有neighbor的出現(xiàn),Scene中的neighbor包含所有共視的圖像,而在DepthData中的neighbor則是從中做了一定挑選以后用來做重建的共視圖像,可以選多個,也可以只選一個。

選擇多個neighbor

neighbor的確認(rèn):在輸入的稀疏點云中,每個點都存儲了一個track,代表著哪些view可以看到它,于是對于當(dāng)前視角而言,能共同看到三個以上三維點的視角即為neighbor。

neighbor的排序:針對每個neighbor,會有一個評分,這個評分的維度主要是有三個,一個是三角化的角度,一個是相對于reference視角的scale,另一個是兩個視角的overlap。

對于稀疏重建中,當(dāng)前視角與neighbor視角都能看到的三維點,根據(jù)對應(yīng)點的關(guān)系,我們可以構(gòu)造如圖的三角化,對應(yīng)的角度即為三角化的角度。


angle.png

我們對于這個角度值進行一個打分,我們設(shè)置最理想的角度為\theta_{opt} = 15度,具體的公式如下:
w_{\theta}= \left\{ \begin{matrix} \left(\frac{\theta}{\theta_{opt}}\right)^{1.5}, & \theta < \theta_{opt} \\ \exp\left(-\frac{(\theta - \theta_{opt})^2}{2(\theta_{opt}*1.3)^2}\right), & \theta \geq \theta_{opt} \end{matrix} \right.

weight_angle.png

w_{\theta}的示意圖像可以知道,傾向于選擇接近理想角度的neighbor,同時對于小于理想角度的情形懲罰力度會比大于理想角度情形懲罰力度要大。這主要是說三角化只有達到一定的角度,基線才能夠足夠保證三維重建的可靠性及準(zhǔn)確性。

而對于每個公共三維點,scale的定義為s = \frac{f_1}{f_2}\frac{d_2}{d_1},其中f為相機焦距,而d為該三維點在對應(yīng)視角的深度。我們同樣對scale進行打分,設(shè)置了一個期望區(qū)間[1,1.6],對處于該區(qū)間之外的scale進行懲罰,具體的公式為:
w_{s}= \left\{ \begin{matrix} \left(\frac{1.6}{s}\right)^{2}, & s > 1.6 \\ 1.0, & 1.0 \leq s \leq 1.6 \\ s^2, & s < 1.0 \end{matrix} \right.

weight_scale.png

同樣,可以看到w_s主要懲罰那些scale大于1.6及小于1.0的情形。

兩個視角的overlap值w_{a},計算方式為找到兩個視角下overlap的三維點,然后投影到reference視角,此時將refrence視角的圖像化成16*16的格子,按投影點算像素的占有率,這個比例即當(dāng)做neighbor視角與reference視角的overlap值。

綜合上述三個維度,score的最終計算公式為
score = w_a\cdot\sum_{common~nodes} w_{\theta}\cdot w_{s}

根據(jù)score從大到小排序,我們可以截斷選擇成績最好的若干共視圖像用來重建。

選擇最優(yōu)neighbor

基于上面得到的共視圖像集合,我們也可以選擇最優(yōu)neighbor來進行重建。選擇最優(yōu)neighbor的策略比較復(fù)雜,本質(zhì)上是在求解一個馬爾科夫隨機場的優(yōu)化問題。我們定義view的編號為x_i \in [0, N-1],view x_i對應(yīng)的最優(yōu)neighbor為y(x_i)\in[0, N],這里需要注意的是當(dāng)yN時,代表這個view沒有找到適合的neighbor,它在接下來的重建中也將會被拋棄。求解最優(yōu)neighbor其實是在做一個全局優(yōu)化,優(yōu)化的代價函數(shù)為
\arg\min\limits_y ~E_{data}(x_i, y(x_i)) + E_{pairwise}(x_i, x_j)
其中,E_{data}描述的是當(dāng)view x_i選中某一個y的代價,而E_{pairwise}描述的則是,當(dāng)x_jx_i的其中一個neighbor時,兩者對應(yīng)的最優(yōu)neighbor相關(guān)性的一個代價??傮w的原則是,view x_i選中y的自身代價要小,同時還要盡量避免它和它的neighbor互為最優(yōu)選擇。這兩個代價的具體形式可以描述為
E_{data}(x_i, y(x_i))= \left\{ \begin{matrix} avgScore / score(x_i, y(x_i)), & y(x_i)\neq N \\ C_{none} * avgScore*r_{none}, & y(x_i)=N~且~x_i沒有neighbor\\ C_{none} * E_{data}(x_i, y(neighbor(x_i))), & y(x_i)=N~且~x_i有neighbor \end{matrix} \right.

E_{pairwise}(x_i, x_j) = \left\{ \begin{matrix} C_{penalty}, & 當(dāng)~y(x_i)=x_j~且~y(x_j)=x_i \\ C_{empty} + r*\frac{w_a(x_i, x_j)}{w_a(x_i, y(x_i))}, & 當(dāng)y(x_i)\neq N ~且~y(x_j)=N\\ C_{empty} + r*\frac{w_a(x_i, x_j)}{w_a(x_j, y(x_j))}, & 當(dāng)y(x_i)= N ~且~y(x_j)\neq N\\ r*\left(\frac{w_a(x_i, x_j)}{w_a(x_i, y(x_i))} + \frac{w_a(x_i, x_j)}{w_a(x_j, y(x_j))}\right), & 其他情形 \end{matrix} \right.

其中,avgScore對應(yīng)了x_i與所有neighbor的score值的平均,而C,r等都為預(yù)設(shè)的常數(shù),默認(rèn)參數(shù)中C_{none} = 6.0, r_{none} = 0.01, C_{penalty}=7.2, C_{empty} = 2.4, r = 0.3。E_{data}項比較好理解,E_{pairwise}項其實是懲罰兩個view互為最優(yōu)neighbor的情形,也同時懲罰找不到最優(yōu)neighbor的情形。

深度初始化:InitViews

初始化的時候主要干了如下幾件事情:

  1. 按照之前計算的scale值,將neighbor對應(yīng)的image重采樣至對應(yīng)大小,同時更新相應(yīng)的相機參數(shù);

  2. 去除一些score值過小的neighbor,這個閾值是動態(tài)設(shè)定的,默認(rèn)的是排名第一的neighbor對應(yīng)的score值的3%;

  3. 初始化當(dāng)前視角的深度及法向信息

這里重點介紹第3件事情。深度初始化的目的是要給reference圖像的每個像素找到一個初始的深度值及法向值,這里利用的在二維區(qū)域上的Delaunay分割來實現(xiàn)的。我們利用稀疏重建的點云,將其往圖像的二維區(qū)域上投影,通過Delaunay分割可以將圖像區(qū)域做一個三角剖分,同時保證上述二維投影點為三角形節(jié)點。如果加上圖像區(qū)域的4個角,則可以實現(xiàn)整個圖像區(qū)域的三角剖分。實際上,這些投影點都對應(yīng)有深度信息,我們通過把投影點按深度進行提升,就可以把二維區(qū)域的三角剖分轉(zhuǎn)化成一個三維的表面網(wǎng)格。在這里,由于圖像區(qū)域的4個角不一定對應(yīng)稀疏點云中的點,我們可以用平均深度來當(dāng)做其深度。有了上述表面網(wǎng)格以后,我們可以估計出節(jié)點位置的法向方向。同時對于二維區(qū)域的任何一個像素,可以往該表面網(wǎng)格豎直投影找到其三維位置,即可得到初始的深度值,其實也就是找到該像素所在的三角形,利用線性插值可以得到深度值。而法向值則對應(yīng)為該表面網(wǎng)格的三角片的法向方向。


init.png

深度估計CPU版本

深度估計的CPU版本主要是實現(xiàn)了如下參考文獻的算法

Shen, Shuhan. "Accurate multiple view 3d reconstruction using patch-based stereo for large-scale scenes." IEEE transactions on image processing 22.5 (2013): 1901-1914.

像素處理的順序

每個像素點都需要估計深度,CPU版本中,像素的處理時串行的,預(yù)先訂制好了一個處理的順序。在有些操作中,深度估計依賴于鄰域的一些信息,所以,這個順序?qū)罄m(xù)的處理還是有影響的。

zigzag.png

處理時,主要按照上圖中所示的順序來進行,當(dāng)該像素點位于mask之外時,則會被忽略。

匹配代價的計算:ScorePixel

給定一個reference圖像上的像素,patch對應(yīng)的圖像鄰域大小,其對應(yīng)的深度,對應(yīng)的法向等,即可找到它在所有neighbor圖像上的對應(yīng)像素及對應(yīng)patch,然后可以計算patch與patch之間的匹配代價,最后綜合所有的neighbor的匹配代價可以得到一個最終的聚合匹配代價。需要注意的是,reference圖像上的patch我們可以取成n\times n的方形鄰域,但經(jīng)過變換以后,方形鄰域每個像素都將在neighbor圖像上找到對應(yīng)點,這些對應(yīng)點圍成的patch就不再是方形的了,這是與基于極線校正方法計算匹配代價的比較大的不同。

按照上述說法,整個計算將分成幾部分

  1. 給定reference圖像的像素,及其深度,法向信息,如何確定變換矩陣(單應(yīng)矩陣)H,找到匹配像素?

  2. 單個neighbor圖像的匹配代價值是如何計算的?

  3. 聚合匹配代價是如何計算的?

單應(yīng)矩陣H的確定

給定兩個視角,其投影矩陣(將世界坐標(biāo)系的點投影到相機歸一化平面坐標(biāo)系的矩陣)分別為P_0 = [I|0]P_1 = [A|a],對于空間中的一個平面\pi^T X = 0,其中\pi = (v^T, 1)^T,則該平面上任意一點在兩個相機上的投影之間的關(guān)系可以由一個單應(yīng)矩陣來確定x'=Hx,這個單應(yīng)矩陣在齊次坐標(biāo)下可以表達為[1]
H=A-av^T
上式的推導(dǎo)如下。取平面上任一三維點X(X',Y',Z'),則其在第0個相機下的投影點x_0(x_0',y_0')滿足

\left( \begin{matrix} x_0'\\ y_0'\\ 1 \end{matrix} \right) = \rho_0 P_0 \left( \begin{matrix} X'\\ Y'\\ Z'\\ 1 \end{matrix} \right) = \rho_0 \left( \begin{matrix} X'\\ Y'\\ Z' \end{matrix} \right)
X在平面上,所以有v^TX + 1=0,用x_0代入,則有\rho_0 = - v^T(x_0,1).

該點在第一個相機下的投影點x_1(x_1', y_1')滿足
\left( \begin{matrix} x_1\\ 1 \end{matrix} \right) = \left( \begin{matrix} x_1'\\ y_1'\\ 1 \end{matrix} \right) = \rho_1 P_1 \left( \begin{matrix} X'\\ Y'\\ Z'\\ 1 \end{matrix} \right) = \rho_1 \left( AX+a \right) = \frac{\rho_1}{\rho_0} \left(A\left(\begin{matrix} x_0\\ 1 \end{matrix} \right)+ a \rho_0\right) = s (A-av^T)\left( \begin{matrix} x_0\\ 1 \end{matrix} \right)
這里的s代表的是該三維點在兩個相機坐標(biāo)系下深度的比例。

在當(dāng)前的場景中,我們?nèi)eference相機為0號相機,而neighbor相機為1號相機,不考慮內(nèi)參矩陣K的情況下,我們有
P_0= \left( \begin{matrix} R_0 & - R_0C_0\\ 0 & 1 \end{matrix} \right) ,~~ P_1= \left( \begin{matrix} R_1 & - R_1C_1\\ 0 & 1 \end{matrix} \right)
如果我們通過變換使得P_0 = [I|0],則P_1可以寫成
\begin{eqnarray*} P_1&=& \left( \begin{matrix} R_1 & - R_1C_1\\ 0 & 1 \end{matrix} \right) \left( \begin{matrix} R_0 & - R_0C_0\\ 0 & 1 \end{matrix} \right)^{-1} \\ &=& \left( \begin{matrix} R_1 & - R_1C_1\\ 0 & 1 \end{matrix} \right) \left( \begin{matrix} R_0^{-1} & C_0\\ 0 & 1 \end{matrix} \right)\\ &=& \left( \begin{matrix} R_1R_0^{-1} & R_1(C_0-C_1)\\ 0 & 1 \end{matrix} \right)\\ &=& [R_1R_0^{-1}|R_1(C_0-C_1)] \end{eqnarray*}
經(jīng)過點X的patch平面可以定義為
n^TX+d=0
其中,n為點X的法線,而d則代表了世界坐標(biāo)系原點到該平面的距離,與上面平面的定義對比可知,v=-\frac{n}{n^TX}.

根據(jù)上面的結(jié)果,可以得到P_0P_1之間的單應(yīng)矩陣為
H=R_1R_0^{-1}-R_1(C_0-C_1)\cdot \frac{n^T}{-n^TX} =R_1R_0^{-1}+ \frac{R_1(C_0-C_1)\cdot n^T}{n^TX}

再引入內(nèi)參矩陣變可得到最終的單應(yīng)矩陣
H = K_1\left(R_1R_0^{-1}+ \frac{R_1(C_0-C_1)\cdot n^T}{n^TX}\right)K_0^{-1}

這里的H是沒有考慮深度比例s的,因為s的值與具體的點是有關(guān)的。在OpenMVS的實現(xiàn)中,s相關(guān)的操作十分隱蔽,對于給定像素x=(x_0, y_0)^T,其對應(yīng)點應(yīng)該滿足
H\left( \begin{matrix} x_0\\ y_0\\ 1 \end{matrix} \right) = \left( \begin{matrix} x_1\\ y_1\\ z_1 \end{matrix} \right) \Rightarrow \left( \begin{matrix} x_1/z_1\\ y_1/z_1\\ 1 \end{matrix} \right)
上述箭頭對應(yīng)的操作,OpenMVS中是通過Point2f的構(gòu)造函數(shù)實現(xiàn)的

explicit inline TPoint2(const cv::Point3_<TYPE>& pt) : Base(pt.x/pt.z,pt.y/pt.z) {}
匹配代價的計算

這里的匹配代價是通過ZNCC(zero-normalized cross correlation)來計算的。按照ZNCC的定義有
ncc = \frac{\sum\limits_{q\in B} (I_q-\overline{I_q}) (I_{H(q)} - \overline{I_{H(q)}})}{\sqrt{\sum\limits_{q\in B} (I_q-\overline{I_q})^2 * \sum\limits_{q\in B} (I_{H(q)}-\overline{I_{H(q)}})^2 }}
這里的B代表在reference圖像空間的鄰域,I代表該像素的灰度值,\bar{I}代表鄰域范圍內(nèi)的平均值。在具體實現(xiàn)時,這里的平均值其實是一個加權(quán)平均,權(quán)重為一個以中心像素的灰度及位置為中心的一個高斯分布
w_q= \exp(w_c + w_s) = \exp\left(-\frac{(I_{ij}-I_c)^2}{2*\sigma_c^2} - \frac{i^2 +j^2}{2*\sigma_s^2}\right)

\overline{I_q} = \frac{\sum\limits_{q\in B} I_q * w_q}{\sum\limits_{q\in B} w_q}

需要注意的是,計算\overline{I_{H(q)}}時使用的權(quán)重仍然是w_q。但從代碼的實現(xiàn)上,匹配代價中ZNCC部分的計算并不完全遵循上述公式,具體可寫成
ncc=\frac{\sum\limits_{q\in B} (I_q-\overline{I_q})*I_{H(q)}*w_q}{\sqrt{\sum\limits_{q\in B}w_q * (I_q - \overline{I_q})^2}\sqrt{\sum\limits_{q \in B} w_q*(I_{H(q)}^2-\overline{I_{H(q)}}^2)}}
ZNCC的意義是說兩個patch越相近,值越大,而我們定義的匹配代價希望是越小,代表匹配效果越好,因此從ZNCC轉(zhuǎn)換成匹配代價的過程中我們先定義score = 1-ncc。同時,這個score值還可以進行多個維度的加權(quán)。第一個是光滑度的考量,主要是看當(dāng)前像素與其四鄰域的像素深度值及法向值是否差異不大,具體的公式如下
w_d = \exp\left(-\frac{(d_p/d)^2}{2\sigma_d^2}\right),~~w_n=\exp\left(-\frac{\delta\theta^2}{2\sigma_n^2}\right),~~w_{smooth}=\prod_{i=1}^4(1-c_d*w_d)(1-c_n*w_n)
其中,c_d,c_n,\sigma_d,\sigma_n都為設(shè)定好的常數(shù)。另一個維度便是一致性的考量,即reference圖像與neighbor圖像對應(yīng)點的深度一致性,這個一致性是通過將neighbor圖像對應(yīng)點的深度還原成世界坐標(biāo)系的三維點,再投影回reference圖像,計算投影值與原像素值的差異來描述的。具體公式為
dist = \sqrt{\delta x^2 + \delta y^2}\\ w_{con} = c_{con}\min(\sqrt{dist*(dist+2.0)}, 4.0)
綜合起來,最終的匹配代價表達式為
score=(1-ncc)*w_{smooth} + w_{con}
ncc的取值范圍是[-1,1],因此理論上,score的值最小為0,最大為2+\max(w_{con}),而實際上我們會給score設(shè)一個閾值,默認(rèn)設(shè)置是0.55,高于這個閾值的都會被拋棄,所以最后得到的score將在區(qū)間[0, 0.55]。

聚合匹配代價的計算

該像素的聚合匹配代價,可以由每個neighbor的匹配代價平均而來,也可以直接使用最小的匹配代價。在具體實現(xiàn)中,當(dāng)neighbor數(shù)小于2時,選取的是最小的匹配代價,而大于2時,在去掉一些過大的匹配代價值后再平均。

傳播與隨機優(yōu)化:ProcessPixel

在傳播優(yōu)化時,像素的處理順序一種是按照前節(jié)描述的那樣從左上到右下,另一種是反過來從右下到左上。上述操作我們迭代運行,一次左上到右下,一次右下到左上,總共3次。對于每個待考察的像素,我們查看其四鄰域的深度和法向值,以鄰域像素的值來重新估計待考察像素的匹配代價,如果匹配代價變小,則用鄰域像素的值來取代。實際操作中,并不是直接使用了鄰域的深度,而是使用了鄰域像素的patch平面,取當(dāng)前像素的三維點與相機原點的連線與該patch平面的交點作為當(dāng)前像素新的三維點位置。

interpolation.png

如上圖,假設(shè)當(dāng)前像素為P',傳播之前的相機坐標(biāo)系位置為X',對應(yīng)法向n'和深度d',傳播的像素為P,相機坐標(biāo)系位置為X,對應(yīng)法向n和深度d,則傳播后P'對應(yīng)的位置為CX'與patch平面的交點X'',法向為n,深度為d''。新的深度的計算公式可推導(dǎo)如下:
\begin{eqnarray*} n^T(X''-X) &=& 0\\ n^T(d''K^{-1}P'-dK^{-1}P) &=& 0\\ n^TK^{-1}(d''P'-dP)&=&0 \\ (n_x, n_y, n_z)* \left( \begin{matrix} \frac{1}{f} & & -\frac{c_x}{f}\\ & \frac{1}{f} & -\frac{c_y}{f}\\ & & 1 \end{matrix} \right) * \left( \begin{matrix} d''x' - dx \\ d''y' - dy \\ d'' - d \end{matrix} \right) &=& 0 \end{eqnarray*}
求解這個線性方程組可以得到
d'' = d * \frac{\frac{n_x}{f}(x-c_x) + \frac{n_y}{f}(y-c_y) + n_z}{\frac{n_x}{f}(x'-c_x) + \frac{n_y}{f}(y'-c_y) + n_z}
在進行完鄰域傳播以后,還有一步是隨機優(yōu)化操作?;旧习凑誷core的值按大小分成三擋,score越大的隨機范圍越大,在最大的那一檔中,基本上就是完全隨機找一個深度和法向與當(dāng)前去比,而在前兩檔中,則是給定不同的隨機范圍,并隨著迭代次數(shù)增加而收緊這個范圍。

深度估計CUDA版本

OpenMVS里CUDA版本的深度估計算法主要是基于如下參考文獻

Xu, Qingshan, and Wenbing Tao. "Multi-view stereo with asymmetric checkerboard propagation and multi-hypothesis joint view selection." arXiv preprint arXiv:1805.07920 (2018).

算法的基本流程與CPU版本類似,都是先計算匹配代價,然后再傳播優(yōu)化,隨機調(diào)整,但是具體步驟和公式上有很多不同之處。

匹配代價的計算

對于給定的reference像素,給定neighbor圖像,給定深度和法向,匹配代價可以表示成
score = 1-\frac{\sum\limits_{q\in B}w_qI_qI_{H(q)}*\sum\limits_{q\in B}w_q - \left(\sum\limits_{q\in B}w_qI_q\right)\left(\sum\limits_{q\in B}w_qI_{H(q)}\right)} {\sqrt{\left(\sum\limits_{q\in B}w_qI_q^2\right)*\left(\sum\limits_{q\in B}w_q\right)-\left(\sum\limits_{q\in B}w_qI_q\right)^2}*\sqrt{\left(\sum\limits_{q\in B}w_qI_{H(q)}^2\right)*\left(\sum\limits_{q\in B}w_q\right)-\left(\sum\limits_{q\in B}w_qI_{H(q)}\right)^2}} +w_{con}
其中所有的記號都與CPU版本中的公式一樣。每個像素匹配代價的計算都可以并行完成。而在計算聚合匹配代價時,與CPU版本的簡單平均或是取最小值不同,CUDA版本有一套很復(fù)雜的加權(quán)方式,并且這個加權(quán)方式與傳播融合在一起,將在下節(jié)介紹。

傳播優(yōu)化

在CPU版本中,傳播優(yōu)化時像素是順序進行的,即后一個像素的處理是依賴于上一個像素的結(jié)果。為了能夠并行地進行傳播,這里采用了棋盤格紅黑像素分隔的方法,具體的分法可以查看下圖,黑色像素的深度法向更新只依賴于鄰域內(nèi)的紅色像素,而紅色像素的深度法向更新只依賴于鄰域內(nèi)的黑色像素。在每一輪的傳播中,先是固定紅色像素的取值,并行更新所有的黑色像素,然后再固定黑色像素的取值,并行更新所有的紅色像素。

checkboard.png

對于順序傳播而言,每個像素的更新有可能從較遠的地方傳播而來,而對于并行傳播而言,每個像素只能接受鄰域像素的傳播,因此為了提高傳播的效率,并行傳播時的鄰域會選取得更大,而不僅限于上下左右的四鄰域。具體的實現(xiàn)中,鄰域的范圍如下圖所示


cuda_neighbor.png

傳播過程中,鄰域像素被分成了8條路徑,每條路徑對應(yīng)上圖中的一種顏色,需要注意的是,在實現(xiàn)中,淡色的直線路徑不只4個像素,而是11個像素。對于每條路徑,我們會挑選出confidence值最大的那個像素當(dāng)做這條路徑的候選者(論文中稱為hypothesis),我們的目標(biāo)就是確定這8個候選像素的深度法向值能否傳播給當(dāng)前像素。對于每個hypothesis而言,我們可以通過插值得到當(dāng)前像素的新的深度和法向,新的值對應(yīng)每個neighbor圖像都會有一個匹配代價,我們需要將其加權(quán)平均得到最終這個hypothesis的聚合匹配代價,傳播是否成功就取決于聚合匹配代價與當(dāng)前像素的取值計算得到的聚合匹配代價相比是否變小。

下面我們來介紹權(quán)重的計算。如果一個neighbor圖像對應(yīng)的權(quán)重大,我們認(rèn)為它起決定性作用的概率更大。如果我們能得到這樣一種概率分布,也就大概能得到neighbor圖像的權(quán)重了。假設(shè)有N個neighbor圖像,它們被選中的概率為P_0, P_1, ..., P_{N-1},滿足\sum\limits_{i=0}^{N-1}P_i=1,實現(xiàn)中并不是直接以這個概率來作為權(quán)重的,而是通過均勻分布采樣的方式來確定。如下圖,不同的概率布滿了區(qū)間[0,1],線段的長度代表著概率的大小,我們通過[0,1]區(qū)間的均勻分布產(chǎn)生了32個點,然后看這32個點落在哪個概率區(qū)間,權(quán)重即是落在該區(qū)間點的個數(shù)除以32。從大數(shù)定理的角度來看,只要采樣點的數(shù)目足夠多,得到的權(quán)重其實將趨于上述概率值,但通過采樣的手段,可以增加一點隨機性,比如,沒有被sample到的圖像在下一輪傳播中會被剔除neighbor集合。

prob.png

問題現(xiàn)在轉(zhuǎn)化成如何確定每個neighbor圖像選中的概率。這個概率與兩個因素有關(guān),第一個是一致性,即該neighbor圖像是否也是當(dāng)前像素的四鄰域像素的neighbor圖像,第二個是與8個hypothesis在該neighbor圖像下的匹配代價有關(guān)。這兩個因素分別會產(chǎn)生兩個系數(shù)w_1,w_2,而每個neighbor圖像對應(yīng)的概率為p_j = w_{1j}*w_{2j}歸一化后的值。

因素1:w_{1j}=0.9n+0.1(4-n),這里的n代表四鄰域像素中共享當(dāng)前neighbor圖像的個數(shù),最大為4。

因素2:w_{2j} = \sum\limits_{i=0}^K \exp\left(-\frac{c_{ij}^2}{2\sigma^2}\right)/K,其中c_{ij}代表第i個hypothesis在第j個neighbor圖像上的匹配代價。需要注意的是并不是8個hypothesis都要參與上述平均,即K不一定為8。實現(xiàn)中,對c_{ij}設(shè)置了閾值,并且這個閾值是與迭代次數(shù)相關(guān)的,具體來說,只有c_{ij} < 0.8*\exp(-\frac{iter^2}{2*4^2}),這個hypothesis才會參與平均,總體原則是說隨著迭代次數(shù)增多,閾值收緊,更傾向于選擇score較小的幾個去確定概率。

在每一輪黑色或者紅色像素做完空間傳播以后,還是需要做幾次隨機的調(diào)整,以期獲得更好的深度和法向信息。

深度優(yōu)化

這一步主要是兩個操作,一個去除孤立的小團體(RemoveSmallSegments),一個是填補小洞(GapInterpolation)。

RemoveSmallSegments:從當(dāng)前像素出發(fā),從四鄰域生長,只要深度差異在一定范圍內(nèi),即合并入小團體,直至無法生長。檢測小團體的點數(shù),當(dāng)點數(shù)小于閾值(預(yù)設(shè)100)時,則該小團體中的所有點將被刪除。

GapInterpolation:逐行掃描,如果有相隔小于(默認(rèn)7)個像素沒有深度值,則啟動填補小洞操作,深度上取小洞邊界兩個像素的深度值線性插值,法向按角度線性插值,信任值則去兩個端點最小的。逐列掃描,進行同樣的操作。

深度濾波

這里的深度濾波近似于在多個視角上去做平滑,對于reference圖像上每一個二維像素點,自身有一個重建的深度,而其在neighbor圖像上的對應(yīng)點,也有一個對應(yīng)的深度,這個深度是針對neighbor圖像相機坐標(biāo)系的,通過變換,我們可以得到它相當(dāng)于reference圖像相機坐標(biāo)系的深度,我們可以將reference圖像的深度與neighbor圖像變換得來的深度進行加權(quán)平均,作為濾波后的深度。實現(xiàn)時,先將neighbor圖像的深度圖轉(zhuǎn)換到reference圖像相機坐標(biāo)系的深度圖,對于每一個像素,查看深度深度差異,只有大多數(shù)neighbor的深度差異在一定合理范圍內(nèi)時,才會利用這些深度參與加權(quán)平均,而權(quán)重即是深度對應(yīng)的confidence值。此時,新的confidence值則等于參與平均的那些深度對應(yīng)的confidence值的和減去沒參與平均的那些深度對應(yīng)的confidence值的和。當(dāng)大多數(shù)neighbor的深度與當(dāng)前深度不一致的時候,則會將該點刪除,將深度置0。

深度融合

fuse.png

整個融合的過程大體可以由上圖來解釋,首先每個視角對應(yīng)的深度圖經(jīng)由該視角的相機內(nèi)參及位姿,可以得到世界坐標(biāo)系的三維坐標(biāo)。然后對于neighbor之間的對應(yīng)點,我們考察他們在reference相機坐標(biāo)系下的深度,如圖所示,N_1, N_2的深度比reference像素的深度要大,被認(rèn)為是處于遮擋狀態(tài),會被刪除掉,做法就是將對應(yīng)像素在其相機坐標(biāo)系的深度圖中置0;N_4的深度與reference深度相差不大,最終它會被用來平均reference的深度;N_3上述兩個條件都不滿足,會被暫時保留。而對于reference像素本身,如果和他一致的neighbor數(shù)(像N_4這樣的點)很少,那么它也將被刪除掉,深度置0。


  1. Multiple View Geometry in Computer Vision, 2nd ed, p326, Result 13.1 ?

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容