首页 > 编程语言 >OpenCV-Python 特征匹配

OpenCV-Python 特征匹配

时间:2024-11-25 09:31:06浏览次数:8  
标签:匹配 BFMatcher Python matches cv2 OpenCV SIFT 图像

37.1 Brute-Force 匹配的基础
  蛮力匹配器是很简单的。首先在第一幅图像中选取一个关键点然后依次与第二幅图像的每个关键点进行(描述符)距离测试,最后返回距离最近的关键点。
对于 BF 匹配器,我们首先要使用 cv2.BFMatcher() 创建一个 BFMatcher 对象。它有两个可选参数。第一个是 normType。它是用来指定要使用的距离测试类型。默认值为 cv2.Norm_L2。这很适合 SIFT 和 SURF 等(c2.NORM_L1 也可以)。对于使用二进制描述符的 ORB,BRIEF,BRISK算法等,要使用 cv2.NORM_HAMMING,这样就会返回两个测试对象之间的汉明距离。如果 ORB 算法的参数设置为 V TA_K==3 或 4,normType就应该设置成 cv2.NORM_HAMMING2。
第二个参数是布尔变量 crossCheck,默认值为 False。如果设置为True,匹配条件就会更加严格,只有到 A 中的第 i 个特征点与 B 中的第 j 个特征点距离最近,并且 B 中的第 j 个特征点到 A 中的第 i 个特征点也是最近(A 中没有其他点到 j 的距离更近)时才会返回最佳匹配(i,j)。也就是这两个特征点要互相匹配才行。这样就能提供统一的结果,这可以用来替代 D.Lowe在 SIFT 文章中提出的比值测试方法。
BFMatcher 对象具有两个方法,BFMatcher.match() 和 BFMatcher.knnMatch()。
第一个方法会返回最佳匹配。第二个方法为每个关键点返回 k 个最佳匹配(降序排列之后取前 k 个),其中 k 是由用户设定的。如果除了匹配之外还要做其他事情的话可能会用上(比如进行比值测试)。
就像使用 cv2.drawKeypoints() 绘制关键点一样,我们可以使用cv2.drawMatches() 来绘制匹配的点。它会将这两幅图像先水平排列,然后在最佳匹配的点之间绘制直线(从原图像到目标图像)。如果前面使用的是 BFMatcher.knnMatch(),现在我们可以使用函数 cv2.drawMatchsKnn为每个关键点和它的 k 个最佳匹配点绘制匹配线。如果 k 等于 2,就会为每个关键点绘制两条最佳匹配直线。如果我们要选择性绘制话就要给函数传入一个掩模。
让我们分别看一个 ORB 和一个 SURF 的例子吧。(使用不同距离计算方法)。

37.2 对 对 ORB 描述符进行蛮力匹配
  现在我们看一个在两幅图像之间进行特征匹配的简单例子。在本例中我们有一个查询图像和一个目标图像。我们要使用特征匹配的方法在目标图像中寻找查询图像的位置。(这两幅图像分别是/sample/c/box.png,和/sample/c/box_in_scene.png)
我们使用 ORB 描述符来进行特征匹配。首先我们需要加载图像计算描述符。

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)

下面我们要创建一个 BFMatcher 对象,并将距离计算设置为 cv2.NORM_HAMMING(因为我们使用的是 ORB),并将 crossCheck 设置为 True。然后使用 Matcher.match()方法获得两幅图像的最佳匹配。然后将匹配结果按特征点之间的距离进行降序排列,这样最佳匹配就会排在前面了。最后我们只将前 10 个匹配绘制出来(太多了看不清,如果愿意的话你可以多画几条)。

# 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()

37.3 匹配器对象是什么?
 matches = bf.match(des1,des2) 返回值是一个 DMatch 对象列表。这个DMatch 对象具有下列属性:
  • DMatch.distance - 描述符之间的距离。越小越好。
  • DMatch.trainIdx - 目标图像中描述符的索引。
  • DMatch.queryIdx - 查询图像中描述符的索引。
  • DMatch.imgIdx - 目标图像的索引。

37.4 对 对 SIFT 描述符进行蛮力匹配和比值测试
  现在我们使用 BFMatcher.knnMatch() 来获得 k 对最佳匹配。在本例中我们设置 k = 2,这样我们就可以使用 D.Lowe 文章中的比值测试了。

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()

37.5 FLANN 匹配器
  FLANN 是快速最近邻搜索包(Fast_Library_for_Approximate_Nearest_Neighbors)的简称。它是一个对大数据集和高维特征进行最近邻搜索的算法的集合,而且这些算法都已经被优化过了。在面对大数据集时它的效果要好于 BFMatcher。
我们来对第二个例子使用 FLANN 匹配看看它的效果。

使用 FLANN 匹配,我们需要传入两个字典作为参数。这两个用来确定要使用的算法和其他相关参数等。第一个是 IndexParams。各种不同算法的信息可以在 FLANN 文档中找到。这里我们总结一下,对于 SIFT 和 SURF 等,我们可以传入的参数是:

index_params = dict(algorithm = FLANN_INDEX_KDTREE, trees = 5)
但使用 ORB 时,我们要传入的参数如下。注释掉的值是文献中推荐使用的,但是它们并不适合所有情况,其他值的效果可能会更好。

index_params= dict(algorithm = FLANN_INDEX_LSH,
table_number = 6, # 12
key_size = 12, # 20
multi_probe_level = 1) #2
第二个字典是 SearchParams。用它来指定递归遍历的次数。值越高结果越准确,但是消耗的时间也越多。如果你想修改这个值,传入参数:
search p arams = 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()

标签:匹配,BFMatcher,Python,matches,cv2,OpenCV,SIFT,图像
From: https://blog.csdn.net/m0_37302966/article/details/144019055

相关文章

  • 探索Python自动化的奥秘:pexpect库的神奇之旅
    文章目录**探索Python自动化的奥秘:pexpect库的神奇之旅**一、背景:为何选择pexpect?二、pexpect是什么?三、如何安装pexpect?四、pexpect的五个简单函数五、pexpect在实际场景中的应用六、常见bug及解决方案七、总结探索Python自动化的奥秘:pexpect库的神奇之旅一、背......
  • 探索Python应用分发的新利器:Shiv
    文章目录**探索Python应用分发的新利器:Shiv**1.背景:为什么选择Shiv?2.Shiv是什么?3.如何安装Shiv?4.Shiv的简单使用方法5.场景应用6.常见Bug及解决方案7.总结探索Python应用分发的新利器:Shiv1.背景:为什么选择Shiv?在Python开发中,应用的分发和部署常常因为环......
  • python - 验证身份证合法性
    可以使用id_validator库1.验证身份证号合法性验证身份证号是否合法,合法返回True,不合法返回Falsefromid_validatorimportvalidatorvalidator.is_valid('440308199901101512')#大陆居民身份证18位validator.is_valid('610104620927690')#大陆居民身份证15位......
  • Python 基于 opencv 的疲劳检测系统的研究与设计
    博主介绍:✌程序员徐师兄、7年大厂程序员经历。全网粉丝12w+、csdn博客专家、掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java技术领域和毕业项目实战✌......
  • python+Django+MySQL+echarts+bootstrap制作的教学质量评价系统,包括学生、老师、管理
    项目介绍该教学质量评价系统基于Python、Django、MySQL、ECharts和Bootstrap技术,旨在为学校或教育机构提供一个全面的教学质量评估平台。系统主要包括三种角色:学生、老师和管理员,每个角色有不同的功能权限。学生角色:学生可以通过该平台对所选课程进行评价,评价内容包括老师的......
  • Python字典默认值处理的优雅艺术
    在Python编程中,字典是最常用的数据结构之一,它就像我们生活中的图书目录,通过索引可以快速找到对应的内容。但在实际开发中,经常会遇到一个问题:当我们要查找的键不存在时,该如何优雅地处理?传统的处理方式许多程序员,特别是初学者,习惯用if-else来处理这种情况:user_scores={'Ali......
  • Python编程技巧:多变量赋值的优雅艺术
    在Python编程的世界里,有许多令人惊叹的语法特性,而多变量赋值就像是一颗闪耀的明珠,它不仅让代码更优雅,还能提升程序的执行效率。今天我们就深入探讨这个看似简单却蕴含深意的编程技巧。基础认识传统的变量赋值方式,我们都很熟悉:x=1y=2z=3但Python提供了一种更简洁......
  • Python变量交换的艺术:从基础到进阶的优雅之道
    在Python编程世界里,变量交换是一个非常基础但又充满智慧的话题。让我们深入探讨这个看似简单却蕴含丰富内涵的编程技巧。基础交换方式传统编程语言中,交换两个变量的值通常需要使用临时变量:x=10y=20temp=xx=yy=tempprint(x,y)#输出:2010这种方式虽然直......
  • python本地保存浏览器文件夹
    BIGSMATER/local-bookmark其实就是找到本地文件,json解析然后dfs,文件名上有点坑,暴力替换即可importjsonimportosfromseleniumimportwebdriver#refs:#https://blog.csdn.net/Demonslzh/article/details/125062240#https://www.cnblogs.com/superhin/p/12600358.html......
  • Python学习笔记(4)Python多线程
    线程可以分为:内核线程:由操作系统内核创建和撤销。用户线程:不需要内核支持而在用户程序中实现的线程。Python3线程中常用的两个模块为:_threadthreading(推荐使用)_thread提供了低级别的、原始的线程以及一个简单的锁,它相比于threading模块的功能还是比较有限的......