1. 程式人生 > >第十六節、基於ORB的特徵檢測和特徵匹配

第十六節、基於ORB的特徵檢測和特徵匹配

之前我們已經介紹了SIFT演算法,以及SURF演算法,但是由於計算速度較慢的原因。人們提出了使用ORB來替代SIFT和SURF。與前兩者相比,ORB有更快的速度。ORB在2011年才首次釋出。在前面小節中,我們已經提到了ORB演算法。ORB演算法將基於FAST關鍵點的技術和基於BRIEF描述符的技術相結合,關於FAST和BRIEF相關內容可以參考部落格第十四節、FAST角點檢測(附原始碼)第十六節、特徵描述符BRIEF(附原始碼)

一 ORB演算法原理

ORB演算法將FAST特徵點的檢測方法和BRIEF特徵描述子結合起來,並在它們的基礎上做了改進與優化。

首先,它利用FAST特徵點檢測的方法來檢測特徵點,然後利用Harris角點的度量方法,從FAST特徵點中挑選出Harris角點響應值最大的N個特徵點。其中Harris角點的響應函式定義為:

$$R=detM-k(trace(M))^2$$

1、旋轉不變性

在現在生活中,我們從不同的距離,不同的方向、角度、不同的光照條件下觀察一個物體時,物體的大小、形狀,明暗都會有所不同。但是我們仍然可以判斷它是一個物體。理想的特徵描述子應該具備這些性質,即在大小、方向、明暗不同的影象中,同一特徵點應具有足夠相似的描述子,稱之為描述子的可復現性。

但是ORB並沒有解決尺度不一致的問題,在OpenCV的ORB實現中採用了影象金字塔來改善這方面的效能,我們通過構建高斯金字塔,然後在每一層金字塔影象上檢測角點,來實現尺度不變性。ORB主要解決了BRIEF描述子不具備旋轉不變性的問題,ORB論文種提出了一種利用灰度質心法來解決這個問題,灰度質心法假設角點的灰度與質心之間存在一個偏移,這個向量可以用於表示一個方向。對於任意一個特徵點$p$來說,我們定義$p$的鄰域畫素的矩為:

$$m_{ij}=\sum\limits_{x=-r}^{r}\sum\limits_{y=-r}^{r}x^iy^jI(x,y)$$

其中$I(x,y)$為點$(x,y)$處的灰度值,$q$為質心,$i,j=0,1$。那麼我們可以得到影象的質心為:

$$C=(\frac{m_{10}}{m_{00}},\frac{m_{01}}{m_{00}})$$

那麼特徵點與質心的夾角定義為FAST特徵點的方向:

$$\theta=arctan(m_{01},m_{10})$$

為了提高演算法的旋轉不變性,需要確保$x$和$y$在半徑為$r$的圓形區域內,即$x,y\in[-r,r]$,$r$等於鄰域半徑。

2、特徵點的描述

ORB選擇了BRIEF作為特徵描述方法,但是我們知道BRIEF不具備旋轉不變性,所以我們要給BRIEF加上旋轉不變性,把這種方法稱為"Steer BRIEF"。對於任何一個特徵點來說,它的BRIEF描述子是一個長度為$n$的二值碼串,這個二值碼串是由特徵點鄰域$n$個點對生成的,我們現在講這$2n$個點$(x_i,y_i),i=1,2,.....,2n$組成一個矩陣$S$:

$$S=\begin{bmatrix} x_1 & x_2 & ... &x_{2n} \\ y_1 & y_2 & ... & y_{2n} \end{bmatrix}$$

Calonder建議為每個塊的旋轉和投影集合分別計算BRIEF描述子,但代價昂貴。ORB中採用了一個更有效的方法:使用鄰域方向$\theta$和對應的旋轉矩陣$R_{\theta}$,構建$S$的一個校正版本$S_{\theta}$:

$$S_{\theta}=R_{\theta}S$$

其中:

$$R_{\theta}=\begin{bmatrix} cos\theta & sin\theta \\ -sin\theta & cos\theta \end{bmatrix}$$

而$\theta$即我們為特徵點求得的主方向。

即我們把座標軸旋轉$]theta$,計算以主方向為座標系的匹配點對,如下圖:

實際上,我們可以把角度離散化,即把360度分為12份,每一份是30度,然後我們對這個12個角度分別求得一個$S_{\theta}$,這樣我們就建立了一個查詢表,對於每一個$\theta$,我們只需要查表即可快速得到它的點的集合$S_{\theta}$。

3、解決描述子的區分性

BRIEF令人驚喜的特性之一是:對於$n$維的二值串的每個特徵位,所有特徵點在該位上的值都滿足一個均值接近於0.5,而方差很大的高斯分佈。方差越大,說明區分性越強,那麼不同特徵點的描述子就表現出來越大差異性,對匹配來說不容易誤配。但是當我們把BRIEF沿著特徵點的方向調整為Steered BRIEF時,均值就漂移到一個更加分散式的模式。可以理解為有方向性的角點關鍵點對二值串則展現了一個更加均衡的表現。而且論文中提到經過PCA對各個特徵向量進行分析,得知Steered BRIEF的方差很小,判別性小,各個成分之間相關性較大。

為了減少Steered BRIEF方差的虧損,並減少二進位制碼串之間的相關性,ORB使用了一種學習的方法來選擇一個較小的點對集合。方法如下:

首先建立一個大約300k關鍵點的測試集,這些關鍵點來自於PASCAL2006集中的影象。

對於這300k個關鍵點中的每一個特徵點,考慮它的$31\times{31}$的鄰域,我們將在這個鄰域內找一些點對,不同於BRIEF中要先對這個Patch內的點做平滑,再用以Patch中心為原點的高斯分佈選擇點對的方法。ORB為了去除某些噪聲點的干擾,選擇了一個$5\times{5}$大小的區域的平均灰度來代替原來一個單點的灰度,這裡$5\times{5}$區域內影象平均灰度的計算可以用積分圖的方法。我們知道$31\times{31}$的Patch裡共有$N=(31-5+1)\times{(31-5+1)}$個這種視窗,那麼我們要$N$個子視窗中選擇2個子視窗的話,共有$C_N^2$種方法。所以對於300k中每一個特徵點,我們都可以從它的$31\times{31}$大小的鄰域中提取一個很長的二進位制串,長度為$M=C_N^2$,表示為:

$$binArray = \begin{bmatrix} p_1 & p_2 & ... &p_M \end{bmatrix},p_i\in\{0,1\} $$

那麼當300k個關鍵點全部進行上面的特徵提取之後,我們就得到了一個$300k\times{M}$的矩陣,矩陣中的每個元素值為0或者1.

對該矩陣的每個列向量,也就是每個點對在300k個特徵點上的測試結果,計算其均值。把所有的列向量按均值進行重新排序。排好後,組成了一個向量$T$,$T$的每一個元素都是一個列向量。

進行貪婪搜尋,從$T$中把排在第一的那個列放到$R$中,$T$中就沒有這個點對的測試結果了,然後把$T$中的排在下一個的列與$R$中的所有元素比較,計算它們的相關性,如果相關超過了某一事先設定好的閾值,就扔了它,否則就把它方到$R$裡面。重複上面的步驟,直到$R$中有256個列向量位置。如果把$T$全部找完也沒有找到256個,那麼我們可以把相關的閾值調高一些,再嘗試一遍。

這樣,我們就得到了256個點對。上面這個過程我們稱它為rBRIEF。

二 OpenCV實現

 ORB中有很多引數可以設定,在OpenCV中它可以通過ORB來建立一個ORB檢測器。

cv2.ORB_create([,nfeatues[,scaleFactor[,nlevels[,edgeThreshold[,firstLevel[,WTA_K[,[scoreType,[patchSize,fastThreshold]]]]]]]]])

引數說明:

  • nfeatures :最多提取的特徵點的數量;
  • scaleFactor : 金字塔影象之間的尺度引數,類似於SIFT中的$k$;
  • nlevels: 高斯金字塔的層數;
  • edgeThreshold :邊緣閾值,這個值主要是根據後面的patchSize來定的,靠近邊緣edgeThreshold以內的畫素是不檢測特徵點的。
  • firstLevel-:看過SIFT都知道,我們可以指定第一層的索引值,這裡預設為0。
  • WET_K : 用於產生BIREF描述子的點對的個數,一般為2個,也可以設定為3個或4個,那麼這時候描述子之間的距離計算就不能用漢明距離了,而是應該用一個變種。OpenCV中,如果設定WET_K = 2,則選用點對就只有2個點,匹配的時候距離引數選擇NORM_HAMMING,如果WET_K設定為3或4,則BIREF描述子會選擇3個或4個點,那麼後面匹配的時候應該選擇的距離引數為NORM_HAMMING2。
  • scoreType :用於對特徵點進行排序的演算法,你可以選擇HARRIS_SCORE,也可以選擇FAST_SCORE,但是它也只是比前者快一點點而已。
  • patchSize :用於計算BIREF描述子的特徵點鄰域大小。
# -*- coding: utf-8 -*-
"""
Created on Mon Sep 10 22:37:36 2018

@author: zy
"""

'''
ORB特徵匹配
'''
import numpy as np
import cv2


def orb_test():
    #載入圖片  灰色
    img1 = cv2.imread('./image/orb1.jpg')    
    gray1 = cv2.cvtColor(img1,cv2.COLOR_BGR2GRAY)
    img2 = cv2.imread('./image/orb2.jpg')
    img2 = cv2.resize(img2,dsize=(450,300))
    gray2 = cv2.cvtColor(img2,cv2.COLOR_BGR2GRAY)
    image1 = gray1.copy()
    image2 = gray2.copy()
    
    '''
    1.使用ORB演算法檢測特徵點、描述符
    '''
    orb = cv2.ORB_create(128)
    keypoints1,descriptors1 =  orb.detectAndCompute(image1,None)
    keypoints2,descriptors2 =  orb.detectAndCompute(image2,None)    
    #在影象上繪製關鍵點
    image1 = cv2.drawKeypoints(image=image1,keypoints = keypoints1,outImage=image1,color=(255,0,255),flags=cv2.DRAW_MATCHES_FLAGS_DRAW_RICH_KEYPOINTS)
    image2 = cv2.drawKeypoints(image=image2,keypoints = keypoints2,outImage=image2,color=(255,0,255),flags=cv2.DRAW_MATCHES_FLAGS_DRAW_RICH_KEYPOINTS)
    #顯示影象
    cv2.imshow('orb_keypoints1',image1)
    cv2.imshow('orb_keypoints2',image2)
    cv2.waitKey(20)
    
    '''
    2、匹配
    '''
    matcher = cv2.BFMatcher_create(cv2.HAMMING_NORM_TYPE,crossCheck=True)    
    matchePoints = matcher.match(descriptors1,descriptors2)
    print(type(matchePoints),len(matchePoints),matchePoints[0])
    #按照距離從小到大排序,選取最優匹配的
    sorted(matchePoints,key=lambda x:x.distance)
    #繪製最優匹配點
    outImg = None
    outImg = cv2.drawMatches(img1,keypoints1,img2,keypoints2,matchePoints[:10],outImg,matchColor=(0,255,0),flags=cv2.DRAW_MATCHES_FLAGS_DEFAULT)
    cv2.imshow('matche',outImg)
    cv2.waitKey(0)
    cv2.destroyAllWindows()
    
    
    cv2.waitKey(0)
    cv2.destroyAllWindows()
    
if __name__ == '__main__':
    orb_test()

參考文章:

相關推薦

基於ORB特徵檢測特徵匹配

之前我們已經介紹了SIFT演算法,以及SURF演算法,但是由於計算速度較慢的原因。人們提出了使用ORB來替代SIFT和SURF。與前兩者相比,ORB有更快的速度。ORB在2011年才首次釋出。在前面小節中,我們已經提到了ORB演算法。ORB演算法將基於FAST關鍵點的技術和基於BRIEF描述符的技術相結合,關

特徵描述符BRIEF(附原始碼)

我們已經知道SIFT演算法採用128維的特徵描述子,由於描述子用的是浮點數,所以它將會佔用512位元組的空間。類似的SUFR演算法,一般採用64維的描述子,它將佔用256位元組的空間。如果一幅影象中有1000個特徵點,那麼SIFT或SURF特徵描述子將佔用大量的記憶體空間,對於那些資源緊張的應用,尤其是嵌入式

基於傳統影象處理的目標檢測與識別(詞袋模型BOW+SVM附程式碼)

在上一節、我們已經介紹了使用HOG和SVM實現目標檢測和識別,這一節我們將介紹使用詞袋模型BOW和SVM實現目標檢測和識別。 一 詞袋介紹 詞袋模型(Bag-Of-Word)的概念最初不是針對計算機視覺的,但計算機視覺會使用該概念的升級。詞袋最早出現在神經語言程式學(NLP)和資訊檢索(IR)領域,該模型

模組化操作

在ES5中我們要進行模組華操作需要引入第三方類庫,隨著前後端分離,前端的業務日漸複雜,ES6為我們增加了模組話操作。模組化操作主要包括兩個方面。 export :負責進行模組化,也是模組的輸出。 import:負責八模組引入,也是模組的引入操作。 exp

Harris角點檢測原理

str 物體 per 權重 模式 windows www http 特定 OpenCV可以檢測圖像的主要特征,然後提取這些特征、使其成為圖像描述符,這類似於人的眼睛和大腦。這些圖像特征可作為圖像搜索的數據庫。此外,人們可以利用這些關鍵點將圖像拼接起來,組成一個更大的圖像,比

Harris角點檢測原理(附原始碼)

OpenCV可以檢測影象的主要特徵,然後提取這些特徵、使其成為影象描述符,這類似於人的眼睛和大腦。這些影象特徵可作為影象搜尋的資料庫。此外,人們可以利用這些關鍵點將影象拼接起來,組成一個更大的影象,比如將許多影象放在一塊,然後形成一個360度全景影象。 這裡我們將學習使用OpenCV來檢測影象特徵,並利用這些

FAST角點檢測(附原始碼)

在前面我們已經陸續介紹了許多特徵檢測運算元,我們可以根據影象區域性的自相關函式求得Harris角點,後面又提到了兩種十分優秀的特徵點以及他們的描述方法SIFT特徵和SURF特徵。SURF特徵是為了提高運算效率對SIFT特徵的一種近似,雖然在有些實驗環境中已經達到了實時,但是我們實踐工程應用中,特徵點的提取與匹

尺度不變特徵(SIFT)

上一節中,我們介紹了Harris角點檢測。角點在影象旋轉的情況下也可以檢測到,但是如果減小(或者增加)影象的大小,可能會丟失影象的某些部分,甚至導致檢測到的角點發生改變。這樣的損失現象需要一種與影象比例無關的角點檢測方法來解決。尺度不變特徵變換(Scale-Invariant Feature Transfor

學習筆記

作業 學習筆記 第十六節課 lvm講解 lvm有很大的便利性,可以方便的擴容和縮容磁盤的空間。(但是也有局限性) 一旦出現問題,磁盤使用lvm,文件系統壞了,數據沒了,恢復數據的時候很麻煩。 做個實驗:創建三個磁盤分區,(這裏要註意下ID 是83,說明他是普通的分區。如果要想使用lvm,就要修改

【php增刪改查實例】 - 用戶新增

img dialog onsubmit null 允許 array 增刪改查 res UNC 6.1工具欄 <div id="toolbar"> <a href="javascript:openDialog()" class="easyu

韋伯局部描述符(WLB)

times 向量 font .com ima 灰度共生矩陣 領域 局部特征 limit 紋理作為一種重要的視覺線索,是圖像中普遍存在而又難以描述的特征,圖像的紋理特征一般是指圖像上地物重復排列造成的灰度值有規則的分布。紋理特征的關鍵在於紋理特征的提取方法。目前,用於紋理特征

學習筆記一類,第二類斯特林數Bell數(坑)

正題       百度:“       在組合數學,Stirling數可指兩類數,第一類Stirling數和第二類Stirling數,都是由18世紀數學家James Stirling提出的。   

,使用函式封裝庫tf.contrib.layers

這一節,介紹TensorFlow中的一個封裝好的高階庫,裡面有前面講過的很多函式的高階封裝,使用這個高階庫來開發程式將會提高效率。 我們改寫第十三節的程式,卷積函式我們使用tf.contrib.layers.conv2d(),池化函式使用tf.contrib.layers.max_pool2d(

課:16,17章,Squid服務iscsi網路儲存

第十六章 squid總結: 正向代理:yum  安裝後清空防火牆即可正常使用,客戶端設定瀏覽器 透明正向代理:vim  /etc/squid/squid.conf                 &

20181214

Squid是Linux系統中最為流行的一款高效能代理服務軟體, 通常用作Web網站的前置快取服務,能夠代替使用者向網站 伺服器請求頁面資料並進行快取。   硬碟介面型別主要有IDE、SCSI和SATA這3種 DE是一種成熟穩定、價格便宜的並行傳輸介面。 SATA是一種傳輸速度

Spark修煉之道(進階篇)——Spark入門到精通: Spark Streaming與Kafka

作者:周志湖 主要內容 Spark Streaming與Kafka版的WordCount示例(一) Spark Streaming與Kafka版的WordCount示例(二) 1. Spark Streaming與Kafka版本的WordCount示例

Scala入門到精通—— 泛型與註解

本節主要內容 泛型(Generic Type)簡介 註解(Annotation)簡介 註解常用場景 1. 泛型(Generic Type)簡介 泛型用於指定方法或類可以接受任意型別引數,引數在實際使用時才被確定,泛型可以有效地增強程式的適用性,使用

css進階:消除未使用的css

相信有很多人都用過Bootstrap這個框架,我們在使用的時候每個頁面只使用了其中一小部分的css樣式,對著專案的推進,css程式碼會越來越多,有些是你自己寫的,有的是你直接使用框架定義好的,到後期進行需求更改的時候我們可能就無暇關注css樣式,造成很多css的冗餘。這節內

Spring入門學習(AOP返回通知&異常通知&環繞通知&切面的優先順序)

Spring入門學習(AOP返回通知&異常通知&環繞通知) 返回通知 異常通知 環繞通知 切面的優先順序 返回通知 使用`@AfterReturning`註解,在方法正常結束後執行的通知,它是可以獲得方法的返回

鳥哥的Linux私房菜(伺服器)- 檔案伺服器之二: SAMBA 伺服器

時至今日,印表機的網路功能已經很強悍了!甚至也有支援無線網路的印表機,因此每臺印表機都可以獨立作為各個 PC 的獨自的印表機,老實說也沒有必要進行 Samba 的網路印表機伺服器啦!但畢竟還是有些比較舊型的機種, 或者買不起有內建網路的印表機時,那麼 Samba 的印表機伺服器還是有存在的價值囉。 在