Programming Computer Vision with Python (學習筆記十二)

ORB(Oriented FAST and Rotated BRIEF)可用來替代SIFT(或SURF),它對圖像更具備抗噪特性,是一種特徵檢測高效算法,其速度知足實時要求,可用於加強圖像匹配應用。
ORB的算法基於FAST角檢測(Features from accelerated segment test)BRIEF(Binary Robust Independent Elementary Features)特徵描述符,這也是它名字的由來。python

FAST角檢測

FAST角檢測比以前咱們介紹過的Harris角檢測、SIFT特徵點檢測(使用高斯差)都要快,後二者關注的是高質量(精準、穩定性高)的特徵檢測,但計算複雜,而FAST關注的是實時應用,好比即時檢測定位(檢測視頻中的移動物體),並且要在計算資源有限的智能手機上使用。算法

FAST檢測角點的過程真的很簡單:
圖片描述數組

  1. 以灰度圖像爲例,從原圖像中選一個點(設爲p),如上圖,放大顯示p點周圍的像素服務器

  2. 給定一個閾值,好比設爲p點灰度值的20%數據結構

  3. 以p爲圓心,劃出半徑爲3的圓,考慮落在圓周上的16個像素的值,若這16個像素連續N(N通常爲12)個符合閾值,則認爲p爲興趣點(角點)dom

  4. 爲讓上面的判斷更快,能夠先計算序號爲一、五、九、13的4個像素(如圖),這4個像素至少要有3個符合閾值,纔有可能存在連續12個像素知足閾值,纔有必要檢測其它像素。機器學習

  5. 對原圖像每個像素,重複以上計算過程,最終得出全部興趣點。數據結構和算法

FAST算法存在的問題:ide

  1. N若是小於12,得出來的結果不是很理想,N建議值爲12函數

  2. 只把圓周上的16個像素做爲興趣點的信息貢獻(不必定適合大多數使用場景)

  3. 檢測出的興趣點,存在不少相鄰的興趣點(須要排除,選其一便可)

但如今這些問題能夠經過機器學習的方法來解決。

skimage庫包含了FAST算法實現:

skimage.feature.corner_fast(image, n=12, threshold=0.15)

BRIEF特徵描述

若是用一個二進制串(binary strings)做爲興趣點描述符(interest point descriptor,下很簡稱IPD),不只存儲空間低,並且比較IPD,能夠轉化爲比較漢明距離(hamming distance),漢明距離爲兩個二進制串不一樣位的個數,用異或就能夠簡單高效的完成計算。

BRIEF算法並不包含興趣點檢測(檢測能夠用FAST或Harris等方法),它只是提出了一種二進制串IPD,只須要256bit,甚至128bit就能夠取得較好的匹配效果。在提取BRIEF二進制串以前,須要先對圖像進行高斯濾波(有關高斯濾波,前面筆記已詳細介紹,此再也不述)以去除噪聲,而後使用其它方法檢測出興趣點,以其中一個興趣點爲例:考慮以興趣點爲中心的S×S大小的矩形圖像塊,以兩個像素值(設爲p1和p2)爲1對,隨機選N對(N爲128或256或512),對每對(p1,p2)進行測試,比較p1和p2,若p1<p2,結果爲1,不然爲0,此稱爲二值測試(binary test),將結果做爲1bit存儲,N對的結果連在一塊兒就組成了一個N bit的二進制串。

如何選取N對像素?BRIEF給出了5種方法,並認爲第2種效果最好:
圖片描述

  1. 均勻採樣(uniformly sampled)

  2. 以圖像中心進行高斯分佈採樣,即越接近中心點的像素點將被優先選擇

  3. 使用兩個不一樣sigma的高斯分佈,設爲G1和G2,全部p1用G1採樣,全部p2用G2採樣

  4. 使用粗極座標網格(coarse polar gird)的離散位置隨機採樣(原文:randomly sampled from discrete location of a coarse polar gird)

  5. 全部p1都固定爲圖像塊的中心像素,全部p2用粗極座標網格採樣(每格採一像素)

對後兩種方法提到的粗極座標網格,看一下圖就不難理解了:
圖片描述

須要注意的是,BRIEF描述符沒有考慮多尺度,雖然對亮度、模糊、視角失真有必定的不變性,但它沒有考慮旋轉,容易受旋轉影響。

ORB

ORB其實綜合了FAST、Harris角測量、圖像矩、BRIEF等理論方法,併爲實時計算提供解決方案。

ORB對FAST的補充

  1. 因FAST檢測出的鄰近興趣點一般會有不少,這些鄰近興趣點其實都位於同一個角點處。ORB的解決方法是:使用閾值過濾,並藉助Harris角測量獲得角點。

  2. FAST沒有考慮圖像縮放,ORB構造了不一樣縮放尺寸的圖像金字塔(詳細參考SIFT),對每一層圖像應用上述方法檢測角點。

  3. FAST檢測的角點沒有考慮方向,ORB藉助圖像中心矩 計算方向。

圖像矩(image moment)
*圖像矩(或稱幾何矩)是由Hu(Visual pattern recognition by moment invariants)在1962年提出的。矩給出了對圖像形狀的一種度量。理解矩的概念有點困難,下面只是簡要說明ORB用到的中心矩,有興趣的讀者,可自行深刻了解。

一個圖像塊I的p+q階矩的公式爲:
圖片描述

其中,I(x,y)表示xy座標所在像素的亮度。
0階矩(記m00,用p=0, q=0代入上述公式)其實就是全部I(x,y)的和,即全部像素的亮度之和,也稱爲圖像的總質量(mass)。

用p=1,q=0代入公式,獲得相對x的一階矩,記爲m10,若是用m10除以m00,即可以獲得x的平均值,也稱爲中心值。同理,用p=0,q=1代入公式,獲得相對y的一階矩,記爲m01,用m01除以m00便獲得y的中心值,x的中心值和y的中心值構成了圖像亮度的 中心矩(centroid),記爲C:
圖片描述

中心矩有時也稱爲質心,在二值圖像中,可用來表明形狀的中心。若是咱們構建一個從角點到中心矩的向量,那麼此向量與X軸的角度爲:
圖片描述

θ即爲圖像塊的亮度方向,先旋轉到此方向再計算得出的興趣點描述符,便具備旋轉不變性。
測試代表,在圖像噪聲較大的狀況下,此方法對旋轉相對SIFT更穩定。

steered BRIEF
ORB使用BRIEF建議的第二種採樣方法(即以圖像中心進行高斯分佈採樣,IPD長度使用256bit),而後在BRIEF基礎上增長了旋轉的描述以及快速的計算方法,這種方法被稱爲steered BRIEF

BRIEF在選取點對(採樣)以前,須要對圖像應用高斯濾波,而ORB則不用,取而代之的是使用以選取點爲中心的5×5區域像素平均值,並用積分圖(integral image)來計算。積分圖,又稱總和麪積表(summed area table,簡稱SAT),是一個快速且有效的對一個網格的矩形子區域中計算和的數據結構和算法。

因引入了旋轉,採樣的點對座標也須要旋轉變換。將採樣點對座標組成矩陣S:
圖片描述

旋轉矩陣(Rotation matrix)設爲Rθ:
Rθ = 58ee3d6d55fbb2fb006f83ce4a4a20a44723dca2.jpg

則經過:
Sθ = S*Rθ
將S的每一個列向量(x,y)關於原點逆時針旋轉θ,爲加速計算,將360度以12度爲單位離散爲30份,事先計算好30個Sθ做爲查找表,以後就能夠節省座標變換這一步計算了。

看起來此方法不錯,惋惜的是,它的匹配效果比BRIEF差一截,經過大量樣本分析發現,BRIEF描述符有一個很好的特性,就是每一位bit對應的點對之間表現出方差大、相關性小,並且同一位置bit的平均值接近0.5。可是steered BRIEF因進行了座標旋轉,損失了這個特性,致使不一樣特徵點描述符差異不大,相關性高,不利於匹配。因此ORB開發了另外一種選取點對和計算IPD的方法——rBRIEF,此方法比steered BRIEF優不少。

rBRIEF
這纔是ORB最爲關鍵的部分,一是由於有點難懂(細節之處論文沒有講清楚),二是由於用了這個方法,使得ORB相較BRIEF和SURF表現突出。
rBRIEF是一種須要學習的算法,學習分兩步:

第一步,創建訓練集,提取二值測試

  • 論文例子使用的樣本數爲30萬,即30萬個特徵點及其對應的(31×31)圖像塊,圖像數據來自PASCAL 2006 dataset

  • 對每個特徵點, 其對應的31×31圖像塊中,任選出兩個5×5的小塊組成一個二值測試,這種組合數目達到205590個,至關於窮舉出了全部點對的可能組合

  • 執行全部二值測試,每一個二值測試其實就是比較兩個5×5小塊的像素平均值(前文有述),結果爲1或0,用1bit存儲,因此一個特徵點得出一個向量[b1,b2,...,b205590]

  • 循環上述計算步驟,直至完成30萬個特徵點,將全部向量組成矩陣A,共30萬行:

[b1,b2,...,b205590]
[b1,b2,...,b205590]
...
[b1,b2,...,b205590]
[b1,b2,...,b205590]

第二步,排序,挑選

  • 計算矩陣A的每一列的平均值,設爲avg,那麼該列與0.5的距離爲:d = avg - 0.5

  • 將矩陣A的列按d從小到大順序排列,結果設爲T

  • 將T中第一列放到結果矩陣R中

  • 從T中拿出第一列,與R中全部列進行比較,若它與R中任何一列的絕對相關度(absolute correlation)大於給定閾值,則丟棄,不然將它放入R中,循環執行這一步,直到R中有256列

  • 若是全部T的列都歷遍了,R中的列數還不足256,則增大閾值,重複上述步驟,直至R中有256列

通過第二步的計算,咱們獲得一個列向量之間相關性最小、每一個列向量均值最接近0.5的結果集R(30萬行,256列),每一行便可以作爲對應特徵點的IPD(256bit),此IPD對應的點對組合是最優的。

新的特徵點的計算過程:

  1. 參考上述第一步,窮舉計算特徵點全部可能的二值測試

  2. 將結果做爲一行加入矩陣A中,按照上述第二步進行計算,就能夠獲得此特徵點對應的IPD
    因以前的樣本都計算過,因此對新的特徵點來講,計算消耗就是上述第二步。

最後,還遺留有一個小問題沒有講清楚,就是二進制向量間的絕對相關度(absolute correlation)如何計算?用漢明距離?

示例

skimage庫包含了一個ORB類:

from skimage.feature import ORB

若import出錯,查看scikit-image包版本:

pip show scikit-image
---
Name: scikit-image
Version: 0.11.3

若是低於此版本須要進行升級:

sudo pip install -U scikit-image

構造函數

class skimage.feature.ORB(downscale=1.2, n_scales=8, 
                        n_keypoints=500, fast_n=9, fast_threshold=0.08, harris_k=0.04)

downscale : 縮減因子,用於構建圖像金字塔,默認值1.2能夠加強特徵對圖像縮放尺度不變性
n_scales : 圖像金字塔的最大層數
n_keypoints : 指定最多檢測多少個關鍵點
fast_n : FAST算法的N值,即圓周上連續N個點符合閾值時,則中心點爲關鍵點
fast_threshold : FAST算法閾值,設Ic爲圓周上的像素值,Ip爲中心像素值,若 Ic < Ip - fast_threshold 或 Ic > Ip + fast_threshold,表示符合閾值
harris_k : 爲harris角檢測k方法中的k係數(詳見以前筆記),用於將角點從邊緣分離出來,典型取值區間[0, 0.2],值越小表示檢測越銳利的邊緣

類方法
detect(image): 檢測圖像關鍵點
extract(image, keypoints, scales, orientations): 爲給定關鍵點提取rBRIEF描述符
detect_and_extract(image): 檢測圖像關鍵點並提取rBRIEF描述符,此方法比用上面兩步要快

對象屬性
keypoints: 關鍵點座標數組
scales: 尺度數組
orientations: 方向(弧度)數組
responses: harris角檢測結果
descriptors:描述符數組

ORB論文中沒有描述如何比較兩個IPD的相關性和如何匹配,但BRIEF是有指出用漢明距離比較IPD。下面的例子,我使用是skimage庫中的一個匹配函數:

skimage.feature.match_descriptors(descriptors1, descriptors2, metric=None, 
                                            p=2, max_distance=inf, cross_check=True)

metric: 指定匹配算法: {‘euclidean’, ‘cityblock’, ‘minkowski’, ‘hamming’, ...},默認使用hamming(漢明距離)
max_distance: 兩個IPD之間的最大距離,小於此距離才認爲是匹配的,經測試,它的取值範圍爲[0.0,1.0]
cross_check: 爲True時,表示使用兩向匹配,即兩個IPD相互認爲對方是最佳匹配時,才肯定對應關係

綜合以上函數,找出兩張圖像的若干對應關鍵點的代碼示例:

from PIL import Image
import numpy as np
import matplotlib.pyplot as plt
from skimage.feature import (match_descriptors, ORB, plot_matches)
                             
im1 = Image.open('y1.jpg')
im2 = Image.open('y2.jpg')
img1 = np.array(im1.convert('L'))
img2 = np.array(im2.convert('L'))

o = ORB(n_keypoints=200)     #建立一個ORB對象,只提取200個關鍵點
o.detect_and_extract(img1)   #提取第一幅圖像                    
k1 = o.keypoints
d1 = o.descriptors

o.detect_and_extract(img2)   #提取第二幅圖像                       
k2 = o.keypoints
d2 = o.descriptors

matches12 = match_descriptors(d1, d2, cross_check=True, max_distance=0.5)

plot_matches(plt, im1, im2, k1, k2, matches12)
plt.axis('off')
plt.show()

效果圖:
圖片描述

小結

從整個ORB的設計思想能夠看出,它重在快速計算,目的就是爲了知足在實時計算情景下使用,並且經過大量的樣本分析得出,ORB並不遜於SIFT和SURF,反而在圖像受噪聲影響的狀況下,ORB表示出更穩定的特性。
另外,ORB的rBRIEF描述符須要事先訓練學習,但我以爲這不是問題,第一,今時今日很是容易收集和獲取到更具備表明性的數據樣本;第二,訓練這一步計算能夠由後臺服務器來實現,因此ORB很是適合在移動設備上使用。
目前,關於ORB可參考的中文資料缺少,加上論文原文有一些關鍵細節沒有表達出來,因此在學習ORB上花了較多的時間。但本文包含的所介紹的方法,其思想讓人視野開闊。
本文所述內容,可能存在理解誤差,歡迎指正。

參考資料

FAST
BRIEF
Image moment
ORB

相關文章
相關標籤/搜索