目标
在本章中,算法
import numpy as np import cv2 as cv import matplotlib.pyplot as plt img1 = cv.imread('box.png',cv.IMREAD_GRAYSCALE) # 索引图像 img2 = cv.imread('box_in_scene.png',cv.IMREAD_GRAYSCALE) # 训练图像 # 初始化ORB检测器 orb = cv.ORB_create() # 基于ORB找到关键点和检测器 kp1, des1 = orb.detectAndCompute(img1,None) kp2, des2 = orb.detectAndCompute(img2,None)
接下来,咱们建立一个距离测量值为cv.NORM_HAMMING的BFMatcher对象(由于咱们使用的是ORB),而且启用了CrossCheck以得到更好的结果。而后,咱们使用Matcher.match()方法来获取两个图像中的最佳匹配。咱们按照距离的升序对它们进行排序,以使最佳匹配(低距离)排在前面。而后咱们只抽出前10的匹配(只是为了提升可见度。您能够根据须要增长它)app
# 建立BF匹配器的对象 bf = cv.BFMatcher(cv.NORM_HAMMING, crossCheck=True) # 匹配描述符. matches = bf.match(des1,des2) # 根据距离排序 matches = sorted(matches, key = lambda x:x.distance) # 绘制前10的匹配项 img3 = cv.drawMatches(img1,kp1,img2,kp2,matches[:10],None,flags=cv.DrawMatchesFlags_NOT_DRAW_SINGLE_POINTS) plt.imshow(img3),plt.show()
将得到如下的结果:
什么是Matcher对象?
matchs = bf.match(des1,des2)行的结果是DMatch对象的列表。该DMatch对象具备如下属性:ide
import numpy as np
import cv2 as cv
import matplotlib.pyplot as plt
img1 = cv.imread('box.png',cv.IMREAD_GRAYSCALE) # 索引图像
img2 = cv.imread('box_in_scene.png',cv.IMREAD_GRAYSCALE) # 训练图像函数
sift = cv.xfeatures2d.SIFT_create()测试
kp1, des1 = sift.detectAndCompute(img1,None)
kp2, des2 = sift.detectAndCompute(img2,None)优化
bf = cv.BFMatcher()
matches = bf.knnMatch(des1,des2,k=2)3d
good = []
for m,n in matches:
if m.distance < 0.75*n.distance:
good.append([m])code
img3 = cv.drawMatchesKnn(img1,kp1,img2,kp2,good,None,flags=cv.DrawMatchesFlags_NOT_DRAW_SINGLE_POINTS)
plt.imshow(img3),plt.show()orm
查看如下结果:  **基于匹配器的FLANN** FLANN是近似最近邻的快速库。它包含一组算法,这些算法针对大型数据集中的快速最近邻搜索和高维特征进行了优化。对于大型数据集,它的运行速度比BFMatcher快。咱们将看到第二个基于FLANN的匹配器示例。 对于基于FLANN的匹配器,咱们须要传递两个字典,这些字典指定要使用的算法,其相关参数等。第一个是IndexParams。对于各类算法,要传递的信息在FLANN文档中进行了说明。归纳来讲,对于SIFT,SURF等算法,您能够经过如下操做:
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
第二个字典是SearchParams。它指定索引中的树应递归遍历的次数。较高的值可提供更好的精度,但也须要更多时间。若是要更改值,请传递search_params = dict(checks = 100) 有了这些信息,咱们就很容易了。
import numpy as np
import cv2 as cv
import matplotlib.pyplot as plt
img1 = cv.imread('box.png',cv.IMREAD_GRAYSCALE) # 索引图像
img2 = cv.imread('box_in_scene.png',cv.IMREAD_GRAYSCALE) # 训练图像
sift = cv.xfeatures2d.SIFT_create()
kp1, des1 = sift.detectAndCompute(img1,None)
kp2, des2 = sift.detectAndCompute(img2,None)
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))]
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()
查看如下结果: 