目标

本章节中

  • 我们将实现如何不同图像之间匹配特征.
  • 将使用两种匹配器,openCV提供了Brute-Force 和 FLANN

Brute-Force 匹配器的基本原理

Brute-Force匹配器很简单。它采用第一个集合中一个特征的描述符,并通过距离计算与第二个集合中的所有其他特征匹配,返回最近的一个。对于BF匹配器,首先必须使用cv.BFMatcher()创建BFMatcher对象。它需要两个可选参数。第一个是normType。它指定要使用的距离度量。默认情况下,它是cv.NORM_L2。适用于SIFT、SURF等。cv.NORM_L1也在那里)。对于基于二进制字符串的描述符,如ORB、BRIEF、lively等,使用cv.NORM_HAMMING,它使用Hamming distance作为度量。如果ORB使用WTA_K == 3或4,则使用cv.NORM_HAMMING2。

第二个参数是布尔变量crossCheck,默认为false。如果为真,Matcher只返回值为(i,j)的匹配项,以便集合A中的第i个描述符与集合B中的第j个描述符具有最佳匹配,反之亦然。也就是说,两个集合中的两个特性应该相互匹配。它可以得到可靠的结果,是D.Lowe的论文中提出的一个比值检验很好的替代法。创建之后,两个重要的方法是BFMatcher.match()和BFMatcher.knnMatch()。第一个返回最佳匹配。第二个方法返回由用户指定的k的最佳匹配。当我们需要在这方面做额外的工作时,它可能是有用的。

就像我们使用了cv.drawKeypoints()来绘制关键点一样,cv.drawMatches()帮助我们绘制匹配项。它水平地堆叠两个图像,并从第一个图像到第二个图像绘制线,以显示最佳匹配。还有cv.drawMatchesKnn可以画出所有k个最佳匹配项。如果k=2,它将为每个关键点绘制两条匹配线。所以我们必须传递一个蒙版如果我们想有选择地画它。让我们来分别看看用SURF和ORB的示例 (它们都使用不同的距离测量)。

BF 匹配 ORB 描述子

在这里,我们将看到一个关于如何在两个图像之间匹配特性的简单示例。在本例中,我有一个queryImage和一个trainImage。我们将尝试使用特征匹配在trainImage中找到queryImage。

( 实例图像 /samples/c/box.png and /samples/c/box_in_scene.png)

我们使用ORB描述符来匹配特性。让我们从加载图像开始,寻找描述符等等。

import numpy as npimport cv2 as cvimport matplotlib.pyplot as pltimg1 = cv.imread('box.png',0) # queryImageimg2 = cv.imread('box_in_scene.png',0) # trainImage# Initiate ORB detectororb = cv.ORB_create()# find the keypoints and descriptors with ORBkp1, des1 = orb.detectAndCompute(img1,None)kp2, des2 = orb.detectAndCompute(img2,None)

接下来,我们创建一个带有距离测量的BFMatcher对象。cv.NORM_HAMMING(因为我们使用ORB)和crossCheck被打开以获得更好的结果。然后我们使用Matcher.match()方法在两个图像中获得最佳匹配。我们按照它们之间距离的升序对它们进行排序,以便最好的匹配(低距离)出现在前面。然后我们只绘制前10个匹配项(只是为了便于查看)。你可以随意增加)

# create BFMatcher objectbf = cv.BFMatcher(cv.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 = cv.drawMatches(img1,kp1,img2,kp2,matches[:10], flags=2)plt.imshow(img3),plt.show()

以下就是我们得到的结果:

什么是匹配器对象?

代码行中 matches = bf.match(des1,des2) 返回的结果是 DMatch 对象的列表. 这个DMatch 对象有以下属性:

  • DMatch.distance - 描述子之间的距离. 越小越好.
  • DMatch.trainIdx - 训练集中的描述子的索引
  • DMatch.queryIdx - 检索集中的描述子的索引
  • DMatch.imgIdx - 训练集图像的索引.

BF 匹配 SIFT 描述子和比值检测

这次,我们将使用BFMatcher.knnMatch()获得k个最佳匹配。在这个例子中,我们取k=2,这样我们就可以应用D.Lowe在论文中解释的比值检验。

import numpy as npimport cv2 as cvfrom matplotlib import pyplot as pltimg1 = cv.imread('box.png',0) # queryImageimg2 = cv.imread('box_in_scene.png',0) # trainImage# Initiate SIFT detectorsift = cv.SIFT()# find the keypoints and descriptors with SIFTkp1, des1 = sift.detectAndCompute(img1,None)kp2, des2 = sift.detectAndCompute(img2,None)# BFMatcher with default paramsbf = cv.BFMatcher()matches = bf.knnMatch(des1,des2, k=2)# Apply ratio testgood = []for m,n in matches: if m.distance < 0.75*n.distance: good.append([m])# cv.drawMatchesKnn expects list of lists as matches.img3 = cv.drawMatchesKnn(img1,kp1,img2,kp2,good,flags=2)plt.imshow(img3),plt.show()

以下得到结果:

基于FLANN 匹配器

FLANN是Fast Library for Approximate Nearest Neighbors的缩写。它包含一组优化算法,用于在大型数据集中快速搜索最近邻和高维特性。对于大型数据集,它比BFMatcher工作得更快。我们将看到基于FLANN的匹配器的第二个例子。

对于基于FLANN的匹配器,我们需要通过两个字典来指定要使用的算法及其相关参数等。第一个是IndexParams。对于各种算法,要传递的信息在FLANN文档中进行了解释。作为总结,对于SIFT、SURF等算法,您可以通过以下步骤:

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

在使用ORB时,您可以传递以下内容。注释值是根据文档推荐的,但在某些情况下它没有提供所需的结果。其他的值可能会更好:

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

第二个字典是SearchParams。它指定应该递归遍历索引中的树的次数。数值越大,精度越高,但也需要更多的时间。如果要更改值,请传递search_params = dict(check =100)。有了这些信息,我们可以开始了。

import numpy as npimport cv2 as cvfrom matplotlib import pyplot as pltimg1 = cv.imread('box.png',0) # queryImageimg2 = cv.imread('box_in_scene.png',0) # trainImage# Initiate SIFT detectorsift = cv.SIFT()# find the keypoints and descriptors with SIFTkp1, des1 = sift.detectAndCompute(img1,None)kp2, des2 = sift.detectAndCompute(img2,None)# FLANN parametersFLANN_INDEX_KDTREE = 1index_params = dict(algorithm = FLANN_INDEX_KDTREE, trees = 5)search_params = dict(checks=50) # or pass empty dictionaryflann = cv.FlannBasedMatcher(index_params,search_params)matches = flann.knnMatch(des1,des2,k=2)# Need to draw only good matches, so create a maskmatchesMask = [[0,0] for i in xrange(len(matches))]# ratio test as per Lowe's paperfor 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 = cv.drawMatchesKnn(img1,kp1,img2,kp2,matches,None,**draw_params)plt.imshow(img3,),plt.show()

请看结果如下:

opencv4 图像特征匹配_openCV - 图像特征匹配相关推荐

  1. python图像特征提取与匹配_图像特征特点及其常用的特征提取与匹配方法

    常用的图像特征有颜色特征.纹理特征.形状特征.空间关系特征. 一颜色特征 (一)特点:颜色特征是一种全局特征,描述了图像或图像区域所对应的景物的表面性质.一般颜色特征是基于像素点的特征,此时所有属于图 ...

  2. OpenCV—python 模板匹配与图像特征匹配

    文章目录 一.理论介绍与算法 二.算法代码 单目标匹配 多目标匹配 三 多尺度模板匹配 一.理论介绍与算法 模板匹配是在一幅图像中寻找一个特定目标的方法之一,这种方法的原理非常简单,遍历图像中的每一个 ...

  3. getvalue参数计数不匹配_OpenCV开发笔记(六十八):红胖子8分钟带你使用特征点Flann最邻近差值匹配识别...

    若该文为原创文章,未经允许不得转载 原博主博客地址:https://blog.csdn.net/qq21497936 原博主博客导航:https://blog.csdn.net/qq21497936/ ...

  4. Java OpenCV-4.0.0 图像处理22 图像模板匹配

    Java OpenCV-4.0.0 图像处理22 图像模板匹配 参考链接:https://blog.csdn.net/qq_34814092/article/details/95813654 Java ...

  5. Nature科学报告:根据大脑思维意图来生成对应匹配的图像

    点击上面"脑机接口社区"关注我们 更多技术干货第一时间送达 导读 脑机接口可以进行主动通信并执行一组预定义的命令,例如键入字母或移动光标.但是,到目前为止,他们还无法根据大脑信号推 ...

  6. opencv上gpu版surf特征点与orb特征点提取及匹配实例

    opencv上gpu版surf特征点与orb特征点提取及匹配实例 标签: gpu版surfgpu orbsurf和orbgpu surf及orbsurf orb gpu 2016-09-25 23:4 ...

  7. 图像相似度测量与模板匹配总结

    摘要 本文主要总结了进行目标跟踪.检测中经常使用到的图像相似度测量和模板匹配方法,并给出了具体的基于OpenCV的代码实现. 引言 模板匹配是一种在源图像中寻找与图像patch最相似的技术,常常用来进 ...

  8. 【图像处理】——特征匹配(SIFT特征检测器+FLANN特征匹配方法+KNN近邻最优匹配筛选)——cv.xfeatures2d.SIFT_create()sift.detectAndCompute

    转载请注明地址 目录 1.特征检测和特征匹配方法 (1)特征检测算法 (2)特征匹配算法 (3)各种特征检测算法的比较 2.特征匹配的基本步骤(附带主要的函数) (1)图像预处理--灰度化(模板--查 ...

  9. OpenCV与图像处理学习十二——图像形状特征之HOG特征

    OpenCV与图像处理学习十二--图像形状特征之HOG特征 一.图像特征理解 1.1 颜色特征 1.2 纹理特征 1.3 形状特征 1.4 空间关系特征 二.形状特征描述 2.1 HOG特征 2.1. ...

最新文章

  1. Java面试题之一 (转)
  2. Java调用WebService接口实现发送手机短信验证码功能
  3. 建造者模式 coding
  4. sphinx和coreseek
  5. poj 1325 Machine Schedule 最小顶点覆盖
  6. rtklib 后处理_RTKLIB 手册解读及代码调试知识总结
  7. Quartz 2.x 任务调度使用(CronTrigger)
  8. 太硬核了,50年前的登月程序和程序员绝对超乎你的想象
  9. 烂泥:KVM虚拟机的关机与开启
  10. 正则判断手机号地区_匹配中国大陆所有手机号正则表达式
  11. 程序员的成长之路——道和术的思考
  12. 如何快速通过信息系统管理工程师考试
  13. 计算机硬盘容量越大运行速度越快,你是不是也感觉电脑内存越大运行速度越快?...
  14. 一步一步实现STM32-FOTA系列教程之BIN文件解包C语言实现
  15. python小操作——读取文件夹内的任意格式文件到txt并排序
  16. K8s Liveness/Readiness/Startup 探针机制
  17. 【揭密:刘强东9年密谋的商业布局—京东快物流背后的核心技术盘点】
  18. IPsec IKE第一阶段主模式和野蛮模式
  19. C++标准库中的数学函数
  20. Ajax保姆级使用攻略

热门文章

  1. java long类型报错:error: integer number too large
  2. OpenGL ES简介(一)
  3. 十大经典算法总结(JavaScript描述)
  4. 人脸方向学习(十):Face Detection-MobileNet_SSD解读
  5. Educoder 机器学习之随机森林算法 第3关:手写数字识别
  6. Zabbix(简介和ubuntu安装步骤)
  7. 简单叙述tcp/ip的工作原理和主要的协议_802.11协议精读3:CSMA/CD与CSMA/CA
  8. 大学python作业_2020年大学moocPython编程基础作业答案
  9. 外星人进化_外星人真的比人类强大吗?科学家给出几种猜想,你认同吗?
  10. quarts集群 运维_Quartz.Net分布式运用