Python OpenCV特征檢測(cè)之特征匹配方式詳解
前言
獲得圖像的關(guān)鍵點(diǎn)后,可通過(guò)計(jì)算得到關(guān)鍵點(diǎn)的描述符。關(guān)鍵點(diǎn)描述符可用于圖像的特征匹配。通常,在計(jì)算圖A是否包含圖B的特征區(qū)域時(shí),將圖A稱做訓(xùn)練圖像,將圖B稱為查詢圖像。圖A的關(guān)鍵點(diǎn)描述符稱為訓(xùn)練描述符,圖B的關(guān)鍵點(diǎn)描述符稱為查詢描述符。
一、暴力匹配器
暴力匹配器使用描述符進(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è)量類型, 默認(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)周圍繪制具有關(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ù)的算法類型和數(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)文章
pandas篩選某列出現(xiàn)編碼錯(cuò)誤的解決方法
今天小編就為大家分享一篇pandas篩選某列出現(xiàn)編碼錯(cuò)誤的解決方法,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧2018-11-11
python 用lambda函數(shù)替換for循環(huán)的方法
今天小編就為大家分享一篇python 用lambda函數(shù)替換for循環(huán)的方法,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧2018-06-06
Python+Selenium實(shí)現(xiàn)自動(dòng)化的環(huán)境搭建的步驟(圖文)
這篇文章主要介紹了Python+Selenium實(shí)現(xiàn)自動(dòng)化的環(huán)境搭建的步驟(圖文),文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2020-09-09
Python實(shí)現(xiàn)批量下載excel表中超鏈接圖片
這篇文章主要為大家詳細(xì)介紹了如何使用Python實(shí)現(xiàn)批量下載excel表中超鏈接圖片,文中的示例代碼講解詳細(xì),感興趣的小伙伴可以參考一下2024-11-11
Python利用selenium建立代理ip池訪問(wèn)網(wǎng)站的全過(guò)程
selenium控制瀏覽器也是可以使用代理ip的,下面這篇文章主要給大家介紹了關(guān)于Python利用selenium建立代理ip池訪問(wèn)網(wǎng)站的相關(guān)資料,文中通過(guò)實(shí)例代碼介紹的非常詳細(xì),需要的朋友可以參考下2022-03-03
解決django xadmin主題不顯示和只顯示bootstrap2的問(wèn)題
這篇文章主要介紹了解決django xadmin主題不顯示和只顯示bootstrap2的問(wèn)題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧2020-03-03

