opencv 进阶17-使用K最近邻和比率检验过滤匹配(图像匹配)

K最近邻(K-Nearest Neighbors,简称KNN)和比率检验(Ratio Test)是在计算机视觉中用于特征匹配的常见技术。它们通常与特征描述子(例如SIFT、SURF、ORB等)一起使用,以在图像中找到相似的特征点。

下面是使用K最近邻和比率检验进行特征匹配的一般步骤:

  1. 提取特征描述子:
    使用适当的特征提取算法(如SIFT、SURF、ORB等)从图像中提取特征点,并计算每个特征点的描述子。

  2. 特征点匹配:
    对于两幅图像,分别计算每个特征点的描述子,并使用KNN算法来找到在第二幅图像中与每个特征点最接近的K个特征点。

  3. 比率检验:
    对于每个特征点,计算最接近的两个特征点的距离比率(通常称为比率检验)。如果最近的邻居距离远离次近邻居距离,则说明匹配比较可靠。您可以使用一个阈值来过滤匹配。

  4. 过滤匹配:
    应用比率检验,将那些距离比率低于阈值的匹配点过滤掉。这可以帮助排除掉不太可靠的匹配。

  5. 绘制匹配结果:
    将保留下来的匹配点绘制在两幅图像上,以便观察和分析。

想象一下,一大群知名哲学家邀请你评判他们关于对生命、宇宙
和一切事物都很重要的一个问题的辩论。在每位哲学家轮流发言时,你都会认真听。最后,在所有哲学家都发表完他们所有的论点时,你浏览笔记,会发现以下两件事:

  • 每位哲学家都不赞同其他哲学家的观点。
  • 没有哲学家比其他哲学家更有说服力。

根据最初的观察,你推断最多只有一位哲学家的观点是正确的,
但事实上,也有可能所有哲学家的观点都是错误的。然后,根据第二次观察,即使其中一位哲学家的观点是正确的,你也会开始担心可能会选择一个观点错误的哲学家。不管你怎么看,这些人都会让你的晚宴迟到。你称其为平局,并说辩论中仍有最重要的问题尚未解决。我们可以对判断哲学家辩论的假想问题与过滤糟糕关键点匹配的实际问题进行比较。

首先,假设查询图像中的每个关键点在场景中最多有一个正确的
匹配。也就是说,如果查询图像是NASA标识,那么就假定另一幅图像、(场景)最多包含一个NASA标识。假设一个查询关键点最多有一个正确或者良好的匹配,那么在考虑所有可能的匹配时,我们主要观察糟糕的匹配。

因此,蛮力匹配器计算每个可能匹配的距离分值,可以提供大量的对糟糕匹配的距离分值的观察。与无数糟糕的匹配相比,我期望良好的匹配会有明显更好(更低)的距离分值,因此糟糕的匹配分值可以帮助我们为针对良好的匹配选择一个阈值。这样的阈值不一定能很好地推广到不同的查询关键点或者不同的场景,但是至少在具体案例上会有所帮助。

现在,我们来考虑修改后的蛮力匹配算法的实现,该算法以上述
方式自适应地选择距离阈值。在上一节的示例代码中,我们使用
cv2.BFMatcher类的match方法来获得包含每个查询关键点的单个最佳匹配(最小距离)的列表。这样的实现丢弃了有关所有可能的糟糕匹配的距离分值的信息,而这类信息是自适应方法所需要的。幸运的是,cv2.BFMatcher还提供了knnMatch方法,该方法接受一个参数k,可以指定希望为每个查询关键点保留的最佳(最短距离)匹配的最大数量。(在某些情况下,得到的匹配数可能比指定的数量最大值更少。)KNN表示K最近邻(K-Nearest Neighbor)。

我们会使用knnMatch方法为每个查询关键点请求两个最佳匹配的
列表。基于每个查询关键点至多有一个正确匹配的假设,我们确信次优匹配是错误的。次优匹配的距离分值乘以一个小于1的值,就可以获得阈值。

然后,只有当距离分值小于阈值时,才将最佳匹配视为良好的匹
配。这种方法被称为比率检验(ratio test),最先是由David
Lowe(SIFT算法的作者)提出来的。他在论文“Distinctive Image
Features from Scale-Invariant Keypoints”(网址为
https://www.cs.ubc.cs/~lowe/papers/ijcv04.pdf)中描述了比率检
验。具体来说,在“Application to object recognition”部分,他
声明如下:

一个匹配正确的概率可以根据最近邻到第2近邻的距离比例来确
定。

我们可以用与前面代码示例相同的方式加载图像、检测关键点,
并计算ORB描述符。然后,使用下面两行代码执行蛮力KNN匹配:

    bf = cv2.BFMatcher(cv2.NORM_HAMMING, crossCheck= False)
    knn_matches = bf.knnMatch(descriptors1, descriptors2, k=2)

knnMatch返回列表的列表,每个内部列表至少包含一个匹配项,
且不超过k个匹配项,各匹配项从最佳(最短距离)到最差依次排序。

下列代码行根据最佳匹配的距离分值对外部列表进行排序:

  # 根据匹配的质量,对匹配进行排序,显示前n个排序
    knn_matches = sorted(knn_matches, key=lambda x: x[0].distance)

总体代码如下:


import cv2


def orb_test():
    # 加载图片  灰色
    img1 = cv2.imread('images\\quexiao\\2-1.png')
    gray1 = cv2.cvtColor(img1, cv2.COLOR_BGR2GRAY)
    img2 = cv2.imread('images\\quexiao\\2.png')

    gray2 = cv2.cvtColor(img2, cv2.COLOR_BGR2GRAY)
    image1 = gray1.copy()
    image2 = gray2.copy()

    '''
    1.使用ORB算法检测特征点、描述符
    '''
    orb = cv2.ORB_create(128)
    keypoints1, descriptors1 = orb.detectAndCompute(image1, None)
    keypoints2, descriptors2 = orb.detectAndCompute(image2, None)


    # BFMatcher解决匹配
    bf = cv2.BFMatcher(cv2.NORM_HAMMING, crossCheck= False)
    knn_matches = bf.knnMatch(descriptors1, descriptors2, k=2)
   # matches = bf.match(descriptors1, descriptors2)

    # 根据匹配的质量,对匹配进行排序,显示前n个排序
    knn_matches = sorted(knn_matches, key=lambda x: x[0].distance)

    # 绘制前10个最佳匹配
    img_matches = cv2.drawMatchesKnn(img1, keypoints1, img2, keypoints2, knn_matches[:10], img2,flags=cv2.DRAW_MATCHES_FLAGS_NOT_DRAW_SINGLE_POINTS)


    cv2.imshow('matche', img_matches)
    cv2.waitKey(0)

    cv2.destroyAllWindows()


if __name__ == '__main__':
    orb_test()

运行效果:

在这里插入图片描述

将此输出图像与上一节中的输出图像进行比较,可以看到使用KNN
和比率检验可以过滤掉很多糟糕的匹配项。剩余的匹配项并不完美,但是几乎所有的匹配项都指向了正确的区域。

实验原图在上一节中,上一节 opencv 进阶16-基于FAST特征和BRIEF描述符的ORB(图像匹配)

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mfbz.cn/a/86139.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

分布式锁系列之zookeeper分布式锁和mysql分布式锁

目录 介绍 下载安装 基本指令​编辑 java集成zookeeper 官方提供版 永久节点 临时节点​编辑 永久序列化节点 判断当前节点是否存在 获取当前节点中的数据内容 获取当前节点的子节点 更新节点内容 删除节点 zookeeper实现分布式锁 Mysql实现分布式锁 总结 介绍 ZooK…

【Spring框架】Spring事务的介绍与使用方法

⚠️ 再提醒一次:Spring 本身并不实现事务,Spring事务 的本质还是底层数据库对事务的支持。你的程序是否支持事务首先取决于数据库 ,比如使用 MySQL 的话,如果你选择的是 innodb 引擎,那么恭喜你,是可以支持…

2023年计算机设计大赛国三 数据可视化 (源码可分享)

2023年暑假参加了全国大学生计算机设计大赛,并获得了国家三等奖(国赛答辩出了点小插曲)。在此分享和记录本次比赛的经验。 目录 一、作品简介二、作品效果图三、设计思路四、项目特色 一、作品简介 本项目实现对农产品近期发展、电商销售、灾…

基于AVR128单片机世界电子时钟的设计

一、系统方案 上电初始化完成系统初始化,液晶滚动显示北京、莫斯科、东京、伦敦、巴黎、纽约等六个城市的标准时间,显示的内容包括地区名及相应地区的年、月、日、星期、时、分、秒。 使用K1按键控制滚动显示或稳定显示某个地区的时间。 使用K3、K4、K5按…

Linux操作系统面试题汇总

Linux操作系统 1.Linux操作命令 Linux 目录结构及常用命令详细介绍参考 2.在Linux中find和grep的区别? 在Linux中,find命令用于按照指定条件搜索文件或目录,而grep命令则用于在文件中搜索指定的文本字符串。具体来说,find命令可…

使用扩展函数方式,在Winform界面中快捷的绑定树形列表TreeList控件和

在一些字典绑定中,往往为了方便展示详细数据,需要把一些结构树展现在树列表TreeList控件中或者下拉列表的树形控件TreeListLookUpEdit控件中,为了快速的处理数据的绑定操作,比较每次使用涉及太多细节的操作,我们可以把…

深入了解Git:介绍及常用命令指南

当今软件开发领域中,版本控制是一个至关重要的概念,而Git作为最流行的分布式版本控制系统,发挥着不可替代的作用。本文将介绍Git的基本概念以及常用命令,帮助你更好地理解和使用这一强大的工具。 Git简介 Git是一种分布式版本管…

RK3399平台开发系列讲解(内核调试篇)网络调试工具

🚀返回专栏总目录 文章目录 一、dstat 工具介绍二、例如dstat 进行网络问题调试三、ss 命令查看 TCP 详细信息四、netstat 查看TCP详细信息沉淀、分享、成长,让自己和他人都能有所收获!😄 📢 本篇将介绍网络的相关工具。 一、dstat 工具介绍 当设备产生问题,而我们又…

Mysql 开窗函数(窗口函数)

文章目录 全部数据示例1(说明)开窗函数可以比groupby多查出条件列外的字段,开窗函数主要是为了跟聚合函数一起使用,达到分组统计效果,并且开窗函数的结果集基本都是跟总行数一样示例2示例3示例4错误示例1错误示例2错误…

2023河南萌新联赛第(六)场:河南理工大学

目录 A 简单的异或 题目: 解析: B 这是dp题吗 题目链接:https://ac.nowcoder.com/acm/contest/63602/B 解析: D 买饼干的小Y 题目:https://ac.nowcoder.com/acm/contest/63602/D 解析: E 不爱吃早…

Redisson 分布式锁

Redis是基础客户端库,可用于执行基本操作。 Redisson是基于Redis的Java客户端,提供高级功能如分布式锁、分布式集合和分布式对象。 Redisson提供更友好的API,支持异步和响应式编程,提供内置线程安全和失败重试机制。 实现步骤…

【算法】活用双指针完成复写零操作

Problem: 1089. 复写零 文章目录 题目解析算法原理分析找到最后一个复写的位置从后往前进行复写操作 代码展示 题目解析 首先我们来分析一下本题的题目意思 可以看到题目中给到了一个数组,意思是让我们将数组中的零元素都复写一遍,然后将其余的元素向后平…

云计算在IT领域的发展和应用

文章目录 云计算的发展历程云计算的核心概念云计算在IT领域的应用1. 基础设施即服务(IaaS):2. 平台即服务(PaaS):3. 软件即服务(SaaS): 云计算的拓展应用结论 &#x1f3…

无涯教程-PHP - 全局变量函数

全局变量 与局部变量相反,可以在程序的任何部分访问全局变量。通过将关键字 GLOBAL 放置在应被识别为全局变量的前面,可以很方便地实现这一目标。 <?php$somevar15;function addit() {GLOBAL $somevar;$somevar;print "Somevar is $somevar";}addit(); ?> …

NineData中标移动云数据库传输项目(2023)

近日&#xff0c;玖章算术NineData智能数据管理平台成功中标《2023年移动云数据库传输服务软件项目》&#xff0c;中标金额为406万。这标志着玖章算术NineData平台已成功落地顶级运营商行业&#xff0c;并在数据管理方面实现了大规模应用实践。 NineData中标2023移动云数据库传…

LabVIEW硬件在环仿真模拟电路故障分析和特征提取

LabVIEW硬件在环仿真模拟电路故障分析和特征提取 与数字电路相比&#xff0c;模拟电路故障分析是一项具有挑战性的任务。这主要是由于模拟分立元件的非线性特性&#xff0c;以及其他因素&#xff0c;包括噪声和内部可访问性的限制。参数故障和灾难性故障是模拟电路中发生的两种…

使用IDEA把Java程序打包成jar

点击左上角File,选择Project Structure 左侧选中Artifacts,点击右侧的号 选择JAR->From modules with dependencies 选择你要运行的main方法所在的类,选好了点击OK Artifacts添加完成后点击右下角OK 在工具栏中找到Build,选择Build Artifacts 刚才创建好的Artifacts,选择Bui…

阿里云使用WordPress搭建个人博客

手把手教你使用阿里云服务器搭建个人博客 一、免费创建服务器实例 1.1 点击试用 点击试用会需要你创建服务器实例&#xff0c;直接选择默认的操作系统即可&#xff0c;点击下一步 1.2 修改服务器账号密码 二、创建云数据库实例 2.1 免费获取云数据库使用 2.2 实例列表页 在…

ORB-SLAM系列算法演进

ORB-SLAM算法是特征点法的代表&#xff0c;当前最新发展的ORB-SLAM3已经将相机模型抽象化&#xff0c;适用范围非常广&#xff0c;虽然ORB-SLAM在算法上的创新并不是很丰富&#xff0c;但是它在工程上的创新确实让人耳目一新&#xff0c;也能更好的为AR、机器人的算法实现落地。…

【笔记】MySQL行转列函数

GROUP_CONCAT()函数 创建表person_info&#xff0c;并插入数据 CREATE TABLE person_info (id bigint(20) NOT NULL AUTO_INCREMENT,name varchar(100) DEFAULT NULL,family varchar(100) DEFAULT NULL,PRIMARY KEY (id) ) ENGINEInnoDB AUTO_INCREMENT8 DEFAULT CHARSETutf8;…