OpenCv提供了兩種描述符匹配方法:Brute-Force匹配與FLANN匹配
1.Brute-Force匹配
1.1創建BFMatcher物件
1.2使用兩個方法:match()或knnMatch()進行描述符匹配
1.3基于ORB或SIFT的BF匹配
2.FLANN匹配
2.1第一個字典是IndexParams
2.2第二個字典是SearchParams:
2.3FLANN匹配器示例
1.Brute-Force匹配
Brute-Force匹配又稱蠻力匹配, 將一組特征點中的每一個特征點描述符與另一組的最接近的特征點描述符匹配,
下面介紹OpenCv中的使用流程:
1.1創建BFMatcher物件
retval = cv.BFMatcher_create([, normType[, crossCheck]]) ,引數詳解如下
1.normType:NORM_L1,NORM_L2,NORM_HAMMING,NORM_HAMMING2四種可選,
SIFT與SUFT描述符應使用NORM_L1、NORM_L2,ORB、BRISK和BRIEF描述符應該使用NORM_HAMMING,使用ORB描述符但當WTA_K等于3或4時應該選用NORM_HAMMING2,
2.crossCheck:默認為FALSE,如果設定為TRUE,只有當兩組中特征點互相匹配時才算匹配成功,也就是說A組中x點描述符的最佳匹配點是B組的y點,那么B組的y點的描述符最佳匹配點也要是A組的x點才算匹配成功,
1.2使用兩個方法:match()或knnMatch()進行描述符匹配
二者的區別是match()回傳最佳匹配,knnMathch()回傳最佳的k個匹配,
matches = cv.DescriptorMatcher.match( queryDescriptors, trainDescriptors[, mask] )
# 創建BF匹配器物件
bf = cv2.BFMatcher_create(cv2.NORM_HAMMING, crossCheck=True)
# 特征點描述符匹配
matches = bf.match(des1,des2)
# 距離排序
matches = sorted(matches, key = lambda x:x.distance)
# 畫出前30匹配
img3 = cv2.drawMatches(img1, kp1, img2, kp2, matches[:30], None, flags=2)
matches = cv.DescriptorMatcher.knnMatch( queryDescriptors, trainDescriptors, k[, mask[, compactResult]] )
**注意,兩種方法對應的畫點方法也不一樣,
# 創建BF匹配器物件
bf = cv2.BFMatcher_create(cv2.NORM_HAMMING, crossCheck=True)
# 特征點描述符匹配
matches = bf.knnMatch(des1,des2,k=1)
# 畫出前30匹配
img3 = cv2.drawMatchesKnn(img1, kp1, img2, kp2, matches[:30], None, flags=2)
**關于Matcher物件:
可能會有人好奇回傳的變數matches是什么?其實是一種DMatch資料結構的串列,
DMatch結構含有:
DMatch.distance:描述符之間的距離,越低越好,
DMatch.queryIdx:主動匹配的描述符組中描述符的索引,
DMatch.trainIdx:被匹配的描述符組中描述符的索引,
DMatch.imgIdx:目標影像的索引,
更詳細見:
opencv中match與KnnMatch回傳值解釋
1.3基于ORB或SIFT的BF匹配
# 使用ORB描述符進行Brute-Force匹配:
import cv2
img1 = cv2.imread('gyy.jpg')
# 設一個ROI為被匹配的影像
ROI = img1[100:350,150:300]
img2=cv2.resize(ROI,None,fx=2,fy=2,interpolation=cv2.INTER_CUBIC)
# 初始化ORB特征點檢測器
orb = cv2.ORB_create()
# 檢測特征點與描述符
kp1, des1 = orb.detectAndCompute(img1,None)
kp2, des2 = orb.detectAndCompute(img2,None)
# 創建蠻力(BF)匹配器
bf = cv2.BFMatcher_create(cv2.NORM_HAMMING, crossCheck=True)
# 匹配描述符
matches = bf.match(des1,des2)
# 整理排序匹配后的描述符
matches = sorted(matches, key = lambda x:x.distance)
# 畫出前10個匹配的描述符
img3 = cv2.drawMatches(img1, kp1, img2, kp2, matches[:10], None, flags=2)
cv2.imshow("show",img3)
cv2.waitKey()
cv2.destroyAllWindows()

# 帶有SIFT描述符和比例測驗的BF匹配:
import cv2
img1 = cv2.imread('gyy.jpg')
# 設一個ROI為被匹配的影像
ROI = img1[250:350,150:300] # trainImage
img2=cv2.resize(ROI,None,fx=2,fy=2,interpolation=cv2.INTER_CUBIC)
# 初始化SIFT特征點檢測器
sift = cv2.xfeatures2d.SIFT_create()
# 檢測特征點與描述符
kp1, des1 = sift.detectAndCompute(img1,None)
kp2, des2 = sift.detectAndCompute(img2,None)
# 創建蠻力(BF)匹配器
bf = cv2.BFMatcher()
matches = bf.knnMatch(des1,des2, k=2)
# 比值測驗,首先獲取與 A 距離最近的點 B(最近)和 C(次近),只有當 B/C
# 小于閾值時( 0.75)才被認為是匹配,因為假設匹配是一一對應的,真正的匹配的理想距離為 0
good = []
for m,n in matches:
if m.distance < 0.75*n.distance:
good.append([m])
# cv.drawMatchesKnn()把串列作為匹配項,
img3 = cv2.drawMatchesKnn(img1,kp1,img2,kp2,good,None,flags=2)
cv2.imshow("show",img3)
cv2.waitKey()
cv2.destroyAllWindows()
2.FLANN匹配
FLANN是近似最近鄰的快速庫,它包含一組演算法,這些演算法針對大型資料集中的快速最近鄰搜索和高維特征進行了優化,對于大型資料集,它的運行速度比BFMatcher快,
基于FLANN的匹配器,我們需要傳遞兩個字典,這些字典指定要使用的演算法,其相關引數等,
2.1第一個字典是IndexParams
對于SIFT、SUFT演算法應該是:
FLANN_INDEX_KDTREE = 1
index_params = dict(algorithm = FLANN_INDEX_KDTREE, trees = 5)
對于ORB演算法應該是:
FLANN_INDEX_LSH = 6
index_params= dict(algorithm = FLANN_INDEX_LSH,
table_number = 6, # 12
key_size = 12, # 20
multi_probe_level = 1) #2
2.2第二個字典是SearchParams:
它指定索引中的樹應遞回遍歷的次數,較高的值可提供更好的精度,但也需要更多時間,例如:
search_params = dict(checks = 100)
2.3FLANN匹配器示例
import numpy as np
import cv2 as cv
import matplotlib.pyplot as plt
img1 = cv.imread('gyy.jpg',cv.IMREAD_GRAYSCALE) # 索引影像
img2 = cv.imread('gyy.jpg',cv.IMREAD_GRAYSCALE) # 訓練影像
# 初始化SIFT描述符
sift = cv.xfeatures2d.SIFT_create()
# 基于SIFT找到關鍵點和描述符
kp1, des1 = sift.detectAndCompute(img1,None)
kp2, des2 = sift.detectAndCompute(img2,None)
# FLANN的引數
FLANN_INDEX_KDTREE = 1
index_params = dict(algorithm = FLANN_INDEX_KDTREE, trees = 5)
search_params = dict(checks=50) # 或傳遞一個空字典
flann = cv.FlannBasedMatcher(index_params,search_params)
matches = flann.knnMatch(des1,des2,k=2)
# 只需要繪制好匹配項,因此創建一個掩碼
matchesMask = [[0,0] for i in range(len(matches))]
# 根據Lowe的論文進行比例測驗
for i,(m,n) in enumerate(matches):
if m.distance < 0.7*n.distance:
matchesMask[i]=[1,0]
draw_params = dict(matchColor = (0,255,0),
singlePointColor = (255,0,0),
matchesMask = matchesMask,
flags = cv.DrawMatchesFlags_DEFAULT)
img3 = cv.drawMatchesKnn(img1,kp1,img2,kp2,matches,None,**draw_params)
plt.imshow(img3,),plt.show()
轉載請註明出處,本文鏈接:https://www.uj5u.com/qita/293059.html
標籤:其他
上一篇:Opencv學習3.形狀識別模塊
下一篇:SSD+LBP實作人臉識別
