(四)OpenCV中的特征检测之特征匹配

news/2024/11/23 3:57:07/

注释:本文翻译自OpenCV3.0.0 document->OpenCV-Python Tutorials,包括对原文档种错误代码的纠正

1.概述

我们知道很多关于特征检测器和描述符。 现在是学习如何匹配不同描述符的时候了。 OpenCV提供了两种技术,Brute-Force匹配器和基于FLANN的匹配器。

2.目标

  • 我们将看到如何将一副图像中的特征与其它图像特征匹配
  • 我们将在OpenCV中使用Brute-Force匹配器和FLANN Matcher

3.Brute-Force匹配器基础(Basics of Brute-Force Matcher)

    蛮力匹配器很简单。它采用第一组的一个特征的描述符并且使用一些距离计算与第二组中的所有其它特征匹配。将最近的一个返回。 

    对于BF匹配器,首先我们必须使用cv2,BFMatcher()创建BFMatcher对象。它需要两个可选参数,首先是normType。它指定要使用的距离测量。默认情况下,它是cv2.NORM_L2,这对SIFT、SURF等是有好处的(cv2.NORM_L1也在那里)。对于像ORB,BRIEF、BRISK等基于二进制字符串的描述符,应该使用cv2.NORM_HAMMING,它使用汉明距离作为度量。如果ORB使用WTA_K==3或4,则应使用cv2.NORM_HAMMING2.

    第二个参数是布尔变量,crossCheck默认为false。如果确实如此,则匹配器仅返回具有值(i,j)的匹配,使得集合A中的第i个描述符具有集合B中的第j个描述符作为最佳匹配,反之亦然。也就是说,两组中的两个特征应该相互匹配。它提供了一致的结果,对于D.Lowe在SIFT论文中提出的比率测试来说是一个很好的选择。

   一旦创建,两个重要的方法是BFMatcher.match()和BFMatcher.knnMatch()。首先返回最佳匹配。第二种方法返回k个最佳匹配,其中k由用户指定。当我们需要为此做额外的工作时,它可能会有用。

    就像我们使用cv2.drawKeypoints()来绘制关键点,cv2.drawMatches()帮助我们绘制匹配。它将两个图像水平堆叠,并从第一个图像到第二个图像绘制线条,以显示最佳匹配。还有cv2.drawMatchesKnn可以绘制所有k个最佳匹配。如果k = 2,它将为每个关键点绘制两条匹配线。所以如果我们想要有选择地绘制它,我们必须传递一个掩码。

我们来看SURF和ORB的每个例子(都使用不同的距离测量)。


4.用ORB描述符进行Brute-Force匹配(Brute-Force Matching with ORB Descripotrs)

在这里,我们将看到一个关于如何匹配两幅图像之间特征的简单示例。在这种情况下,我有一个queryImage和一个trainImage。 我们将尝试使用特征匹配在trainImage中查找queryImage。 (图像是/samples/c/box.png和/samples/c/box_in_scene.png)。

我们使用SIFT描述符来匹配特征。那么让我们开始加载图片,找到描述符等。

接下来我们创建一个距离测量值为cv2.NORM_HAMMING的BFMatcher对象(因为我们使用的是ORB),并且为了获得更好的结果,crossCheck被打开。 然后我们使用Matcher.match()方法来获取两幅图像中的最佳匹配。 我们按照距离的升序对它们进行排序,以便最佳匹配(低距离)出现在前面。然后我们只画出前10个匹配(只是为了能见度,你可以随意增加)。

代码如下:

# -*- coding: utf-8 -*-
'''
特征匹配(Feature Matching):
1.了解了很多特征检测器和描述符,现在是学习如何匹配不同描述符的时候了。
2.OpenCV提供了两种技术:Brute-Force匹配器和基于FLANN的匹配器
3.学会如何将一幅图像中的特征与其它图像匹配特征匹配器1:Brute-Force(basicis of Brute-Force Matcher)蛮力匹配器它采用第一组中的一个特征的描述符并且使用一些距离计算与第二组中的所有其它特征匹配。将最近的一个返回。1.首先使用cv2.BFMatcher(normType,bool)创建BFMatcher对象.2.BFMatcher.match()和BFMatcher().knnMatch()。前一个方法返回最佳匹配,第二个方法返回k个最佳匹配。3.使用cv2.drawMatches()帮助我们绘制匹配。还有cv2.drawMatchesknn()绘制k个最佳匹配。需要传递一个掩膜下面的栗子:用ORB描述符进行BF匹配
'''import cv2
import numpy as np
from matplotlib import pyplot as pltimg1 = cv2.imread('1.jpg', 0)  # 查询图片  queryImage
img2 = cv2.imread('2.jpg', 0)  # 训练图片  trainImage# 初始化SIFT探测器
orb = cv2.ORB_create()# 用SIFT找到关键点和描述符
kp1, des1 = orb.detectAndCompute(img1, None)
kp2, des2 = orb.detectAndCompute(img2, None)'''
接下来创建一个距离测量值为cv2.NORM_HAMMING的BFMatcher对象
用Matcher.match()来获取两幅图像中的最佳匹配;
我们按照距离的升序对它们进行排序
'''
# 创建BFMatcher对象
bf = cv2.BFMatcher(cv2.NORM_HAMMING, crossCheck=True)# 匹配器描述符:结果是DMatch对象的列表,该DMatch对象具有以下属性:# 1.DMatch.distance:描述符之间的距离。越低,它就越好。# 2.DMatch.trainIndex:训练描述符中描述符的索引# 3.DMatch.queryIndex:查询描述符中描述符的索引# 4.DMatch.imgIndex:训练图像的索引
matches = bf.match(des1, des2)# 根据距离排序,第六个参数是outImg
img3 = cv2.drawMatches(img1, kp1, img2, kp2, matches[:10], None, flags=2)plt.imshow(img3), plt.show()

结果:


5.这个匹配对象是什么?

matches=bf.match(des1,des2)行的结果是DMatch对象的列表。该DMatch对象具有以下属性:

  • DMatch.distance - 描述符之间的距离。 越低,它就越好。
  • DMatch.trainIdx – 训练描述符中描述符的索引
  • DMatch.queryIdx - 查询描述符中描述符的索引
  • DMatch.imgIdx – 训练图像的索引

6.使用SIFT描述符和比率测试的Brute-Force匹配(强力匹配)

这一次,我们将使用BFMatcher.knnMatch()来获得k个最佳匹配。 在这个例子中,我们将采取k = 2,以便我们可以应用D.Lowe在他的论文中解释的比率测试。

# -*- coding: utf-8 -*-
'''
下面的栗子:使用SIFT描述符和比率测试的Brute-Force匹配
'''import numpy as np
import cv2
from matplotlib import pyplot as pltimg1 = cv2.imread('1.jpg', 0)
img2 = cv2.imread('2.jpg', 0)# 初始化SIFT检测器
sift = cv2.xfeatures2d.SIFT_create()# 用SIFT找到关键点和描述符
kp1, des1 = sift.detectAndCompute(img1, None)
kp2, des2 = sift.detectAndCompute(img2, None)# 默认参数的BFMatcher
bf = cv2.BFMatcher()
matches = bf.knnMatch(des1, des2, k=2)# 应用比率测试(ratio test)
good = []
for m, n in matches:if m.distance < 0.75 * n.distance:good.append([m])img3 = cv2.drawMatchesKnn(img1, kp1, img2, kp2, good, None, flags=2)
plt.imshow(img3), plt.show()

查看下面的结果:


7.基于FLANN的匹配器(FLANN based Matcher)

FLANN表近似最近邻居的快速库。它包含一组经过优化的算法,用于大数据集中的快速最近邻搜索以及高维特征。对于大型数据集,它的工作速度比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_params = dict(checks = 100)。

有了这些信息,我们就很好去匹配:

# -*- coding: utf-8 -*-
'''
基于FLANN的匹配器(FLANN based Matcher)
1.FLANN代表近似最近邻居的快速库。它代表一组经过优化的算法,用于大数据集中的快速最近邻搜索以及高维特征。
2.对于大型数据集,它的工作速度比BFMatcher快。
3.需要传递两个字典来指定要使用的算法及其相关参数等
对于SIFT或SURF等算法,可以用以下方法:
index_params = dict(algorithm = FLANN_INDEX_KDTREE, trees = 5)
对于ORB,可以使用以下参数:
index_params= dict(algorithm = FLANN_INDEX_LSH,table_number = 6, # 12   这个参数是searchParam,指定了索引中的树应该递归遍历的次数。值越高精度越高key_size = 12,     # 20multi_probe_level = 1) #2'''
import cv2
import numpy as np
from matplotlib import pyplot as pltimg1 = cv2.imread('1.jpg', 0)
img2 = cv2.imread('2.jpg', 0)# 初始化SIFT检测器
sift = cv2.xfeatures2d.SIFT_create()# 用SIFT找到关键点和描述符
kp1, des1 = sift.detectAndCompute(img1, None)
kp2, des2 = sift.detectAndCompute(img2, None)# FLANN参数
FLANN_INDEX_KDTREE = 0
index_params = dict(algorithm=FLANN_INDEX_KDTREE, trees=5)
search_params = dict(checks=50)  # 或者传递空字典flann = cv2.FlannBasedMatcher(index_params, search_params)
matches = flann.knnMatch(des1, des2, k=2)# 只需要绘制好的匹配,所以创建一个掩膜
matchesMask = [[0, 0] for i in range(len(matches))]# 按照Lowe的论文进行比率测试
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()

看结果:




http://www.ppmy.cn/news/196502.html

相关文章

密钥策略的属性基加密(KP-ABE)

目录 KP-ABE的基本知识 KP-ABE过程 KP-ABE的说明 参考文献 KP-ABE的基本知识 基本的属性基加密将密文和密钥都与一组属性关联起来&#xff0c;当密文与密钥之间至少有d个属性重合时&#xff0c;用户就可以解密密文。虽然这个策略对于生物识别的容错加密有一定的作用&#x…

计算机控制实验2,计算机控制系统实验报告 (2)

《计算机控制系统实验报告 (2)》由会员分享,可在线阅读,更多相关《计算机控制系统实验报告 (2)(23页珍藏版)》请在人人文库网上搜索。 1、计算机控制系统实验报告实验一 :D/A数模转换实验实验报告:1、 数字量与模拟量的对应曲线:2、 理论值与实测值对比:数字量模拟量理论…

ORB-SLAM2代码详解06: 单目初始化器Initializer

pdf版本笔记的下载地址: ORB-SLAM2代码详解06_单目初始化器Initializer,排版更美观一点,这个网站的默认排版太丑了&#xff08;访问密码&#xff1a;3834&#xff09; ORB-SLAM2代码详解06: 单目初始化器Initializer 各成员变量/函数初始化函数: Initialize()计算基础矩阵F和单…

SAP中 输入计划作业价格 KP26

在“作业类型”一文中&#xff0c;我们详细介绍了SAP中作业类型的定义&#xff0c;为学习成本核算奠定了基础。在CO模块&#xff0c;通过作业类型结转产品的制造成本&#xff0c;金额等于作业消耗量乘以作业单价。 作业类型标准单价需要每月维护&#xff0c;由成本会计录入&am…

KP522201A采用 SOT23-6 封装的 4.5V 至 17V 输入、2A 输出、600kHz 同步降压转换器

KP52220XA 采用 SOT23-6 封装的 4.5V 至 17V 输入、2A 输出、600kHz 同步降压转换器 KP522201A/08A 是一种简单易用、高效集成的同步降压转换器。它具有 4.5V 到 17V 的宽输入电压范围&#xff0c;非常适合于 12V 和 15V 等各种常见的输入电压轨。它支持高达 2A 的持续输出…

CP-ABE,KP-ABE

1.背景 区块链典型的一个应用场景是资源共享&#xff0c;而在实际应用中&#xff0c;很多参与者的数据很涉及机密&#xff0c;数据所有者并不乐意把自己的数据公开出来。数据明文在链上存证后&#xff0c;虽然共享给其他人&#xff0c;但是数据被所有的人都能查看&#xff0c;…

python特征匹配_OpenCV-Python 系列之特征匹配

之前我们讨论过了众多的特征检测算法,这次我们来讨论如何运用相关的方法进行特征匹配。本次教程完全为实战教程,没有相关的算法原理介绍,大家可以轻松一下了。 蛮力匹配(ORB匹配) Brute-Force 匹配非常简单,首先在第一幅图像中选择一个关键点然后依次与第二幅图像的每个关键…

Linux mem 2.3 内核页表隔离 (KPTI) 详解

文章目录 1. 背景介绍1.1 Meltdown & Spectre 漏洞1.2 KPTI补丁 2. KPTI原理2.1 页表隔离2.2 TLB刷新策略 3. 代码实现3.1 pgd切换3.2 系统调用3.3 进程切换3.4 pgd的初始化 4. 相关知识4.1 ALTERNATIVE()4.2 .pushsection4.3 宏计数器\4.4 pt_regs 参考文档&#xff1a; 1…