Python OpenCV特征檢測(cè)之特征匹配方式詳解
前言
獲得圖像的關(guān)鍵點(diǎn)后,可通過(guò)計(jì)算得到關(guān)鍵點(diǎn)的描述符。關(guān)鍵點(diǎn)描述符可用于圖像的特征匹配。通常,在計(jì)算圖A是否包含圖B的特征區(qū)域時(shí),將圖A稱(chēng)做訓(xùn)練圖像,將圖B稱(chēng)為查詢圖像。圖A的關(guān)鍵點(diǎn)描述符稱(chēng)為訓(xùn)練描述符,圖B的關(guān)鍵點(diǎn)描述符稱(chēng)為查詢描述符。
一、暴力匹配器
暴力匹配器使用描述符進(jìn)行特征比較。在比較時(shí),暴力匹配器首先在查詢描述符中取一個(gè)關(guān)鍵點(diǎn)的描述符,將其與訓(xùn)練描述符中的所有關(guān)鍵點(diǎn)描述符進(jìn)行比較,每次比較后會(huì)給出一個(gè)距離值,距離最小的值對(duì)應(yīng)最佳匹配結(jié)果。所有描述符比較完后,匹配器返回匹配結(jié)果列表。
OpenCV的cv2.BFMatcher_create()函數(shù)用于創(chuàng)建暴力匹配器,其基本格式如下:
bf = cv2.BFMatcher_create([normType[, crossCheck]])
bf
為返回的暴力匹配器對(duì)象
normType
為距離測(cè)量類(lèi)型, 默認(rèn)為cv2.NORM_L2, 通常, SIFT描述符使用cv2.NORM_L1或cv2.NORM_L2, ORB描述符使用cv2.NORM_HAMMING
crossCheck
默認(rèn)為False, 匹配器為每個(gè)查詢描述符找到k個(gè)距離最近的匹配描述符, 為T(mén)rue時(shí), 只返回滿足交叉驗(yàn)證條件的匹配結(jié)果
暴力匹配器對(duì)象的match()方法返回每個(gè)關(guān)鍵點(diǎn)的最佳匹配結(jié)果,其基本格式如下:
ms = bf.match(des1, des2)
ms
為返回的結(jié)果, 它是一個(gè)DMatch對(duì)象列表, 每個(gè)DMatch對(duì)象表示關(guān)鍵點(diǎn)的一個(gè)匹配結(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)鍵點(diǎn)個(gè)兩點(diǎn)之間的連線為彩色
img1
為查詢圖像
keypoints1
為img1的關(guān)鍵點(diǎn)
img2
為訓(xùn)練圖像
keypoints2
為img2的關(guān)鍵點(diǎn)
matches1to2
為img1與img2的匹配結(jié)果
matchColor
為關(guān)鍵點(diǎn)和鏈接線的顏色, 默認(rèn)使用隨機(jī)顏色
singlePointColor
為單個(gè)關(guān)鍵點(diǎn)的顏色, 默認(rèn)使用隨機(jī)顏色
matchesMask
為掩膜, 用于決定繪制哪些匹配結(jié)果, 默認(rèn)為空, 表示繪制所有匹配結(jié)果
flags
為標(biāo)志, 可設(shè)置為下列參數(shù)值:
cv2.DrawMatchesFlags_DEFAUL
:默認(rèn)方式, 繪制兩個(gè)源圖像、匹配項(xiàng)和單個(gè)關(guān)鍵點(diǎn), 沒(méi)有圍繞關(guān)鍵點(diǎn)的圓以及關(guān)鍵點(diǎn)的大小和方向
cv2.DrawMatchesFlags_NOT_DRAW_SINGLE_POINTS
:不會(huì)繪制單個(gè)關(guān)鍵點(diǎn)
cv2.DrawMatchesFlags_DRAW_RICH_KEYPOINTS
:在關(guān)鍵點(diǎn)周?chē)L制具有關(guān)鍵點(diǎ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()
暴力匹配器對(duì)象的knnMatch()方法可返回指定數(shù)量的最佳匹配結(jié)果,其基本格式如下:
ms = knnMatch(des1, des2, k=n)
ms
為返回的匹配結(jié)果, 每個(gè)列表元素是一個(gè)子列表, 它包含了由參數(shù)k指定個(gè)數(shù)的DMatch對(duì)象
des1
為查詢描述符
des2
為訓(xùn)練描述符
k
為返回的最佳匹配個(gè)數(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)用比例測(cè)試選擇要使用的匹配結(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)為近似最近鄰的快速庫(kù),F(xiàn)LANN特征匹配算法比其它的最近鄰算法更快。
在創(chuàng)建FLANN匹配器時(shí),需要傳遞兩參數(shù):index_params和search_params。
index_params用來(lái)指定索引樹(shù)的算法類(lèi)型和數(shù)量。SIFT算法可以使用下面的代碼來(lái)設(shè)置。
FLANN_INDEX_KDTREE = 1 index_params = dict(algorithm = FLANN_INDEX_KDTREE, trees= 5)
ORB算法可以使用下面的代碼來(lái)設(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ù),遍歷次數(shù)越多,匹配結(jié)果越精細(xì),通常設(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特征檢測(cè)之特征匹配方式詳解的文章就介紹到這了,更多相關(guān)Python OpenCV特征匹配內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Python實(shí)戰(zhàn)小項(xiàng)目之身份證信息校驗(yàn)
讀萬(wàn)卷書(shū)不如行萬(wàn)里路,只學(xué)書(shū)上的理論是遠(yuǎn)遠(yuǎn)不夠的,只有在實(shí)戰(zhàn)中才能獲得能力的提升,本篇文章手把手帶你用Python做一個(gè)身份證信息校驗(yàn)的小項(xiàng)目,大家可以在過(guò)程中查缺補(bǔ)漏,提升水平2021-10-10Python 實(shí)現(xiàn)文件打包、上傳與校驗(yàn)的方法
今天小編就為大家分享一篇Python 實(shí)現(xiàn)文件打包、上傳與校驗(yàn)的方法,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧2019-02-02Python 多維List創(chuàng)建的問(wèn)題小結(jié)
這篇文章主要介紹了Python 多維List創(chuàng)建的問(wèn)題小結(jié),詳細(xì)的介紹了遇到的一個(gè)小問(wèn)題的解決方法,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2019-01-01TensorFlow實(shí)現(xiàn)Softmax回歸模型
這篇文章主要介紹了TensorFlow實(shí)現(xiàn)Softmax回歸模型,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2018-03-03matplotlib交互式數(shù)據(jù)光標(biāo)實(shí)現(xiàn)(mplcursors)
這篇文章主要介紹了matplotlib交互式數(shù)據(jù)光標(biāo)實(shí)現(xiàn)(mplcursors),文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2021-01-01