【上海校区】 python opencv入门 特征匹配(38)

python 未结 0 221
武汉网站优化
武汉网站优化 2021-07-05 15:24
悬赏:8
内容来自OpenCV-Python Tutorials 自己翻译整理

目标:
学习匹配一副图片和其他图片的特征。
学习使用OpenCV中的Brute-Force匹配和FLANN匹配。

暴力匹配(Brute-Force)基础

暴力匹配很简单。首先在模板特征点描述符的集合当中找到第一个特征点,然后匹配目标图片的特征点描述符集合当中的所有特征点,匹配方式使用“距离”来衡量,返回“距离”最近的那个。

对于Brute-Force匹配,首先我们要使用cv2.BFMatcher()方法来创建一个BF匹配器的对象。

该方法包含两个可选参数

normType
crossCheck
normType指定了要使用的“距离”测量方法。缺省条件下,的参数是cv2.NORM_L2。

在使用SIFT方法和SURF方法等等进行匹配时,这种“距离”测量方法效果很好(cv2.NORM_L1也一样)。

在使用基于二进制字符串的描述符,像ORB,BRIEF,BRISK等等方法时,应该使用cv2.NORM_HAMMING,这种方法使用汉明距离来测量。如果ORB算法的参数设置为WAT_K==3或者4,那么应该使用cv2.NORM_HAMMING2。

crossCheck参数是boolean类型,缺省的情况下是false。如果crossCheck是true,那么匹配器返回只返回一个最佳的匹配(i,j),其中i在特征点描述符集合A当中,j在特征点描述符集合B当中,反之亦然。也就是两个集合当中的特征点都彼此配对。这种方法返回了一致的结果,并且可以很好的用来替代SIFT算法论文当中测试。

暴力匹配器有两个重要的方法,分别是BFMatcher.match() 和BFMatcher.knnMatch()。第一个返回最佳匹配,第二个返回前k个最佳的匹配,k值由用户指定。当我们需要做一些额外的工作时,这种方法会很有用。

就像在图像上绘制关键点的函数cv2.drawKeypoints()一样, cv2.drawMatches()函数可以绘制匹配结果。该方法将两张图片水平排列,然后从第一张图片到第二张图片绘制直线来现实最佳的匹配结果。cv2.drawMatchesKnn函数会画出所有k个最佳匹配。如果k=2,那么将会画出每个关键点之间的匹配直线。所以,如果我们想有选择的画出,那么要传递进一个蒙版。

下面的例子使用了SURF和ORB算法(分别使用了不同的“距离”测量方法)

ORB的暴力匹配:

下面的例子实现了匹配两个图片的特征点,本例子当中要去查询图片和训练图片。我们要在训练图片当中使用特征匹配来找到查询图片。

使用ORB描述符来匹配特征(文档里写成SIFT算法了)。

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

img1 = cv2.imread("1.jpg",0)
img2 = cv2.imread("26.jpg",0)

orb = cv2.ORB_create()

kp1, des1 = orb.detectAndCompute(img1,None)
kp2, des2 = orb.detectAndCompute(img2,None)

bf = cv2.BFMatcher(cv2.NORM_HAMMING, crossCheck=True)

matches = bf.match(des1,des2)

matches = sorted(matches, key = lambda x:x.distance)

img3=np.empty((300,300))

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

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

原图

原来凤姐最美的是眼睛,不是嘴啊-_-|||

drawMatches函数的参数如下
outImg = cv.drawMatches( img1, keypoints1, img2, keypoints2, matches1to2, outImg[, matchColor[, singlePointColor[, matchesMask[, flags]]]] )

  • img1 第一张图片
  • keypoints1第一张图片的关键点
  • img2第二张图片
  • keypoints2第二章图片的关键点
  • matches1to2 选择第一张图到第二张图的多少个匹配点
  • outImg 输出图片
  • matchColor 匹配点颜色
  • singlePointColor 画出没匹配上的点
  • matchesMask 给出一个蒙版,表示那部分的匹配点不用画出来
  • flags DEFAULT = 0, DRAW_OVER_OUTIMG = 1, NOT_DRAW_SINGLE_POINTS = 2, DRAW_RICH_KEYPOINTS = 4

什么事匹配器对象?

matches = bf.match(des1,des2)结果返回一个列表,DMatch 有如下性质

  • DMatch.distance 描述符的“距离”,越小越好
  • DMatch.trainIdx 目标描述符的下标
  • DMatch.queryIdx 查询图像描述符的下标
  • DMatch.imgIdx 目标图像的下标

SIFT暴力匹配和比率测试

这次试用BFMatcher.knnMatch()来找到k个最佳匹配。在这个例子当中,我们选择k=2,这样可以使用Lowe论文中的比率测试了。

import numpy as np

import cv2

from matplotlib import pyplot as plt


img1 = cv2.imread("1.jpg",0)

img2 = cv2.imread("26.jpg",0)


sift = cv2.xfeatures2d.SIFT_create()


kp1, des1 = sift.detectAndCompute(img1,None)

kp2, des2 = sift.detectAndCompute(img2,None)


bf = cv2.BFMatcher()


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


good = []

for m,n in matches:

    if m.distance < 0.75*n.distance:

        good.append([m])


img3=np.empty((300,300))


img3 = cv2.drawMatchesKnn(img1,kp1,img2,kp2,good, img3,flags=2)


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

不咋准…-_-

基于FLANN的匹配器

FLANN的意思是快速最近邻搜索库。它包含一个对大数据集合和高维特征实现最近邻搜索的算法集合,而且这些算法是优化固偶读。面对大数据集时,效果要比暴力搜索好。

FLANN要传递两个字典作为参数。
第一个参数是使用的搜索算法,详细内容见此处
第二个参数是搜索次数,次数越多,结果越精确,但是速度也越慢。

mport numpy as np

import cv2

from matplotlib import pyplot as plt


img1 = cv2.imread("1.jpg",0)

img2 = cv2.imread("26.jpg",0)


sift = cv2.xfeatures2d.SIFT_create()


kp1, des1 = sift.detectAndCompute(img1,None)

kp2, des2 = sift.detectAndCompute(img2,None)


FLANN_INDEX_KDTREE = 0#kd树

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 range(len(matches))]


# ratio test as per Lowe"s paper

for i,(m,n) in enumerate(matches):

    if m.distance < 0.7*n.distance:

        matchesMask=[1,0]


draw_params = dict(matchColor = (0,255,0),

                   singlePointColor = (255,0,0),

                   matchesMask = matchesMask,

                   flags = 0)


img3=np.empty((300,300))


img3 = cv2.drawMatchesKnn(img1,kp1,img2,kp2,matches, img3,flags=2)


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

效果没有ORB算法实现的好呀


相关标签:
回答
  • 消灭零回复
提交回复