ORB-SLAM2的特征提取算法


ORB-SLAM2跟蹤線程對相機輸入的每一幀圖像進行跟蹤處理,如下圖所示,主要包括4步,提取ORB特征、從上一幀或者重定位來估計初始位姿、局部地圖跟蹤和關鍵幀處理。

以下結合相關理論知識,閱讀ORB-SLAM2源代碼,從而理解ORB-SLAM2算法中ORB特征提取過程。

ORB(Oriented FAST and Rotated BRIEF)

基於特征點的方法是SLAM的前端VO的主流方法,因為其運行穩定,對光照、運動物體不敏感。特征點由關鍵點(Key-point)和描述子(Descriptor)兩部分組成。比如,當說到SIFT特征時,是指“提取SIFT關鍵點,並計算SIFT描述子”。關鍵點是指該特征點在圖像里的位置,有些特征點還具有朝向、大小等信息。描述子通常是一個向量,按照某種人為設計的方式,描述了該關鍵點周圍像素的信息。描述子是按照“外觀相似的特征應該有相似的描述子”的原則設計的。因此,只要兩個特征點的描述子在向量空間上的距離相近,就可以人為它們是同樣的特征點。

常見的特征有SIFT特征,SURF特征等。那么為什么ORB-SLAM2選擇ORB特征呢?

這是因為雖然SIFT考慮了圖像變換過程中出現的光照、尺寸、旋轉等變化,但需要較大計算量,在沒有GPU加速的情況下,很難在SLAM這種系統中進行實時計算,另一方面,SIFT特征和SURF特征是受到專利保護的,需要付費使用。

ORB特征由Ethan Rublee, Vincent Rabaud, Kurt Konolige和Gary R. Bradski在他們2011年的論文《ORB: An efficient alternative to SIFT or SURF》提出,如論文題目所述,ORB特征在計算速度、匹配性能,以及在專利要求上都可以替代SIFT和SURF。

ORB取名已經反映出其是一個結合了改良后的FAST角點提取和BRIEF描述子的算法,提取ORB特征分為兩步:

  1. FAST關鍵點提取:找出圖像中的FAST角點,相較於原版的FAST,ORB中計算了特征點的主方向,為后續的BRIEF描述子增加了旋轉不變性;

  2. BRIEF描述子:對上一步提取出關鍵點的周圍圖像區域進行描述。

FAST關鍵點

FAST是一種角點,主要檢測局部像素灰度變化明顯的地方,以速度快著稱。FAST只需要比較像素亮度大小,速度很快,它的檢測過程如下:

  1. 在圖像中選取像素p,假設它的亮度為Ip

  2. 設置一個閾值T(比如Ip的20%);

  3. 以像素p為中心,選取半徑為3的圓上的16個像素點;

  4. 假如選取的圓上有連續的N個點的亮度大於Ip+T或者小於IpT,那么像素p可以被認為是特征點(N通常取12,即FAST-12)。

  5. 循環以上四步,對每一個像素執行相同的操作。

FAST角點檢測雖然速度很快,但是它存在一些問題。首先是FAST角點數量很大且不確定,因此ORB對其進行改進。ORB指定最終要提取的角點數量N,對原始FAST角點分別計算Harris響應值,然后選取前N個具有最大值的角點作為最終的角點集合。

其次,FAST不具有尺寸,因此ORB構建圖像金字塔,對圖像進行不同層次的降采樣,獲得不同分辨率的圖像,並在金字塔的每一層上檢測角點,從而獲得多尺寸特征。

FAST沒有計算旋轉,因此ORB通過計算以FAST角點O為中心的圖像塊的質心C,那么向量OC的方向就是特征點的方向,具體值通過圖像塊的矩得到。

通過各種改進,FAST特征具有了尺寸和旋轉的描述,在ORB中,把這種改進后的FAST稱為oFAST。

BRIEF描述子

BRIEF描述子是一種二進制字符描述子,其描述向量定義如下:

  

p(x) 是圖像塊p中點x的強度。τ的選擇有很多種,常見的選擇方式是圍繞圖像塊中心的高斯分布。n選為256的話,fn(p)就是256維的向量。BRIEF由於使用了二進制表達,存儲起來十分方便,適用於實時的圖像匹配。原始的BRIEF描述子不具有旋轉不變性,因此在圖片發生旋轉時,匹配性能會急速下降。ORB根據之前關鍵點的方向來旋轉圖像塊,得到“steer BRIEF”。

BRIEF具有每個bit的方差很大,均值約為0.5的特性,但是“steer BRIEF”喪失了這種特性,其均值不再集中在0.5左右。可以理解為特定方向的角點關鍵點使得其產生發散。這樣會導致使用“steer BRIEF”進行匹配時的錯誤率變高,因為“steer BRIEF”的方差發生了虧損,彼此之間區分度降低。同時我們希望每個τ彼此不相干,這樣得到的BRIEF更加有區分度。

為了解決上述問題,BRIEF采用了貪婪搜索,對所有可能的τ進行搜索,找出既具有高方差,均值約為0.5,同時又不相干的τ,最終結果稱為rBRIEF。

由於考慮了旋轉和縮放,使得ORB在平移、旋轉和縮放的變換下仍具有良好的表現。同時,FAST和BRIEF的計算非常高效,使得ORB特征在實時SLAM系統中得以應用。

以下閱讀ORB-SLAM2的源代碼,理清其跟蹤線程中對ORB特征的提取過程。

函數入口

ORB-SLAM2跟蹤運行在主線程,是整個SLAM系統的基礎。主程序在初始化SLAM系統后,

// Examples/Monocular/mono_kitti.cc  line:53
// Create SLAM system. It initializes all system threads and gets ready to process frames.
ORB_SLAM2::System SLAM(argv[1],argv[2],ORB_SLAM2::System::MONOCULAR,true);

就可以將每一幀圖像送往跟蹤函數,如下是單目SLAM主函數調用跟蹤函數的代碼:

// Examples/Monocular/mono_kitti.cc  line:84
// Pass the image to the SLAM system
SLAM.TrackMonocular(im,tframe);

TrackMonocular()函數調用GrabImageMonocular()函數實現跟蹤功能:

// System.cc  line:260
cv::Mat Tcw = mpTracker->GrabImageMonocular(im,timestamp);

 

雙目和RGB-D調用方式類似,分別是SLAM.TrackStereo(imLeftRect,imRightRect,tframe);SLAM.TrackRGBD(imRGB,imD,tframe);

mpTrackerSystem類中的成員,是Tracking類的指針。mpTracker對輸入的每一幀圖像計算出對應的相機位姿,同時決定何時插入新的關鍵幀,創建新的地圖點,並且在跟蹤失效時進行重定位。mpTracker的初始化在System 類的對象SLAM初始化的構造函數中進行:

//System.cc  line:86~87
//Initialize the Tracking thread
//(it will live in the main thread of execution, the one that called this constructor)
mpTracker = new Tracking(this, mpVocabulary, mpFrameDrawer, mpMapDrawer, mpMap, mpKeyFrameDatabase, strSettingsFile, mSensor);

 

那么mpTracker是如何實現上述功能的呢?我們來看Tracking類,其頭文件為Tracking.h,其定義了接口如下:

// Tracking.h  line:61
// Preprocess the input and call Track(). Extract features and performs stereo matching.
cv::Mat GrabImageMonocular(const cv::Mat &im, const double &timestamp);

 

ORB特征提取

ORB-SLAM2是一個基於特征的方法,它對輸入的圖像提取出角點的特征,如下圖所示: 

在提取出特征后,所有輸入的圖片都會刪除,系統剩下的處理流程都是基於這些特征進行的,和相機類型無關。

單目的預處理流程實現過程在cv::Mat GrabImageMonocular(const cv::Mat &im, const double &timestamp)函數中體現為:首先將im轉換為灰度圖mImGray,然后預處理提取ORB特征:

// Tracking.cc  line:257~260
if(mState==NOT_INITIALIZED || mState==NO_IMAGES_YET)
  mCurrentFrame = Frame(mImGray,timestamp,mpIniORBextractor,mpORBVocabulary,mK,mDistCoef,mbf,mThDepth);
else
  mCurrentFrame = Frame(mImGray,timestamp,mpORBextractorLeft,mpORBVocabulary,mK,mDistCoef,mbf,mThDepth);

 

得到預處理的結果mCurrentFrame,從而系統剩余部分的處理流程都是基於mCurrentFrame,和單目相機無關。mCurrentFrameFrame類的對象,這里的預處理在Frame類的構造函數中進行。Frame類對單目相機輸入的構造函數重載形式為:

// Frame.h
// Constructor for Monocular cameras.
Frame(const cv::Mat &imGray, const double &timeStamp, ORBextractor* extractor,ORBVocabulary* voc, cv::Mat &K, cv::Mat &distCoef, const float &bf, const float &thDepth);

 

Frame.cc文件中查看其該重載函數定義,

// Frame.cc line:181~191
// Scale Level Info
mnScaleLevels = mpORBextractorLeft->GetLevels();
mfScaleFactor = mpORBextractorLeft->GetScaleFactor();
mfLogScaleFactor = log(mfScaleFactor);
mvScaleFactors = mpORBextractorLeft->GetScaleFactors();
mvInvScaleFactors = mpORBextractorLeft->GetInverseScaleFactors();
mvLevelSigma2 = mpORBextractorLeft->GetScaleSigmaSquares();
mvInvLevelSigma2 = mpORBextractorLeft->GetInverseScaleSigmaSquares();

// ORB extraction
ExtractORB(0,imGray);

 

其先提取ORB特征參數,然后調用Frame類成員函數ExtractORB()來提取ORB特征,ORB特征參數存儲在配置文件中,在mpTracker的初始化中加載讀入,並傳入Frame的構造函數中。

ExtractORB()函數定義為:

// Frame.cc  line:247~253
// Extract ORB on the image. 0 for left image and 1 for right image.
void Frame::ExtractORB(int flag, const cv::Mat &im)
{
    if(flag==0)
        (*mpORBextractorLeft)(im,cv::Mat(),mvKeys,mDescriptors);
    else
        (*mpORBextractorRight)(im,cv::Mat(),mvKeysRight,mDescriptorsRight);
}

 

其調用了ORBextractor類的重載運算符來提取ORB特征:

// ORBextractor.h  line:56~61
// Compute the ORB features and descriptors on an image.
// ORB are dispersed on the image using an octree.
// Mask is ignored in the current implementation.
void operator()( cv::InputArray image, cv::InputArray mask,
                std::vector<cv::KeyPoint>& keypoints,
                cv::OutputArray descriptors);

 

ORB-SLAM提取ORB特征時采用了8層金字塔,尺寸因子為1.2。對於像素為512*384到752*480的圖片,提取1000個FAST角點,對於更高的分辨率,提取2000個FAST角點就可以了。

至此,得到當前幀ORB特征點mvKeys和描述子mDescriptors,均是Frame類對象mCurrentFrame的成員變量。提取出特征點后,需要對其去失真UndistortKeyPoints();。同時需要將圖片分割為64*48大小的柵格,並將關鍵點按照位置分配到相應柵格中,從而降低匹配時的復雜度,實現函數為AssignFeaturesToGrid(); 。

參考資料

[1] 高翔,張濤.“視覺SLAM十四講”

[2] OBR-SLAM2 github 主頁

 


免責聲明!

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



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