OpenCV-Python教程:41.特征匹配

Brute-Force匹配器基礎(chǔ)

Brute-Force匹配器很簡單歌憨,它取第一個(gè)集合里一個(gè)特征的描述子并用第二個(gè)集合里所有其他的特征和他通過一些距離計(jì)算進(jìn)行匹配。最近的返回。

對于BF匹配器惠险,首先我們得用cv2.BFMatcher()創(chuàng)建BF匹配器對象.它取兩個(gè)可選參數(shù)呜达,第一個(gè)是normType唆貌。它指定要使用的距離量度滑潘。默認(rèn)是cv2.NORM_L2。對于SIFT,SURF很好锨咙。(還有cv2.NORM_L1)众羡。對于二進(jìn)制字符串的描述子,比如ORB蓖租,BRIEF粱侣,BRISK等,應(yīng)該用cv2.NORM_HAMMING蓖宦。使用Hamming距離度量齐婴,如果ORB使用VTA_K == 3或者4,應(yīng)該用cv2.NORM_HAMMING2

第二個(gè)參數(shù)是布爾變量稠茂,crossCheck模式是false柠偶,如果它是true,匹配器返回那些和(i, j)匹配的睬关,這樣集合A里的第i個(gè)描述子和集合B里的第j個(gè)描述子最匹配诱担。兩個(gè)集合里的兩個(gè)特征應(yīng)該互相匹配,它提供了連續(xù)的結(jié)果电爹,

當(dāng)它創(chuàng)建以后蔫仙,兩個(gè)重要的方法是BFMatcher.match()和BFMatcher.knnMatch()。第一個(gè)返回最匹配的丐箩,第二個(gè)方法返回k個(gè)最匹配的摇邦,k由用戶指定。當(dāng)我們需要多個(gè)的時(shí)候很有用屎勘。

想我們用cv2.drawKeypoints()來畫關(guān)鍵點(diǎn)一樣施籍,cv2.drawMatches()幫我們畫匹配的結(jié)果,它把兩個(gè)圖像水平堆疊并且從第一個(gè)圖像畫線到第二個(gè)圖像來顯示匹配概漱。還有一個(gè)cv2.drawMatchesKnn來畫k個(gè)最匹配的丑慎。如果k=2,它會給每個(gè)關(guān)鍵點(diǎn)畫兩根匹配線瓤摧。所以我們得傳一個(gè)掩圖竿裂,如果我們想選擇性的畫的話。

讓我們各看一個(gè)SURF和ORB的例子(都使用了不同的距離度量)

使用ORB描述子的Brute-Force匹配

這里我們會看到如何匹配兩個(gè)圖片的里的特征姻灶。在這個(gè)例子里铛绰,我有一個(gè)查詢圖像和一個(gè)訓(xùn)練圖像诈茧,我們用特征匹配來在訓(xùn)練圖像里找查詢圖像产喉。

我們使用SIFT描述子來匹配特征,所以讓我們先加載圖像,找到描述子曾沈。

import numpy as np
import cv2
from matplotlib import pyplot as plt

img1 = cv2.imread('box.png',0)? ? ? ? ? # queryImage
img2 = cv2.imread('box_in_scene.png',0) # trainImage

# Initiate SIFT detector
orb = cv2.ORB()

# find the keypoints and descriptors with SIFT
kp1, des1 = orb.detectAndCompute(img1,None)
kp2, des2 = orb.detectAndCompute(img2,None)

接著我們用距離度量cv2.NORM_HAMMING創(chuàng)建一個(gè)BFMatcher對象这嚣,crossCheck設(shè)為真。然后我們用Matcher.match()方法來獲得兩個(gè)圖像里最匹配的塞俱。我們按他們距離升序排列姐帚,這樣最匹配的(距離最小)在最前面障涯。然后我們畫出最開始的10個(gè)匹配(為了好看罐旗,你可以增加)

# create BFMatcher object
bf = cv2.BFMatcher(cv2.NORM_HAMMING, crossCheck=True)

# Match descriptors.
matches = bf.match(des1,des2)

# Sort them in the order of their distance.
matches = sorted(matches, key = lambda x:x.distance)

# Draw first 10 matches.
img3 = cv2.drawMatches(img1,kp1,img2,kp2,matches[:10], flags=2)

plt.imshow(img3),plt.show()

下面是結(jié)果:

什么是匹配器對象?

matches = bf.match(des1, des2)的結(jié)果是DMatch對象列表唯蝶。這個(gè)DMatch對象有下面的屬性:

·DMatch.distance - 描述子之間的距離九秀。越低越好

·DMatch.trainIdx - 訓(xùn)練描述子里的描述子索引

·DMatch.queryIdx - 查詢描述子里的描述子索引

·DMatch.imgIdx - 訓(xùn)練圖像的索引

用SIFT描述子和比率測試的Brute-Force 匹配

這次,我們使用BFMatcher.knnMatch()來獲得k個(gè)最匹配的粘我。在這個(gè)例子里鼓蜒,我們設(shè)置k=2這樣我們可以應(yīng)用比率檢測。

import numpy as np
import cv2
from matplotlib import pyplot as plt

img1 = cv2.imread('box.png',0)? ? ? ? ? # queryImage
img2 = cv2.imread('box_in_scene.png',0) # trainImage

# Initiate SIFT detector
sift = cv2.SIFT()

# find the keypoints and descriptors with SIFT
kp1, des1 = sift.detectAndCompute(img1,None)
kp2, des2 = sift.detectAndCompute(img2,None)

# BFMatcher with default params
bf = cv2.BFMatcher()
matches = bf.knnMatch(des1,des2, k=2)

# Apply ratio test
good = []
for m,n in matches:
? ? if m.distance < 0.75*n.distance:
? ? ? ? good.append([m])

# cv2.drawMatchesKnn expects list of lists as matches.
img3 = cv2.drawMatchesKnn(img1,kp1,img2,kp2,good,flags=2)

plt.imshow(img3),plt.show()

看下面的結(jié)果

基于FLANN的匹配器

FLANN是快速估計(jì)最近鄰的庫征字。它包含了一些為大數(shù)據(jù)集內(nèi)搜索快速近鄰和高維特征的優(yōu)化算法都弹。它在大數(shù)據(jù)集的時(shí)候比BFMatcher更快。

對于基于FLANN的匹配器匙姜,我們需要傳兩個(gè)字典指定要用的算法畅厢,他們相關(guān)的參數(shù)等。第一個(gè)是IndexParams氮昧。對于更多算法或详,要傳的信息參看FLANN的文檔。作為總結(jié)郭计,對于像SIFT霸琴,SURF等的算法,你可以傳下面的:

index_params=dict(algorithm=FLANN_INDEX_KDTREE,trees=5)

當(dāng)使用ORB昭伸,你可以傳下面的梧乘。注釋里的值是推薦的值。但是在有些情況下不提供需要的結(jié)果庐杨。其他的值工作正常选调。

index_params = dict(algorithm=FLANN_INDEX_LSH,
? ? table_number = 6, ?# 12
? ? key_size = 12, ? ?# 20
? ? multi_probe_level = 1) ?#2

第二個(gè)字典是SearchParams,它指定了索引里的樹應(yīng)該被遞歸遍歷的次數(shù)灵份。更高的值帶來更高的準(zhǔn)確率仁堪。但是也花更多時(shí)間,如果你想改變值填渠,search_params = dict(checks=100).

通過這些信息弦聂,我們可以開始了:

import numpy as np
import cv2
from matplotlib import pyplot as plt

img1 = cv2.imread('box.png',0)? ? ? ? ? # queryImage
img2 = cv2.imread('box_in_scene.png',0) # trainImage

# Initiate SIFT detector
sift = cv2.SIFT()

# find the keypoints and descriptors with SIFT
kp1, des1 = sift.detectAndCompute(img1,None)
kp2, des2 = sift.detectAndCompute(img2,None)

# FLANN parameters
FLANN_INDEX_KDTREE = 0
index_params = dict(algorithm = FLANN_INDEX_KDTREE, trees = 5)
search_params = dict(checks=50)? # or pass empty dictionary

flann = cv2.FlannBasedMatcher(index_params,search_params)

matches = flann.knnMatch(des1,des2,k=2)

# Need to draw only good matches, so create a mask
matchesMask = [[0,0] for i in xrange(len(matches))]

# ratio test as per Lowe's paper
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 = 0)

img3 = cv2.drawMatchesKnn(img1,kp1,img2,kp2,matches,None,**draw_params)

plt.imshow(img3,),plt.show()

結(jié)果:

END

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末鸟辅,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子莺葫,更是在濱河造成了極大的恐慌匪凉,老刑警劉巖,帶你破解...
    沈念sama閱讀 211,376評論 6 491
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件捺檬,死亡現(xiàn)場離奇詭異再层,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)堡纬,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,126評論 2 385
  • 文/潘曉璐 我一進(jìn)店門聂受,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人烤镐,你說我怎么就攤上這事饺饭。” “怎么了职车?”我有些...
    開封第一講書人閱讀 156,966評論 0 347
  • 文/不壞的土叔 我叫張陵瘫俊,是天一觀的道長。 經(jīng)常有香客問我悴灵,道長扛芽,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 56,432評論 1 283
  • 正文 為了忘掉前任积瞒,我火速辦了婚禮川尖,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘茫孔。我一直安慰自己叮喳,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,519評論 6 385
  • 文/花漫 我一把揭開白布缰贝。 她就那樣靜靜地躺著馍悟,像睡著了一般。 火紅的嫁衣襯著肌膚如雪剩晴。 梳的紋絲不亂的頭發(fā)上锣咒,一...
    開封第一講書人閱讀 49,792評論 1 290
  • 那天,我揣著相機(jī)與錄音赞弥,去河邊找鬼毅整。 笑死,一個(gè)胖子當(dāng)著我的面吹牛绽左,可吹牛的內(nèi)容都是我干的悼嫉。 我是一名探鬼主播,決...
    沈念sama閱讀 38,933評論 3 406
  • 文/蒼蘭香墨 我猛地睜開眼拼窥,長吁一口氣:“原來是場噩夢啊……” “哼戏蔑!你這毒婦竟也來了蹋凝?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 37,701評論 0 266
  • 序言:老撾萬榮一對情侶失蹤辛臊,失蹤者是張志新(化名)和其女友劉穎仙粱,沒想到半個(gè)月后房交,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體彻舰,經(jīng)...
    沈念sama閱讀 44,143評論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,488評論 2 327
  • 正文 我和宋清朗相戀三年候味,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了刃唤。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 38,626評論 1 340
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡白群,死狀恐怖尚胞,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情帜慢,我是刑警寧澤笼裳,帶...
    沈念sama閱讀 34,292評論 4 329
  • 正文 年R本政府宣布,位于F島的核電站粱玲,受9級特大地震影響躬柬,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜抽减,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,896評論 3 313
  • 文/蒙蒙 一允青、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧卵沉,春花似錦颠锉、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,742評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至停撞,卻和暖如春眉枕,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背怜森。 一陣腳步聲響...
    開封第一講書人閱讀 31,977評論 1 265
  • 我被黑心中介騙來泰國打工速挑, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 46,324評論 2 360
  • 正文 我出身青樓葫男,卻偏偏與公主長得像掏婶,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個(gè)殘疾皇子腊满,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,494評論 2 348

推薦閱讀更多精彩內(nèi)容