Python OpenCV特征檢測之特征匹配方式詳解
前言
獲得圖像的關(guān)鍵點后,可通過計算得到關(guān)鍵點的描述符。關(guān)鍵點描述符可用于圖像的特征匹配。通常,在計算圖A是否包含圖B的特征區(qū)域時,將圖A稱做訓(xùn)練圖像,將圖B稱為查詢圖像。圖A的關(guān)鍵點描述符稱為訓(xùn)練描述符,圖B的關(guān)鍵點描述符稱為查詢描述符。
一、暴力匹配器
暴力匹配器使用描述符進行特征比較。在比較時,暴力匹配器首先在查詢描述符中取一個關(guān)鍵點的描述符,將其與訓(xùn)練描述符中的所有關(guān)鍵點描述符進行比較,每次比較后會給出一個距離值,距離最小的值對應(yīng)最佳匹配結(jié)果。所有描述符比較完后,匹配器返回匹配結(jié)果列表。
OpenCV的cv2.BFMatcher_create()函數(shù)用于創(chuàng)建暴力匹配器,其基本格式如下:
bf = cv2.BFMatcher_create([normType[, crossCheck]])
bf為返回的暴力匹配器對象
normType為距離測量類型, 默認為cv2.NORM_L2, 通常, SIFT描述符使用cv2.NORM_L1或cv2.NORM_L2, ORB描述符使用cv2.NORM_HAMMING
crossCheck默認為False, 匹配器為每個查詢描述符找到k個距離最近的匹配描述符, 為True時, 只返回滿足交叉驗證條件的匹配結(jié)果
暴力匹配器對象的match()方法返回每個關(guān)鍵點的最佳匹配結(jié)果,其基本格式如下:
ms = bf.match(des1, des2)
ms為返回的結(jié)果, 它是一個DMatch對象列表, 每個DMatch對象表示關(guān)鍵點的一個匹配結(jié)果, 其dintance屬性表示距離, 距離值越小匹配度越高
des1為查詢描述符
des2為訓(xùn)練描述符
獲得匹配結(jié)果后,可調(diào)用cv2.drawMatches()函數(shù)或cv2.drawMatchesKnn()函數(shù)繪制匹配結(jié)果圖像,其基本格式如下:
outImg = cv2.drawMatches(img1, keypoints1, img2, keypoints2, matches1to2[, matchColor[, singlePointColor[, matchesMask[, flags]]]])
outImg為返回的繪制結(jié)果圖像, 圖像中查詢圖像與訓(xùn)練圖像中匹配的關(guān)鍵點個兩點之間的連線為彩色
img1為查詢圖像
keypoints1為img1的關(guān)鍵點
img2為訓(xùn)練圖像
keypoints2為img2的關(guān)鍵點
matches1to2為img1與img2的匹配結(jié)果
matchColor為關(guān)鍵點和鏈接線的顏色, 默認使用隨機顏色
singlePointColor為單個關(guān)鍵點的顏色, 默認使用隨機顏色
matchesMask為掩膜, 用于決定繪制哪些匹配結(jié)果, 默認為空, 表示繪制所有匹配結(jié)果
flags為標(biāo)志, 可設(shè)置為下列參數(shù)值:
cv2.DrawMatchesFlags_DEFAUL:默認方式, 繪制兩個源圖像、匹配項和單個關(guān)鍵點, 沒有圍繞關(guān)鍵點的圓以及關(guān)鍵點的大小和方向
cv2.DrawMatchesFlags_NOT_DRAW_SINGLE_POINTS:不會繪制單個關(guān)鍵點
cv2.DrawMatchesFlags_DRAW_RICH_KEYPOINTS:在關(guān)鍵點周圍繪制具有關(guān)鍵點大小和方向的圓圈
# 暴力匹配器、ORB描述符和match()方法
import cv2
img1 = cv2.imread("xhu1.jpg", cv2.IMREAD_GRAYSCALE)
img2 = cv2.imread("xhu2.jpg", cv2.IMREAD_GRAYSCALE)
orb = cv2.ORB_create()
kp1, des1 = orb.detectAndCompute(img1, None)
kp2, des2 = orb.detectAndCompute(img2, None)
bf = cv2.BFMatcher_create(cv2.NORM_HAMMING, crossCheck = False)
ms = bf.match(des1, des2)
ms = sorted(ms, key = lambda x:x.distance)
img3 = cv2.drawMatches(img1, kp1, img2, kp2, ms[:20], None, flags=cv2.DrawMatchesFlags_NOT_DRAW_SINGLE_POINTS)
cv2.imshow("Xhu1", img1)
cv2.imshow("Xhu2", img2)
cv2.imshow("Matches", img3)
cv2.waitKey(0)
cv2.destroyAllWindows()

# 暴力匹配器、SIFT描述符和match()方法
import cv2
img1 = cv2.imread("xhu1.jpg", cv2.IMREAD_GRAYSCALE)
img2 = cv2.imread("xhu2.jpg", cv2.IMREAD_GRAYSCALE)
sift=cv2.SIFT_create()
kp1, des1 = sift.detectAndCompute(img1, None)
kp2, des2 = sift.detectAndCompute(img2, None)
bf = cv2.BFMatcher_create(cv2.NORM_L1, crossCheck = False)
ms = bf.match(des1, des2)
ms = sorted(ms, key = lambda x:x.distance)
img3 = cv2.drawMatches(img1, kp1, img2, kp2, ms[:20], None, flags=cv2.DrawMatchesFlags_NOT_DRAW_SINGLE_POINTS)
# ms = np.expand_dims(ms,1)
# img3 = cv2.drawMatchesKnn(img1, kp1, img2, kp2, ms[:20], None, flags=cv2.DrawMatchesFlags_NOT_DRAW_SINGLE_POINTS)
cv2.imshow("Xhu1", img1)
cv2.imshow("Xhu2", img2)
cv2.imshow("Matches", img3)
cv2.waitKey(0)
cv2.destroyAllWindows()

暴力匹配器對象的knnMatch()方法可返回指定數(shù)量的最佳匹配結(jié)果,其基本格式如下:
ms = knnMatch(des1, des2, k=n)
ms為返回的匹配結(jié)果, 每個列表元素是一個子列表, 它包含了由參數(shù)k指定個數(shù)的DMatch對象
des1為查詢描述符
des2為訓(xùn)練描述符
k為返回的最佳匹配個數(shù)
# 暴力匹配器、ORB描述符和knnMatch()方法
import cv2
img1 = cv2.imread("xhu1.jpg", cv2.IMREAD_GRAYSCALE)
img2 = cv2.imread("xhu2.jpg", cv2.IMREAD_GRAYSCALE)
orb = cv2.ORB_create()
kp1, des1 = orb.detectAndCompute(img1, None)
kp2, des2 = orb.detectAndCompute(img2, None)
bf = cv2.BFMatcher_create(cv2.NORM_HAMMING, crossCheck = False)
ms = bf.knnMatch(des1, des2, k=2)
# 應(yīng)用比例測試選擇要使用的匹配結(jié)果
good = []
for m, n in ms:
if m.distance < 0.75 * n.distance:
good.append(m)
img3 = cv2.drawMatches(img1, kp1, img2, kp2, good[:20], None, flags=cv2.DrawMatchesFlags_NOT_DRAW_SINGLE_POINTS)
# good = np.expand_dims(good,1)
#img3 = cv2.drawMatchesKnn(img1, kp1, img2, kp2, good[:20], None, flags=cv2.DrawMatchesFlags_NOT_DRAW_SINGLE_POINTS)
cv2.imshow("Xhu1", img1)
cv2.imshow("Xhu2", img2)
cv2.imshow("Matches", img3)
cv2.waitKey(0)
cv2.destroyAllWindows()
二、FLANN匹配器
FLANN(Fast Library for Approximate Nearest Neignbors)為近似最近鄰的快速庫,F(xiàn)LANN特征匹配算法比其它的最近鄰算法更快。
在創(chuàng)建FLANN匹配器時,需要傳遞兩參數(shù):index_params和search_params。
index_params用來指定索引樹的算法類型和數(shù)量。SIFT算法可以使用下面的代碼來設(shè)置。
FLANN_INDEX_KDTREE = 1
index_params = dict(algorithm = FLANN_INDEX_KDTREE,
trees= 5)
ORB算法可以使用下面的代碼來設(shè)置。
FLANN_INDEX_LSH = 6
index_params = dict(algorithm = FLANN_INDEX_LSH,
table_number = 6,
key_size = 12,
multi_probe_level = 1)
search_params用于指定索引樹的遍歷次數(shù),遍歷次數(shù)越多,匹配結(jié)果越精細,通常設(shè)置為50即可,如下所示:
search_params = dict(check = 50)
# FLANN匹配器、ORB描述符
import cv2
img1 = cv2.imread("xhu1.jpg", cv2.IMREAD_GRAYSCALE)
img2 = cv2.imread("xhu2.jpg", cv2.IMREAD_GRAYSCALE)
orb = cv2.ORB_create()
kp1, des1 = orb.detectAndCompute(img1, None)
kp2, des2 = orb.detectAndCompute(img2, None)
# 定義FLANN參數(shù)
FLANN_INDEX_LSH = 6
index_params = dict(algorithm = FLANN_INDEX_LSH,
table_number = 6,
key_size = 12,
multi_probe_level = 1)
search_params = dict(check = 50)
flann = cv2.FlannBasedMatcher(index_params, search_params)
matches = flann.match(des1, des2)
draw_params = dict(matchColor = (0,255,0),
singlePointColor = (255,0,0),
matchesMask = None,
flags = cv2.DrawMatchesFlags_DEFAULT)
img3 = cv2.drawMatches(img1, kp1, img2, kp2, matches[:20], None, **draw_params)
cv2.imshow("Xhu1", img1)
cv2.imshow("Xhu2", img2)
cv2.imshow("Matches", img3)
cv2.waitKey(0)
cv2.destroyAllWindows()

# FLANN匹配器、SIFT描述符
import cv2
img1 = cv2.imread("xhu1.jpg", cv2.IMREAD_GRAYSCALE)
img2 = cv2.imread("xhu2.jpg", cv2.IMREAD_GRAYSCALE)
sift = cv2.SIFT_create()
kp1, des1 = sift.detectAndCompute(img1, None)
kp2, des2 = sift.detectAndCompute(img2, None)
# 定義FLANN參數(shù)
FLANN_INDEX_KDTREE = 1
index_params = dict(algorithm = FLANN_INDEX_KDTREE,
trees = 5)
search_params = dict(check = 50)
flann = cv2.FlannBasedMatcher(index_params, search_params)
matches = flann.match(des1, des2)
draw_params = dict(matchColor = (0,255,0),
singlePointColor = (255,0,0),
matchesMask = None,
flags = cv2.DrawMatchesFlags_DEFAULT)
img3 = cv2.drawMatches(img1, kp1, img2, kp2, matches[:20], None, **draw_params)
cv2.imshow("Xhu1", img1)
cv2.imshow("Xhu2", img2)
cv2.imshow("Matches", img3)
cv2.waitKey(0)
cv2.destroyAllWindows()

到此這篇關(guān)于Python OpenCV特征檢測之特征匹配方式詳解的文章就介紹到這了,更多相關(guān)Python OpenCV特征匹配內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Python 多維List創(chuàng)建的問題小結(jié)
這篇文章主要介紹了Python 多維List創(chuàng)建的問題小結(jié),詳細的介紹了遇到的一個小問題的解決方法,具有一定的參考價值,感興趣的小伙伴們可以參考一下2019-01-01
matplotlib交互式數(shù)據(jù)光標(biāo)實現(xiàn)(mplcursors)
這篇文章主要介紹了matplotlib交互式數(shù)據(jù)光標(biāo)實現(xiàn)(mplcursors),文中通過示例代碼介紹的非常詳細,對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2021-01-01

