python opencv入门 特征匹配(38)

本文介绍了如何使用OpenCV进行图像特征匹配,包括Brute-Force匹配和FLANN匹配两种方法。通过SURF、ORB等算法提取特征点,并展示了如何利用匹配结果进行图像识别。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

内容来自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]]]] )

  1. img1 第一张图片
  2. keypoints1第一张图片的关键点
  3. img2第二张图片
  4. keypoints2第二章图片的关键点
  5. matches1to2 选择第一张图到第二张图的多少个匹配点
  6. outImg 输出图片
  7. matchColor 匹配点颜色
  8. singlePointColor 画出没匹配上的点
  9. matchesMask 给出一个蒙版,表示那部分的匹配点不用画出来
  10. 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要传递两个字典作为参数。
第一个参数是使用的搜索算法,详细内容见此处
第二个参数是搜索次数,次数越多,结果越精确,但是速度也越慢。

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)

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[i]=[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算法实现的好呀

评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值