在图像间进行特征匹配

2023-11-15

特征匹配

目标
  • 我们将要学习在图像间进行特征匹配
  • 使用 OpenCV 中的蛮力(Brute-Force)匹配和 FLANN 匹配

Brute-Force 匹配的基础
  蛮力匹配器是很简单的。首先在第一幅图像中选取一个关键点然后依次与第二幅图像的每个关键点进行(描述符)距离测试,最后返回距离最近的关键点。
  对于 BF 匹配器,我们首先要使用 cv2.BFMatcher() 创建一个BFMatcher 对象。它有两个可选参数。第一个是 normType。它是用来指定要使用的距离测试类型。默认值为 cv2.Norm_L2。这很适合 SIFT 和 SURF 等 (c2.NORM_L1 也可以)。对于使用二进制描述符的 ORB,BRIEF,BRISK算法等,要使用 cv2.NORM_HAMMING,这样就会返回两个测试对象之间的汉明距离。如果 ORB 算法的参数设置为 V T A_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 的例子吧。(使用不同距离计算方法)。
  
对 ORB 描述符进行蛮力匹配
  现在我们看一个在两幅图像之间进行特征匹配的简单例子。在本例中我们有一个查询图像和一个目标图像。我们要使用特征匹配的方法在目标图像中寻找查询图像的位置。(这两幅图像分别是/sample/c/box.png和/sample/c/box_in_scene.png)
  我们使用 ORB 描述符来进行特征匹配。首先我们需要加载图像计算描述符。

# -*- coding: utf-8 -*-
"""
Created on Fri Jan 24 15:10:41 2014
@author: duan
"""
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

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

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

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

对 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
# 比值测试,首先获取与 A 距离最近的点 B(最近)和 C(次近),只有当 B/C
# 小于阈值时(0.75)才被认为是匹配,因为假设匹配是一一对应的,真正的匹配的理想距离为 0
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[:10],flags=2)
plt.imshow(img3),plt.show()

结果如下:
在这里插入图片描述
FLANN 匹配器
   FLANN 是快速最近邻搜索(Fast_Library_for_Approximate_Nearest_Neighbors)的简称。它是一个对大数据集和高维特征进行最近邻搜索的算法的集合,而且这些算法都已经被优化过了。在面对大数据集时它的效果要好于 BFMatcher。我们来对第二个例子使用 FLANN 匹配看看它的效果。
   使用 FLANN 匹配,我们需要传入两个字典作为参数。这两个用来确定要使用的算法和其他相关参数等。第一个是 IndexParams。各种不同算法的信息可以在 FLANN 文档中找到。这里我们总结一下,对于 SIFT 和 SURF 等,我们可以传入的参数是:
   inde x p {{x}_{p}} xparams = dict(algorithm = F LAN N I {{N}_{I}} NINDE X K {{X}_{K}} XKDT REE, trees = 5)但使用 ORB 时,我们要传入的参数如下。注释掉的值是文献中推荐使用的,但是它们并不适合所有情况,其他值的效果可能会更好。
  但使用 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
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()

第二个字典是 SearchParams。用它来指定递归遍历的次数。值越高结果越准确,但是消耗的时间也越多。如果你想修改这个值,传入参数:searc h p {{h}_{p}} hparams = dict(checks = 100)。
  有了这些信息我们就可以开始了。

# -*- coding: utf-8 -*-
"""
Created on Fri Jan 24 15:36:42 2014
@author: duan
"""
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()

结果如下:
在这里插入图片描述

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

在图像间进行特征匹配 的相关文章

  • 将 JSON 发布到 Python CGI

    我已经安装了 Apache2 并且 Python 可以工作 但我有一个问题 我有两页 一个是 Python 页面 另一个是带有 JQuery 的 Html 页面 有人可以告诉我如何让我的 ajax 帖子正常工作吗
  • Python 转换矩阵

    我有一个如下所示的列表 2 1 3 1 2 3 1 2 2 2 我想要的是一个转换矩阵 它向我显示如下序列 1 后跟 1 的频率是多少 1 后面跟着 2 的频率是多少 1 后跟 3 的频率是多少 2 后跟 1 的频率是多少 2 后跟 2 的
  • Matplotlib 图例,跨列添加项目而不是向下添加项目

    对于下面的简单绘图 有没有办法让 matplotlib 填充图例 以便它从左到右填充行 而不是第一列然后第二列 gt gt gt from pylab import gt gt gt x arange 2 pi 2 pi 0 1 gt gt
  • 将 Python Pandas DataFrame 写入 Word 文档

    我正在努力创建一个使用 Pandas DataFrames 的 Python 生成的报告 目前我正在使用DataFrame to string 方法 但是 这会作为字符串写入文件 有没有办法让我实现这一目标 同时将其保留为表格 以便我可以使
  • Flask 失败并显示“错误:导入‘X’时,引发了 ImportError”,但不显示错误。如何找到错误的根源?

    当使用以下命令启动 Flask 应用程序时 flask run 我收到错误 Error While importing wsgi an ImportError was raised Usage flask OPTIONS COMMAND A
  • 在linux上安装python ssl模块,无需重新编译

    是否可以在已经安装了 OpenSSL 的 Linux 机器上安装 python 的 SSL 模块 而无需重新编译 python 我希望它就像复制几个文件并将它们包含在库路径中一样简单 Python版本是2 4 3 谢谢 是否可以在已经安装了
  • Python - Unicode 到 ASCII 的转换

    我无法在不丢失数据的情况下将以下 Unicode 转换为 ASCII u ABRA xc3O JOS xc9 I tried encode and decode他们不会这么做 有人有建议吗 Unicode 字符u xce0 and u xc
  • 将 window.location 传递给 Flask url_for

    我正在使用 python 在我的页面上 当匿名用户转到登录页面时 我想将一个变量传递到后端 以便它指示用户来自哪里 发送 URL 因此 当用户单击此锚链接时 a href Sign in a 我想发送用户当前所在页面的当前 URL
  • Python-验证我的文档 xls 中是否存在工作表

    我正在尝试在空闲时间设计一个小程序 加载 xls 文件 然后在要扫描的文档中选择一张纸 步骤1 用户导入 xls文件 导入程序后检查文件是否存在 我能做到的 第 2 步 我要求用户提供要分析的文档表 xls 的名称 这就是它停止的地方 该程
  • 为什么将模块级代码放入函数中然后调用该函数在Python中速度更快?

    在亚历克斯 马尔泰利的回应中使 Python 脚本面向对象 https stackoverflow com questions 1813117 making a python script object oriented 他提到在 Pyth
  • Python:在字典中查找具有唯一值的键?

    我收到一个字典作为输入 并且想要返回一个键列表 其中字典值在该字典的范围内是唯一的 我将用一个例子来澄清 假设我的输入是字典 a 构造如下 a dict a cat 1 a fish 1 a dog 2 lt unique a bat 3
  • 为什么 Collections.counter 这么慢?

    我正在尝试解决罗莎琳德的基本问题 即计算给定序列中的核苷酸 并在列表中返回结果 对于那些不熟悉生物信息学的人来说 它只是计算字符串中 4 个不同字符 A C G T 出现的次数 我期望collections Counter是最快的方法 首先
  • 如何获取分类数据的分组条形图

    I have a big dataset with information about students And I have to build a graph of dependencies between different value
  • 如何在matplotlib中调整x轴

    I have a graph like this x轴上的数据表示小时 所以我希望x轴设置为0 24 48 72 而不是现在的值 很难看到 0 100 之间的数据 fig1 plt figure ax fig1 add subplot 11
  • 如何通过 Python Requests 库使用基本 HTTP 身份验证?

    我正在尝试在 Python 中使用基本的 HTTP 身份验证 我正在使用Requests https docs python requests org 图书馆 auth requests post http hostname auth HT
  • Django 将 JSON 数据传递给静态 getJSON/Javascript

    我正在尝试从 models py 中获取数据并将其序列化为views py 中的 JSON 对象 模型 py class Platform models Model platformtype models CharField max len
  • 如何创建用于霍夫曼编码和解码的树?

    对于我的作业 我将对霍夫曼树进行编码和解码 我在创建树时遇到问题 并且陷入困境 不要介意打印语句 它们只是让我测试并查看函数运行时的输出是什么 对于第一个 for 循环 我从主块中用于测试的文本文件中获取了所有值和索引 在第二个 for 循
  • Python 相当于 Scala 案例类

    Python 中是否有与 Scala 的 Case Class 等效的东西 就像自动生成分配给字段而无需编写样板的构造函数一样 当前执行此操作的现代方法 从 Python 3 7 开始 是使用数据类 https www python org
  • Biopython 可以执行 Seq.find() 来解释歧义代码吗

    我希望能够在 Seq 对象中搜索考虑歧义代码的子序列 Seq 对象 例如 以下内容应该是正确的 from Bio Seq import Seq from Bio Alphabet IUPAC import IUPACAmbiguousDNA
  • OpenCV SIFT 描述符关键点半径

    我正在深入研究OpenCV的SIFT描述符提取的实现 https github com Itseez opencv blob master modules nonfree src sift cpp 我发现了一些令人费解的代码来获取兴趣点邻域

随机推荐

  • 【JAVA设计模式】之桥接模式(BridgePattern)

    桥接模式的作用是将两样东西连接起来 比如桥梁把河的两岸连接起来 桥接模式把 类的功能层次结构 和 类的实现层次结构 连接起来 类的层次结构 类的功能层次 父类通过定义抽象方法来定义接口API 类的实现层次 子类通过实现具体方法来实现接口AP
  • FP64、FP32、FP16、FP8简介

    目录 1 单精度浮点数FP32的表示 2 半精度浮点数FP16的表示 3 双精度浮点数FP64的表示 4 FP8 5 写在最后 1 单精度浮点数FP32的表示 浮点数由三部分组成 符号位 指数部分 尾数部分 以单精度浮点数为例 如图所示 符
  • 好多粉使用百度OCPC api提交后如何手动选择有效咨询回传?

    推广每天会有复制 虽然绝大部分是正常的数据 但也有可能有的是同行刷的 有的是没有添加成功的数据 如果不处理 会造成无效数据上传 只能投放的AI可能就要被某些别有用心的人玩坏了 所以我们为解决这个痛点 开发了手动回传功能 并且系统自动帮你标识
  • VS2019现有项目添加Qt界面

    目录 Qt安装教程 Qt下载 Qt安装 VS Qt插件 配置Qt插件 配置包含目录及链接器 添加QT界面 添加UI界面 配置文件属性 编译UI文件 添加 h和 cpp文件 简单运行测试 双击ui文件打开Qt Designer闪退问题 与VS
  • c++实现霍夫曼编码

    c 实现霍夫曼编码 计算信源的熵 平均码长 编码效率 冗余度与压缩比 考虑到指针可能对新手不太友好 这里用的是vector容器 用法类似数组 可以动态扩容 存储树形结构 大致原理就是n号结点的左右子树分别是2n和2n 1号结点 Huffma
  • XMPP客户端库Smack 4.1.4版官方开发文档之五

    本文转载自 博客主页 http blog csdn net chszs 五 名单Roster和在线状态Presence 名单可以让你跟踪其他用户是否在线 而且名单可以让你把用户组织到群组 比如朋友群或工作群 而其它的即时通信IM系统则把名单
  • 7个高频出现的面试题

    收集了2022年所有学生的面试题后 我整理出了7个高频出现的面试题 一起来看看 高频问题1 请自我介绍下 高频问题2 请介绍下最近做过的项目 高频问题3 请介绍下你印象深刻的bug 高频问题4 Fiddler工具怎么使用的 高频问题5 说一
  • 判断是否为数字的两种办法

    今天在写angular的ts中碰到一个问题 就是需要判断用户id是否是number类型还是uuid 在这里我采用了两种办法 1 使用typeof 判断是什么类型 if typeof res userInfo id number alert
  • sar 命令

    NAME sar Collect report or save system activity information SYNOPSIS sar A b B C d h i interval m p q r R S t u ALL v V
  • 2.2 SSD之地址映射

    LBA Logical Block Address 表示用户操作 读写 数据的位置 PBA Physics Block Address 表示数据在硬盘的真实位置 在HDD时代 数据可以覆盖写 LBA和PBA直接对应不会更改 但是SSD时代
  • leetcode-453. 最小操作次数使数组元素相等-js

    题目 代码 关键 每次操作使 n 1 个元素增加 1 相当于使1个元素减小 1 所以算出每个元素减小到最小元素的次数即可 var minMoves function nums const minNum Math min nums retur
  • BootStrap-table 复选框默认选中(checkbox)

    BootStrap table 复选框默认选中 checkbox bootstrap table colums 写法 var columns field checked checkbox true formatter stateFormat
  • 基于深度学习的人脸识别综述

    本文转载自 https xraft github io 2018 03 21 FaceRecognition 作者 Caleb Ge 葛政 如有侵权请告知删除 下文中的 我 均为原文作者 另附有查找的其他参考链接 论文介绍方面链接 1 ht
  • 第三章-Python中的数据类型

    欢迎来到python的世界 博客主页 卿云阁 欢迎关注 点赞 收藏 留言 本文由卿云阁原创 本阶段属于练气阶段 希望各位仙友顺利完成突破 首发时间 2021年3月14日 希望可以和大家一起完成进阶之路 作者水平很有限 如果发现错误 请留言轰
  • ubuntu下编译问题集锦

    1 DSO missing from command line 一般是库链接顺序不对 将依赖于其他库的lib放在前面 库放在后面就行 2 fatal error ceres ceres h No such file or directory
  • CTF中那些脑洞大开的编码和加密

    0x00 前言 正文开始之前先闲扯几句吧 玩CTF的小伙伴也许会遇到类似这样的问题 表哥 你知道这是什么加密吗 其实CTF中脑洞密码题 非现代加密方式 一般都是各种古典密码的变形 一般出题者会对密文进行一些处理 但是会给留一些线索 所以写此
  • vant使用时覆盖默认样式

    在我们使用vant的时候 有时候一些组件的默认样式并不能满足我们项目的需求 这个时候我们可以使用下面的办法 覆盖掉默认样式 亲测有效 vant覆盖默认样式的写法 v deep van cell not last child after le
  • transform的scale属性实现对大屏的适配

    最近公司做的大屏用到了transform的scale属性来对大屏网页 进行缩放 缺点 需要给项目大屏 设定固定的宽高 当使用的屏幕分辨率和项目不一致时 会出现左右或者上下的留白 如果设计稿是1920 1080的尺寸 项目中用px来写宽高的话
  • QT 自学内容 day06 文件的打开,读取,写入,输出内容的时候编码方式的修改,文件的创建日期,和最后的修改时间

    1 打开文件 头文件 include
  • 在图像间进行特征匹配

    特征匹配 目标 我们将要学习在图像间进行特征匹配 使用 OpenCV 中的蛮力 Brute Force 匹配和 FLANN 匹配 Brute Force 匹配的基础 蛮力匹配器是很简单的 首先在第一幅图像中选取一个关键点然后依次与第二幅图像