十.OpenCv 特征点检测和匹配
-
特征點檢測和匹配
1. 特征檢測的基本概念
特征檢測是計算機視覺和圖像處理中的一個概念。它指的是使用計算機提取圖像信息,決定每個圖像的點是否屬于一個圖像特征。特征檢測的結果是把圖像上的點分為不同的子集,這些子集往往屬于孤立的點、連續的曲線或者連續的區域。
特征檢測包括邊緣檢測, 角檢測, 區域檢測和脊檢測.
特征檢測應用場景:
-
圖像搜索, 比如以圖搜圖
-
拼圖游戲
-
圖像拼接
…
以拼圖游戲為例來說明特征檢測的應用流程.
-
尋找特征
-
特征是唯一的
-
特征是可追蹤的
-
特征是能比較的
我們發現:
- 平坦部分很難找到它在原圖中的位置
- 邊緣相比平坦要好找一些, 但是也不能一下確定
- 角點可以一下就找到其在原圖中的位置
圖像特征就是值有意義的圖像區域, 具有獨特性, 易于識別性, 比較角點, 斑點以及高密度區.
在圖像特征中最重要的就是角點. 哪些是角點呢?
- 灰度梯度的最大值對應的像素
- 兩條線的交點
- 極值點(一階導數最大, 二階導數為0)
2. Harris角點檢測
Harris角點檢測原理
檢測窗口在圖像上移動, 上圖對應著三種情況:
- 在平坦區域, 無論向哪個方向移動, 衡量系統變換不大.
- 邊緣區域, 垂直邊緣移動時, 衡量系統變換劇烈.
- 在角點處, 往哪個方向移動, 衡量系統都變化劇烈.
- cornerHarris(src, blockSize, ksize, k[, dst[, borderType]])
- blockSize: 檢測窗口大小
- ksize: sobel的卷積核
- k: 權重系數, 即上面公式中的α\alphaα , 是個經驗值, 一般取0.04~0.06之間.一般默認0.04
3. Shi-Tomasi角點檢測
-
Shi-Tomasi是Harris角點檢測的改進.
-
Harris角點檢測計算的穩定性和K有關, 而K是一個經驗值, 不太好設定最佳的K值.
-
Shi-Tomasi 發現,角點的穩定性其實和矩陣 M 的較小特征值有關,于是直接用較小的那個特征值作為分數。這樣就不用調整k值了。
- Shi-Tomasi 將分數公式改為如下形式:R=min(λ1λ2)R= min(\lambda_1\lambda_2)R=min(λ1?λ2?)
- 和 Harris 一樣,如果該分數大于設定的閾值,我們就認為它是一個角點。
-
goodFeaturesToTrack(image, maxCorners, qualityLevel, minDistance[, corners[, mask[, blockSize[, useHarrisDetector[, k]]]]])
- maxCorners: 角點的最大數, 值為0表示無限制
- qualityLevel: 角點質量, 小于1.0的整數, 一般在0.01-0.1之間.
- minDistance: 角之間最小歐式距離, 忽略小于此距離的點.
- mask: 感興趣的區域.
- blockSize: 檢測窗口大小
- useHarrisDetector: 是否使用Harris算法.
- k: 默認是0.04
4. SIFT關鍵點檢測
SIFT,即尺度不變特征變換(Scale-invariant feature transform,SIFT),是用于圖像處理領域的一種描述。這種描述具有尺度不變性,可在圖像中檢測出關鍵點,是一種局部特征描述子。
Harris角點具有旋轉不變的特性.但是縮放后, 原來的角點有可能就不是角點了.
SIFT原理
-
圖像尺度空間
在一定的范圍內,無論物體是大還是小,人眼都可以分辨出來,然而計算機要有相同的能力卻很難,所以要讓機器能夠對物體在不同尺度下有一個統一的認知,就需要考慮圖像在不同的尺度下都存在的特點。
尺度空間的獲取通常使用高斯模糊來實現
不同σ的高斯函數決定了對圖像的平滑程度,越大的σ值對應的圖像越模糊。
- 多分辨率金字塔
- 高斯差分金字塔(DOG)
-
DoG空間極值檢測
為了尋找尺度空間的極值點,每個像素點要和其圖像域(同一尺度空間)和尺度域(相鄰的尺度空間)的所有相鄰點進行比較,當其大于(或者小于)所有相鄰點時,該點就是極值點。如下圖所示,中間的檢測點要和其所在圖像的3×3鄰域8個像素點,以及其相鄰的上下兩層的3×3領域18個像素點,共26個像素點進行比較。
-
關鍵點的精確定位
這些候選關鍵點是DOG空間的局部極值點,而且這些極值點均為離散的點,精確定位極值點的一種方法是,對尺度空間DoG函數進行曲線擬合,計算其極值點,從而實現關鍵點的精確定位。
- 消除邊界響應
- 特征點的主方向
每個特征點可以得到三個信息(x,y,σ,θ),即位置、尺度和方向。具有多個方向的關鍵點可以被復制成多份,然后將方向值分別賦給復制后的特征點,一個特征點就產生了多個坐標、尺度相等,但是方向不同的特征點。
-
生成特征描述
為了保證特征矢量的旋轉不變性,要以特征點為中心,在附近鄰域內將坐標軸旋轉θ角度,即將坐標軸旋轉為特征點的主方向。
旋轉之后的主方向為中心取8x8的窗口,求每個像素的梯度幅值和方向,箭頭方向代表梯度方向,長度代表梯度幅值,然后利用高斯窗口對其進行加權運算,最后在每個4x4的小塊上繪制8個方向的梯度直方圖,計算每個梯度方向的累加值,即可形成一個種子點,即每個特征的由4個種子點組成,每個種子點有8個方向的向量信息。
論文中建議對每個關鍵點使用4x4共16個種子點來描述,這樣一個關鍵點就會產生128維的SIFT特征向量。
使用SIFT的步驟
- 創建SIFT對象 sift = cv2.xfeatures2d.SIFT_create()
- 進行檢測, kp = sift. detect(img, …)
- 繪制關鍵點, drawKeypoints(gray, kp, img)
關鍵點和描述子
關鍵點: 位置, 大小和方向.
關鍵點描述子: 記錄了關鍵點周圍對其有共享的像素點的一組向量值, 其不受仿射變換, 光照變換等影響.描述子的作用就是進行特征匹配, 在后面進行特征匹配的時候會用上.
import cv2 import numpy as npimg = cv2.imread('chess.png')gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)# 創建sift對象 sift = cv2.xfeatures2d.SIFT_create()# 進行檢測 kp = sift.detect(gray)# 檢測關鍵點, 并計算描述子 kp, des = sift.compute(img, kp) # 或者一步到位, 把關鍵點和描述子一起檢測出來. kp, des = sift.detectAndCompute(img, None) # print(kp) print(des) print(des.shape)# 繪制關鍵點 cv2.drawKeypoints(gray, kp, img)cv2.imshow('img', img) cv2.waitKey(0) cv2.destroyAllWindows()5. SURF特征檢測
Speeded Up Robust Features(SURF,加速穩健特征),是一種穩健的局部特征點檢測和描述算法。最初由Herbert Bay發表在2006年的歐洲計算機視覺國際會議(Europen Conference on Computer Vision,ECCV)上,并在2008年正式發表在Computer Vision and Image Understanding期刊上。
Surf是對David Lowe在1999年提出的Sift算法的改進,提升了算法的執行效率,為算法在實時計算機視覺系統中應用提供了可能。
SIFT最大的問題就是速度慢, 因此才有了SURF.
如果想對一系列的圖片進行快速的特征檢測, 使用SIFT會非常慢.
注意: SURF在較新版本的OpenCV中已經申請專利, 需要降OpenCV版本才能使用. 降到3.4.1.15就可以用了.
import cv2 import numpy as npimg = cv2.imread('chess.png')gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)# 創建SURF對象 surf = cv2.xfeatures2d.SURF_create()# 進行檢測 kp = surf.detect(gray)# 檢測關鍵點, 并計算描述子 kp, des = surf.compute(img, kp) # 或者一步到位, 把關鍵點和描述子一起檢測出來. kp, des = surf.detectAndCompute(img, None) # print(kp) print(des) print(des.shape)# 繪制關鍵點 cv2.drawKeypoints(gray, kp, img)cv2.imshow('img', img) cv2.waitKey(0) cv2.destroyAllWindows()6. OBR特征檢測
ORB(Oriented FAST and Rotated BRIEF)是一種快速特征點提取和描述的算法。這個算法是由Ethan Rublee, Vincent Rabaud, Kurt Konolige以及Gary R.Bradski在2011年一篇名為“ORB:An Efficient Alternative to SIFTor SURF”( http://www.willowgarage.com/sites/default/files/orb_final.pdf )的文章中提出。ORB算法分為兩部分,分別是特征點提取和特征點描述。特征提取是由FAST(Features from Accelerated Segment Test)算法發展來的,特征點描述是根據BRIEF(Binary Robust IndependentElementary Features)特征描述算法改進的。ORB特征是將FAST特征點的檢測方法與BRIEF特征描述子結合起來,并在它們原來的基礎上做了改進與優化。ORB算法最大的特點就是計算速度快。這首先得益于使用FAST檢測特征點,FAST的檢測速度正如它的名字一樣是出了名的快。再次是使用BRIEF算法計算描述子,該描述子特有的2進制串的表現形式不僅節約了存儲空間,而且大大縮短了匹配的時間。
ORB最大的優勢就是可以做到實時檢測ORB的劣勢是檢測準確性略有下降.
ORB還有一個優勢是ORB是開源的算法, 沒有版權問題, 可以自由使用.SIFT和SURF都被申請了專利.
import cv2 import numpy as npimg = cv2.imread('chess.png')gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)# 創建ORB對象 orb = cv2.ORB_create()# 進行檢測 kp = orb.detect(gray)# 檢測關鍵點, 并計算描述子 kp, des = orb.compute(img, kp) # 或者一步到位, 把關鍵點和描述子一起檢測出來. kp, des = orb.detectAndCompute(img, None) # print(kp) print(des) print(des.shape)# 繪制關鍵點 cv2.drawKeypoints(gray, kp, img)cv2.imshow('img', img) cv2.waitKey(0) cv2.destroyAllWindows()三種算法對比
- SIFT 最慢, 準確率最高
- SURF 速度比SIFT快些, 準確率差些
- ORB速度最快, 可以實時檢測, 準確率最差.
7. 暴力特征匹配
我們獲取到圖像特征點和描述子之后, 可以將兩幅圖像進行特征匹配.
BF(Brute-Force) 暴力特征匹配方法, 通過枚舉的方式進行特征匹配.
暴力匹配器很簡單。它使用第一組(即第一幅圖像)中一個特征的描述子,并使用一些距離計算將其與第二組中的所有其他特征匹配。并返回最接近的一個。
- BFMatcher(normType, crossCheck)
- normType計算距離的方式.
- NORM_L1, L1距離, 即絕對值, SIFT和SURF使用.
- NORM_L2, L2距離, 默認值. 即平方. SIFT和SURF使用
- HAMMING 漢明距離. ORB使用
- crossCheck: 是否進行交叉匹配, 默認False.
- normType計算距離的方式.
- 使用match函數進行特征點匹配, 返回的對象為DMatch對象. 該對象具有以下屬性:
- DMatch.distance - 描述符之間的距離。 越低,它就越好。
- DMatch.trainIdx – 訓練描述符中描述符的索引
- DMatch.queryIdx - 查詢描述符中描述符的索引
- DMatch.imgIdx – 訓練圖像的索引
- drawMatches 繪制匹配的特征點
8. FLANN特征匹配
FLANN是快速最近鄰搜索包(Fast_Library_for_Approximate_Nearest_Neighbors)的簡稱。它是一個對大數據集和高維特征進行最近鄰搜索的算法的集合,而且這些算法都已經被優化過了。在面對大數據集是它的效果要好于BFMatcher。
特征匹配記錄下目標圖像與待匹配圖像的特征點(KeyPoint),并根據特征點集合(即特征描述子)構造特征量(descriptor),對這個特征量進行比較、篩選,最終得到一個匹配點的映射集合。我們也可以根據這個集合的大小來衡量兩幅圖片的匹配程度。
- FlannBasedMatcher(index_params)
- index_params字典: 匹配算法KDTREE, LSH, SIFT和SURF使用KDTREE算法, OBR使用LSH算法.
- 設置示例: index_params=dict(algorithm=cv2.FLANN_INDEX_KDTREE, tree=5)
- FLANN_INDEX_LSH = 6index_params= dict(algorithm = FLANN_INDEX_LSH, table_number = 6, # 12 key_size = 12, # 20 multi_probe_level = 1#2)
- search_params字典: 指定KDTREE算法中遍歷樹的次數.經驗值, 如KDTREE設為5, 那么搜索次數設為50.
- search_params = dict(checks=50)
- index_params字典: 匹配算法KDTREE, LSH, SIFT和SURF使用KDTREE算法, OBR使用LSH算法.
- Flann中除了普通的match方法, 還有knnMatch方法.
- 多了個參數–k, 表示取歐式距離最近的前k個關鍵點.
9. 圖像查找
通過特征匹配和單應性矩陣我們可以實現圖像查找.
基本的原理是通過特征匹配得到匹配結果, 作為輸入, 得到單應性矩陣, 再經過透視變換就能夠找到最終的圖像.
9.1 單應性矩陣
單應性(Homography)變換 :可以簡單的理解為它用來描述物體在世界坐標系和像素坐標系之間的位置映射關系。對應的變換矩陣稱為單應性矩陣。
- 單應性矩陣的應用
- 把圖片擺正
- 圖片替換
- findHomography(srcPoints, dstPoints[, method[, ransacReprojThreshold[, mask[, maxIters[, confidence]]]]])
-
srcPoints: 源平面中點的坐標矩陣,可以是CV_32FC2類型,也可以是vector <Point2f>類型
-
dstPoints: 目標平面中點的坐標矩陣,可以是CV_32FC2類型,也可以是vector <Point2f>類型
-
method: 計算單應矩陣所使用的方法。不同的方法對應不同的參數,具體如下:
- 0 - 利用所有點的常規方法
- RANSAC - RANSAC-基于RANSAC的魯棒算法
- LMEDS - 最小中值魯棒算法
- PROSAC-基于PROSAC的魯棒算法
-
ransacReprojThreshold: 將點對視為內點的最大允許重投影錯誤閾值(僅用于RANSAC和RHO方法)。若srcPoints和dstPoints是以像素為單位的,則該參數通常設置在1到10的范圍內。
-
mask: 可選輸出掩碼矩陣,通常由魯棒算法(RANSAC或LMEDS)設置。 請注意,輸入掩碼矩陣是不需要設置的。
-
maxIters: RANSAC算法的最大迭代次數,默認值為2000。
-
confidence: 可信度值,取值范圍為0到1.
-
-
總結
以上是生活随笔為你收集整理的十.OpenCv 特征点检测和匹配的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 理工科学子,从事工程仿真所需的知识结构和
- 下一篇: STM32串口通信原理及实验讲解