ORB是2011年ICCV上作者Rublee所提出,主要針對目前主流的SIFT或者SURF等算法的實時性進行改進。當然在實時性大為提升的基礎上,匹配性能也在一定程度較SIFT與SURF算法降低。但是,在圖像Two Views匹配對之間變換關系較小時,能夠匹配性能逼近SIFT算法,同時計算耗時極大降低。ORB算法實時性在移動端設備上提供很好的應用,當下比較流行SLAM中采用較多的ORB-SLAM算法主要就是青睞於ORB算法實時性同時匹配精度並不差。
論文對ORB算法主要貢獻如下:
1、 在FAST角點算子快速提取角點基礎上,添加主方向信息。
2 、通過方向BRIEF描述算子高效計算FAST角點提取的特征點描述符。
3 、分析方向BRIEF描述符的方差與相關性。
4 、提出一種在旋轉不變情況下去除相關性的BRIEF描述子的學習方式,在最近鄰應用中獲得更好的效果。
ORB特征通過增加了FAST檢測子所沒有的方向性,利用計算速度特快的描述子BRIEF,這就使得提取圖像特征時速度加快了很多。在以往提取一幀圖像特征點的實驗中,在提取相同數量的特征點情況下,提取SURF點耗時時間大約是提取ORB特征點的14倍,而提取SIFT點耗時更大,大概比提取ORB特征點多三百多倍。由此可知提取ORB特征點比提取SIFT, SURF特征點所需要的計算量小得多。所以對於需要實時運行視覺SLAM算法的系統,其前端提取ORB特征點比較合適,且ORB特征點具有兩個特性:一是尺度不變,二是旋轉不變性。
下面幾種特征點檢測的效果圖:
現在我們來進行原理解讀。
原理
ORB 是 Oriented Fast and Rotated Brief 的簡稱,可以用來對圖像中的關鍵點快速創建特征向量,這些特征向量可以用來識別圖像中的對象。
其中,Fast 和 Brief 分別是特征檢測算法和向量創建算法。ORB 首先會從圖像中查找特殊區域,稱為關鍵點。關鍵點即圖像中突出的小區域,比如角點,比如它們具有像素值急劇的從淺色變為深色的特征。然后 ORB 會為每個關鍵點計算相應的特征向量。ORB 算法創建的特征向量只包含 1 和 0,稱為二元特征向量。1 和 0 的順序會根據特定關鍵點和其周圍的像素區域而變化。該向量表示關鍵點周圍的強度模式,因此多個特征向量可以用來識別更大的區域,甚至圖像中的特定對象。
ORB 的特點是速度超快,而且在一定程度上不受噪點和圖像變換的影響,例如旋轉和縮放變換等。
FAST 算法
ORB 特征檢測的第一步是查找圖像中的關鍵點,而關鍵點檢測算法即使用 FAST 算法。
FAST 是 Features from Accelerated Segments Test 的簡稱,可以快速選擇關鍵點,算法步驟如下:
給與一個像素點 p,FAST 比較目標 p 圓圈范圍中的 16 個像素,每個像素按高於 p,小於 p,或者與 p 相似,分為三類。
注意這里的比較是帶有閾值 h 的。對於給定的閾值 h,更亮的像素將是亮度超過 Ip+h 的像素,更暗的像素將是亮度低於 Ip-h 的像素,相似像素將是亮度在這兩個值之間的像素。在對像素分類后, 如果圈圈上有 8 個以上的相連像素,暗於或亮於 p 則將像素 p 選作關鍵點。
而 FAST 如此高效的原因是,僅將 p 與圓圈中的 4 個等距像素相比。這種方法已經證明和比較 16 個周圍像素的效果相同。如果至少有一對連續像素的亮度高於或低於 p,則將 p 選作關鍵點。這種優化使得在整個圖像中搜索關鍵點的時間縮短了四倍。
但是,這些關鍵點可以像我們提供什么樣的信息?對比鄰近像素的亮度有何意義?首先觀察一下 FAST 算法標記關鍵點的圖像:
可以看出關鍵點位於亮度有變化的區域,此類區域通常確定了某種邊緣,例如貓的爪子。邊緣定義了貓的界限,以及臉部區域的界限,因此這些關鍵點使我們能夠識別這只貓,而不是圖像中的任何其他對象或背景。
第二個則為BRIEF算法,我們在上一節已經講過,這里就不在贅述了。
縮放不變性和旋轉不變性
ORB 使用 FAST 檢測圖像中的關鍵點,並且通過額外的幾個步驟確保無論對象的大小或位置如何都能檢測到圖像中的對象。
給定一個圖像 ORB 算法首先開始構建圖像金字塔。
圖像金字塔是單個圖像的多尺度表示法,由一系列原始圖像的不同分辨率版本組成。金字塔的每個級別都由上個級別的圖像下采樣版本組成。下采樣是指圖像分辨率被降低,比如圖像按照 1/2 比例下采樣。因此一開始的 4x4 正方形區域現在變成 2x2 正方形。圖像的下采樣包含更少的像素,並且以 1/2 的比例降低大小。
這是一個包含 5 個級別的圖形金字塔示例,在每個級別圖像都以 1/2 的比例下采樣。到了第四級別圖像的分辨率是原始圖像的 1/16。ORB 創建好圖像金字塔后,它會使用 FAST 算法從每個級別不同大小的圖像中快速找到關鍵點。因為金字塔的每個級別由原始圖像的更小版本組成,因此原始圖像中的任何對象在金字塔的每個級別也會降低大小。
通過確定每個級別的關鍵點 ORB 能夠有效發現不同尺寸的對象的關鍵點,這樣的話 ORB 實現了部分縮放不變性。這一點很重要,因為對象不太可能在每個圖像中的大小都完全一樣,尤其是像貓這樣的對象某個時刻可能靠近相機,在另一個時刻離相機很遠。
例如朝左或朝右,取決於該關鍵點周圍的強度是如何變化的。
我們詳細了解下背后原理。ORB 首先選擇金字塔Level 0 中的圖像,對於該圖像 ORB 將計算關鍵點的方向。
方法是首先計算以該關鍵點為中心的方框中的強度形心。強度形心可以看做給定 patch 中的平均像素強度的位置。計算強度形心后,通過畫一條從關鍵點到強度形心的向量,獲得該關鍵點的方向,如上圖所示。這個關鍵點的方向是向下並朝左,因為這個區域的亮度朝着這個方向增強。
為金字塔級別 0 的圖像中的每個關鍵點分配方向后,ORB 現在為所有其他金字塔級別的圖像重復相同流程。需要注意的是,在每個圖像金字塔級別,Patch 大小並沒有縮減,因此相同 Patch 在每個金字塔級別覆蓋的圖像區域將更大,導致關鍵點的大小各不相同。
可以從此處看出這一點。在此圖中,圓圈表示每個關鍵點的大小,更高的金字塔級別中的關鍵點大小更大。
找到關鍵點並為其分配方向后,ORB 現在使用修改后的 BRIEF 版本創建特征向量,這個修改后的 BRIEF 版本稱為 rBRIEF,即 Rotation-Aware BRIEF。無論對象的方向如何,它都可以為關鍵點創建相同的向量,使得 ORB 算法具有旋轉不變性,意味着它可以在朝着任何角度旋轉的圖像中檢測到相同的關鍵點。和 BRIEF 一樣 rBRIEF 首先在給定關鍵點周圍的已界定 patch 中隨機選擇 256 個像素對,以構建 256 位向量。然后根據關鍵點的方向角度旋轉這些隨機像素對,使隨機點的方向與關鍵點的一致。最后, rBRIEF 對比隨機像素對的亮度並相應地分配 1 和 0 創建對應的特征向量,為圖像中的所有關鍵點創建的所有特征向量集合稱之為 ORB 描述符。
OpenCV中的ORB算法
ORB算法的第一步是定位訓練圖像中的所有關鍵點。找到關鍵點后,ORB會創建相應的二進制特征向量,並在ORB描述符中將它們組合在一起。
我們將使用OpenCV的ORB類來定位關鍵點並創建它們相應的ORB描述符。使用ORB_create()函數設置ORB算法的參數。 ORB_create()函數的參數及其默認值如下:
cv2.ORB_create(nfeatures = 500,
scaleFactor = 1.2,
nlevels = 8,
edgeThreshold = 31,
firstLevel = 0,
WTA_K = 2,
scoreType = HARRIS_SCORE,
patchSize = 31,
fastThreshold = 20)
參數:
·nfeatures - int
確定要查找的最大要素(關鍵點)數。
·scaleFactor - float
金字塔抽取率,必須大於1。ORB使用圖像金字塔來查找要素,因此必須提供金字塔中每個圖層與金字塔所具有的級別數之間的比例因子。scaleFactor = 2表示經典金字塔,其中每個下一級別的像素比前一級低4倍。大比例因子將減少發現的功能數量。
·nlevels - int
金字塔等級的數量。最小級別的線性大小等於input_image_linear_size / pow(scaleFactor,nlevels)。
·edgeThreshold - - int
未檢測到要素的邊框大小。由於關鍵點具有特定的像素大小,因此必須從搜索中排除圖像的邊緣。 edgeThreshold的大小應該等於或大於patchSize參數。
·firstLevel - int
此參數允許您確定應將哪個級別視為金字塔中的第一級別。它在當前實現中應為0。通常,具有統一標度的金字塔等級被認為是第一級。
·WTA_K - int
用於生成定向的BRIEF描述符的每個元素的隨機像素的數量。可能的值為2,3和4,其中2為默認值。例如,值3意味着一次選擇三個隨機像素來比較它們的亮度。返回最亮像素的索引。由於有3個像素,因此返回的索引將為0,1或2。
·scoreType - int
此參數可以設置為HARRIS_SCORE或FAST_SCORE。默認的HARRIS_SCORE表示Harris角算法用於對要素進行排名。該分數僅用於保留最佳功能。 FAST_SCORE生成的關鍵點稍差,但計算起來要快一些。
·patchSize - int
面向簡要描述符使用的補丁的大小。當然,在較小的金字塔層上,由特征覆蓋的感知圖像區域將更大。
我們可以看到,cv2.ORB_create()函數支持多種參數。前兩個參數(nfeatures和scaleFactor)可能是最有可能改變的參數。其他參數可以安全地保留其默認值,將獲得良好的結果。
我們仍然使用這張圖片:
來看代碼:
def ORB(img): # Initiate ORB detector orb = cv2.ORB_create() # find the keypoints with ORB kp = orb.detect(img, None) # compute the descriptors with ORB kp, des = orb.compute(img, kp) # draw only keypoints location,not size and orientation img2 = cv2.drawKeypoints(img, kp, None, color=(0, 255, 0), flags=0) plt.imshow(img2), plt.show()
結果:
我們會在之后講述使用各大算法如何對兩幅圖像進行特征匹配。