ORB_SLAM2 源碼閱讀 ORB_SLAM2::Initializer


ORB_SLAM2::Initializer 用於單目情況下的初始化。

Initializer 的構造函數中傳入第一張影像,這張影像被稱作 reference frame(rFrame)。在獲得第二張影像時傳入第二張影像,這張影像被稱作 current frame(cFrame)。這一部分傳入的代碼可以在ORB_SLAM2::Tracking::MonocularInitialization()中查看,要求 rFrame 與 cFrame 都至少具有 101 個特征點,而且 cFrame 與 rFrame 粗匹配結果不少於 100 個點對。這個粗匹配也很有意思,可以查看ORBmatcher::SearchForInitalization()(粗匹配是對每一個 rFrame 的特征點選定一定大小的窗口,以該特征點在 rFrame 上的坐標為中心,在 cFrame 上提取出覆蓋網格內所有的特征點,計算 ORB 描述子的距離,距離夠小就說明是匹配點)。

Initializer::Initialize()

在這個函數中完成初始化。首先生成 RANSAC 需要用的最小子集的集合mvSets。隨后開兩個線程同步進行FindHomographyFindFundamental,這兩個函數分別返回SHSF這兩個數值用於判定是使用 H 作為初始模型更好,還是用 F 作為初始模型更好。

在用SHSF判定是使用 H 還是 F 之后就是用 H (ReconstructH())或 F (ReconstructF())生成 R、t 和對應的可以三角化的點用於初始地圖生成。

ReconstructH() 是使用 Motion and structure from motion in a piecewise planar
environment
生成 8 種可能結果,再使用CheckRT()確定是哪一種最為合適。

Initializer::FindHomography()

每次使用 8 個點通過 SVD 分解計算得到 H21。值得注意的是在進行 Homography 計算之前先進行歸一化過程(在函數Normalize()中進行)。

Initializer::Normalize()

歸一化過程是將所有的 KeyPoints 進行一次 Affine Transformation,使得變換后的 KeyPoints 均值為原點 \(0\),方差為單位陣 \(I\)

變換公式為:

\[x_i^{\prime} = {x_i - \bar{x} \over \sigma} \\ \bar{x} = {\Sigma{x_i} \over N} \\ \sigma = {\Sigma{\left|x_i - \bar{x}\right|} \over N} \]

歸一化的原因是計算出的 H 會依賴於特征點的位置,所以先歸一化再計算。(MVG Page 104

歸一化的過程可以使用一個矩陣 \(T\) 表示:

\[x^{\prime} = Tx = \begin{bmatrix} {1 \over \sigma_x} & 0 & \bar{x}{1 \over \sigma_x} \\ 0 & {1 \over \sigma_y} & \bar{y}{1 \over \sigma_y} \\ 0 & 0 & 1 \end{bmatrix} x \]

后面的計算過程如下:

\[x_2^{\prime} = H_{21}^{\prime}x_1^{\prime} \]

\[Tx_2 = H_{21}^{\prime}Tx_1 \]

\[x_2 = T^{-1}H_{21}^{\prime}Tx_1 \]

\[H_{21} = T^{-1}H_{21}^{\prime}T \]

Initializer::ComputeH21()

在歸一化之后,使用歸一化的坐標計算 Homography。

沒啥好講,就是 Direct Linear Transformation,參考 MVG Page 88

Initializer::CheckHomography()

用 H21 和 H12 分別將 rFrame(1) 中的特征點和 cFrame(2) 轉換到另一張影像中,計算匹配點的距離誤差,距離誤差轉換為卡方距離,卡方距離小於 5.991 說明顯著性為 5%,應該認為它們匹配成功,否則不成功將這一對匹配標記為 false。注意這里有兩個自由度。

https://en.wikipedia.org/wiki/Chi-squared_distribution#Table_of_.CF.872_values_vs_p-values

匹配成功能就能將於顯著性相關的數值加入到評分中,評分越高說明由這八個點計算出的 Homography 越正確。即由CheckHomography()返回的評分currentScore,取 RANSAC 中評分最高的 Homography 作為最終選定的 Homography。

這個 score 會被傳入Initialize()函數中的 SH,用作計算 SH/(SH+SF),判斷是使用 Homography 還是 Fundamental。

Initializer::ReconstructH()

用函數FindHomography()中 RANSAC 計算得到的 Homography 分解,分解能夠得到 8 種可能的 \(R, t\) 結果,用CheckRT()判斷選擇哪一種結果。

好像這有點錯了吧,應該用所有的 inlier 匹配計算 Homography,再用這個更靠譜的 Homography 分解計算 \(R, t\)

函數ReconstructH()最后也輸出三角化成功的三維點。

Initializer::FindFundamental()

FindFundamental()的計算過程與 FindHomography 類似,都是需要進行歸一化操作

函數ComputeF21()用八點法計算 Fundamental,計算得到的實際 Fundamental 通過設置最小特征值為 0 投影到 Fundamental 空間,作為輸出。

函數CheckFundamental()是將點與線的距離作為誤差,計算卡方距離,注意這里有一個自由度,所以顯著性檢驗使用的卡方距離為 3.84。

都差不多,沒啥好說的。

Initializer::CheckRT()

這個函數挺重要的,因為分解 H 和 F 都會有很多可能的結果,使用這個函數能夠分辨出什么結果是靠譜的。

函數CheckRT()接受 \(R, t\) ,一組成功的匹配。最后給出的結果是這組匹配中有多少匹配是能夠在這組 \(R, t\) 下正確三角化的(即 \(Z\) 都大於0),並且輸出這些三角化之后的三維點。

如果三角化生成的三維點 \(Z\) 小於等於0,且三角化的“前方交會角”(余弦是 cosParallax)不會太小,那么這個三維點三角化錯誤,舍棄。

通過了 \(Z\) 的檢驗,之后將這個三維點分別投影到兩張影像上,計算投影的像素誤差,誤差大於2倍中誤差,舍棄。

總結

ORB 里面對通過“最大值”確定的結果都非常小心。一般要求這個“最大值” outstanding,如 ORBmatcher 的構造函數中就有會傳入一個 (0,1) 的數值給成員變量 mfNNratio,只有最小距離小於次小距離的 mfNNratio 倍才能算是匹配成功,不允許出現相似的匹配,而取好那么一點點的匹配作為匹配結果。

Initializer::ReconstructH()中最后 8 個可能結果中,最好模型 inlier 數要大於次好模型 inlier 的 1/0.75 倍。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM