1. 程式人生 > >ORB-SLAM2 論文&程式碼學習 —— 單目初始化

ORB-SLAM2 論文&程式碼學習 —— 單目初始化

轉載請註明出處,謝謝
原創作者:Mingrui
原創連結:https://www.cnblogs.com/MingruiYu/p/12358458.html


本文要點:

  • ORB-SLAM2 單目初始化部分 論文內容介紹
  • ORB-SLAM2 單目初始化部分 程式碼結構介紹

寫在前面

之前的 ORB-SLAM2 系列文章中,我們已經對 Tracking 執行緒做了介紹,但是當時我們跳過了 Tracking 執行緒中一個很重要的部分 —— 單目初始化。我們將在本文中,對 ORB-SLAM2 系統的單目初始化部分進行介紹。

依舊祭出該圖,方便檢視:

也再次獻上我繪製的程式導圖全圖:ORB-SLAM2 程式導圖

老規矩,還是分兩部分:以 ORB-SLAM 論文為參考 和 以 ORB-SLAM2 程式碼(程式導圖)為參考。

以 ORB-SLAM 論文為參考

對於任何一個單目 SLAM 系統來說,在系統執行之初都要進行初始化,其目的在於,要計算出某兩幀的相對位姿,以此來通過三角化得到一些初始 MapPoints,從而得到一個初始的 Map,這樣之後的跟蹤也好優化也好都在這個基礎上進行。在 ORB-SLAM 之前的單目 SLAM 系統的初始化,往往需要依賴真實場景中某樣確定的物體(eg. MonoSLAM)或者需要人工介入(eg. PTAM),而 ORB-SLAM 的單目初始化是完全自動的。

對 SLAM 基礎知識有過了解的同學會知道,恢復兩幀之間的相對運動,有兩種模型:基礎矩陣(Fundamental)(等同於本質矩陣)模型和單應矩陣(Homography)模型。正常情況下基礎矩陣模型應該可以應付,但如果特徵點共面(初始化場景中主要是一個平面),或者兩幀之間的相對位姿未純旋轉時,基礎矩陣的自由度會下降,也就是所謂的退化,類似於方程數少於變數數。此時為了保證運動恢復的精度,就不能再用基礎矩陣模型。由此提出了單應矩陣,其假設特徵點落在同一平面上,從而適用於這種場景下的運動恢復。

ORB-SLAM 在初始化時,它也不知道場景中的特徵點在不在同一平面,所以它選擇兩種模型各自算一遍(開兩個執行緒同時算),之後計算兩種模型各自進行運動恢復的得分,取得分高的模型,再根據該模型,計算兩幀之間的相對位姿並進行初始化。

單目初始化具體步驟

1. 提取 ORB 特徵點

在當前幀和參考幀中提取 FeaturePoints(只在最優的尺度),同時將當前幀和參考幀的 FeaturePoints 做匹配。如果匹配點不夠多,重新初始化。

2. 同時計算兩種模型

  • 單應矩陣 \(H_{cr}\):DLT 演算法 + RANSAC 迭代
  • 基礎矩陣 \(F_{cr}\):8點法 + RANSAC 迭代

同時計算兩種模型各自的得分,計算公式如下(其中 M 可以表示 H (Homography),也可以表示 F (Fundamental)):

\(S_{M}=\sum_{i}\left(\rho_{M}\left(d_{c r}^{2}\left(\mathbf{x}_{c}^{i}, \mathbf{x}_{r}^{i}, M\right)\right)+\rho_{M}\left(d_{r c}^{2}\left(\mathbf{x}_{c}^{i}, \mathbf{x}_{r}^{i}, M\right)\right)\right)\)

\(\rho_{M}\left(d^{2}\right)=\left\{\begin{array}{ll} {\Gamma-d^{2}} & {\text { if } \quad d^{2}<T_{M}} \\ {0} & {\text { if } \quad d^{2} \geq T_{M}} \end{array}\right.\)

其中 \(d_{c r}^{2}\) \(d_{r c}^{2}\) 是對稱轉換誤差。\(\rho_{M}()\) 的作用是令大的誤差對低的得分,其中 \(T_M\) 閾值是算出來的:假設測量值誤差的標準差為1畫素,通過95%的 \(\chi^{2}\) 檢驗得到的。對於每種模型,在 RANSAC 迭代過程中保留得分最高的模型。如果最終沒能求出解(對於 RANSAC,inliers不夠多),則重新初始化。

3. 選擇合適的模型

根據兩種模型各自的得分:

\(R_{H}=\frac{S_{H}}{S_{H}+S_{F}}\)

如果 \(R_H\) > 0.45(程式碼中是 0.4),則選用單應矩陣;反之則選基礎矩陣模型。大概就是選得分高的,此處的 0.4 應該是經驗值。

4. 進行運動恢復,求解兩幀相對位姿(\(R, t\))並通過三角化得到初始 MapPoints

在求出 \(H_{cr}\) 或 \(F_{cr}\) 後,就要根據該矩陣求出相對位姿(\(R, t\))。但這個過程的求出的解不是唯一的。ORB-SLAM 採取的篩選辦法是:對這些解全部進行三角化恢復 MapPoints,哪個解恢復出來的 MapPoints 大部分都在相機前方且重投影誤差小,就選哪個解。如果不能明確選出一個最合適的,則重新初始化。

5. BA 優化

最後,進行一次全域性 BA,優化以下,得到最終的初始化結果。

從以上步驟可以看出,ORB-SLAM 在單目初始化花了很多心思。有一個很明顯的特點:只要出現一點不妥,ORB-SLAM 就會選擇重新初始化。論文中說,這種高標準嚴要求的初始化準則,是 ORB-SLAM 系統魯棒性非常好的重要原因之一。因為如果初始化就不合適或出錯,後面的跟蹤只會一錯再錯,錯上加錯。

以 ORB-SLAM2 程式碼(程式導圖為參考)

在上圖中 MonocularInitialization() 就是初始化的程式,我們可以看到它在 Tracking 執行緒中的位置。

上圖是 MonocularInitialization() 部分的程式框圖,其大體和論文中介紹的步驟是完全一致的,這樣圖已經很清晰了,這裡就不多描述了。

如果嫌這張圖不夠清晰的話,可以點選 ORB-SLAM2 程式導圖連結(文首)檢視清晰全圖

PS: 從中上圖我們可以看到,在恢復出兩幀之間的相對運動後,程式中還要使用 Tracking::CreateInitialMapMonocular() 來建立初始化的地圖。這部分在論文裡幾乎沒有筆墨提到,但在程式裡需要很大篇幅來實現。這個細節就反映了我在本系列博文開篇就提到過的讀通 ORB-SLAM2 程式碼的困難之處。以我現在小菜雞的水平,我根本想象不出 ORB-SLAM2 這樣複雜而環環相扣的工程是怎麼寫出來的(流淚)。

ORB-SLAM2 系列博文

ORB-SLAM2 初體驗 —— 配置安裝

ORB-SLAM2 論文&程式碼學習 —— 概覽

ORB-SLAM2 論文&程式碼學習 —— Tracking 執行緒

ORB-SLAM2 論文&程式碼學習 —— 單目初始