1. 程式人生 > >SLAM學習筆記4: ORB-SLAM中BOW特徵匹配

SLAM學習筆記4: ORB-SLAM中BOW特徵匹配

通常估計兩幀之間的運動, 我們需要分別計算兩幀中的所有特徵點, 然後計算特徵點之間的匹配關係. 再通過對應特徵點的移動情況來估計兩幀之間的攝像機運動.

這中間會涉及好很多問題, 至今未能得到有效解決:

  1. 提取特徵點的型別: 眾所周知, 對於自然場景影象, SIFT和SURF特徵點具有非常好的特性, 充分考慮了尺度, 光照, 旋轉等因素的影響. 然而SIFT, SURF特徵的計算非常耗時, 很難滿足實時應用的需要. 於是我們只能轉而使用質量較差但計算較為簡單的影象特徵點, 如FAST, ORB等.
  2. 特徵點匹配的問題: 在確定特徵點位置後, 我們可以計算這個特徵點的descriptor. 然後在兩幀之間兩兩對比descriptor, 當descriptor之間的distance低於某個閾值時, 便認為這兩個特徵是同一個點. 然而這裡存在兩個問題:
    (1) 到底distance閾值應該設為多少, 大多憑實驗經驗獲得, 並沒有什麼理論依據.
    (2) 特徵點之間兩兩比對, 計算量非常大. 而且其實有很多比對是不需要的. 目前的解決方案主要是假設兩幀之間的相對運動不大, 於是可以在第一幀的特徵點位置附近來搜尋對應特徵即可. 但是即使如此, 計算量還是難以滿足實時需要. 所以在ORB-SLAM中, 還有很多其它的工程上的優化被考慮進去.

剛開始接觸ORB的時候, 誤解了作者對bow模組的使用, 還以為bow只是簡單地用於loop closure detection, 後面仔細檢視程式碼後發現並沒有那麼簡單.

在作者使用的Bag of Word詞典中, 詞典是一個事先訓練好的分類樹, 而BOW特徵有兩種:
1. BowVector: 即是分類樹中leaf的數值與權重
2. FeatureVector: 是分類樹中leaf的id值與對應輸入ORB特徵列表的特徵序號.

ORB SLAM中, 在利用幀間所有特徵點比對初始化地圖點以後, 後面的幀間比對都採用Feature vector.進行, 而不再利用所有特徵點的descriptor兩兩比對. 這樣做的好處當然是加快了處理速度, 但是資訊再次被壓縮抽象化, 不可避免會造成效能降低. 然而根據作者在之前的文章[1]及github上的描述, 對一幅圖片的BOW特徵抽取可以在5ms以內完成, 而在19000張圖片構成的database中, 圖片搜尋可以在10ms內完成, 且保證False Positive為0. 具體的實驗我沒有進行驗證, Whatever, ORB-SLAM證明了這樣處理是有效的, 至少在資料集上, 及速度較慢的應用上, 可以實現令人滿意的精度.

其實處理非常簡單, 在已經獲得影象特徵點集合的基礎上, 再根據詞典, 對每個特徵做一次分類. 再對第二幅影象提取特徵, 然後也根據詞典, 也對這幅影象的所有特徵進行分類. 用分類後的特徵類別代替原本的特徵descriptor, 即用一個數字代替一個向量進行比對, 顯然速度可以大大提升.

這一方案在ORB SLAM整個project中被大量應用, 除了初始化時, 因為需要較準確的地圖點及初始位姿估計, 而採用descriptor進行暴力比對. 後面的在SearchForTriangulation, SearchByBoW的過程中, 都是直接使用Feature vector作為特徵的值的. 在實際應用中發現效果十分不錯.

然而這一種方法有一個最惱人的問題就是, 每次在初始化系統的時候必須載入一個100多m的詞典庫, 在我的android orb下測試, 這個載入的過程長達2分鐘以上.
當前使用的詞典是使用K-Nearest-Neighbor演算法生成的分類樹, 學過機器學習的童鞋都知道, 這是一種instance based的聚類演算法, 分類速度快, 但是所需儲存空間大. 所以如果使用其它的聚類演算法生成分類器, 不知是否還能達到real time的需求.
另外, 是否可以通過一些online learning的方法進行詞典學習, 或者把特徵descriptor轉為二進位制表達, 加速運算. 這些都是待考究的問題.

[1]Gálvez-López, Dorian, and Juan D. Tardos. “Bags of binary words for fast place recognition in image sequences.” Robotics, IEEE Transactions on 28.5 (2012): 1188-1197.