【OpenCV 例程 300篇】251. 特征匹配之暴力匹配

news2024/11/19 22:48:44

『youcans 的 OpenCV 例程300篇 - 总目录』


【youcans 的 OpenCV 例程 300篇】251. 特征匹配之暴力匹配


特征匹配是特征检测和特征描述的基本应用,在在图像拼接、目标识别、三维重建等领域的应用非常广泛。
基于特征描述符的特征点匹配是通过对两幅图像的特征点集合内的关键点描述符的相似性比对来实现的。分别对参考图像(Reference image)和检测图像(Observation image)建立关键点描述符集合,采用某种距离测度作为关键点描述向量的相似性度量。当参考图像中的关键点描述符R_i与检测图像中的关键点描述符S_j的距离测度d(R_i,S_j )满足设定条件时,判定(R_i,S_j )是配对的关键点描述符。


1. 暴力匹配(Brute-force matcher)

暴力匹配(Brute-force matcher)是最简单的二维特征点匹配方法。对于从两幅图像中提取的两个特征描述符集合,对第一个集合中的每个描述符 R i R_i Ri,从第二个集合中找出与其距离最小的描述符 S j S_j Sj作为匹配点。
暴力匹配显然会导致大量错误的匹配结果,还会出现一配多的情况。通过交叉匹配或设置比较阈值筛选匹配结果的方法可以改进暴力匹配的质量。
如果参考图像中的描述符 R i R_i Ri与检测图像中的描述符 S j S_j Sj的互为最佳匹配,则称 ( R i , S j ) (R_i,S_j ) (Ri,Sj)为一致配对。交叉匹配通过删除非一致配对来筛选匹配结果,可以避免出现一配多的错误。
比较阈值筛选是指对于参考图像的描述符 R i R_i Ri,从检测图像中找到距离最小的描述符 S j 1 S_j1 Sj1和距离次小的描述符 S j 2 S_j2 Sj2。设置比较阈值 t ∈ [ 0.5 , 0.9 ] t∈[0.5,0.9] t[0.5,0.9],只有当最优匹配距离与次优匹配距离满足阈值条件 d ( R i , S j 1 ) ⁄ d ( R i , S j 2 ) < t d(R_i,S_j1) ⁄ d(R_i,S_j2) <t d(Ri,Sj1)d(Ri,Sj2)<t时,表明匹配描述符 S j 1 S_j1 Sj1具有显著性,才接受匹配结果 ( R i , S j 1 ) (R_i,S_j1) (Ri,Sj1)


2. OpenCV 的 BFMatcher类

在OpenCV中提供了cv::BFMatcher类实现暴力匹配。
在Python语言中通过接口函数cv.BFMatcher_create或cv.BFMatcher.create实例化BFMatcher类,创建BFMatcher对象。通过成员函数bf.match对两个描述符集合进行暴力匹配,函数bf.knnMatch对两个描述符集合进行K近邻匹配。

函数原型

cv.BFMatcher.create([, normType, crossCheck]) → retval
cv.BFMatcher_create([, normType, crossCheck]) → retval
bf.match(queryDescriptors, trainDescriptors[, mask]) → matches
bf.knnMatch(queryDescriptors, trainDescriptors, k[, mask, compactResult]) → matches

参数说明

  • normType:距离类型,可选项,默认为欧式距离NORM_L2。
    • NORM_L1:L1范数,曼哈顿距离。
    • NORM_L2:L2范数,欧式距离。
    • NORM_HAMMING:汉明距离。
    • NORM_HAMMING2:汉明距离2,对每2个比特相加处理。
  • crossCheck:交叉匹配选项,可选项,默认为False。
  • queryDescriptors:描述符的查询点集,即参考图像的特征描述符的集合。
  • trainDescriptors:描述符的训练点集,即检测图像的特征描述符的集合。
  • mask:匹配点集的掩码,列表。
  • k:返回匹配点的数量。
  • matches:匹配结果,列表或元组,长度为成功的匹配数量。

注意问题

  • ⑴ 匹配结果是DMatch数据结构,包括:查询点集索引_queryIdx、训练点集索引_trainIdx和匹配距离_distance,可以用如match._distance的方式获取相应的属性值。
  • ⑵ 暴力匹配函数bf.match只返回最优匹配点,返回值matches是列表类型,列表长度为成功的匹配数量,列表元素matches[i]为DMatch数据结构。
  • ⑶ K近邻匹配函数bf.knnMatch对每个特征点返回k个最优的匹配结果,返回值matches是形如(N,k)的元组,N为特征点数量。元组元素matches[i,k]为DMatch数据结构。
  • ⑷ 交叉匹配选项crossCheck默认为False,不进行交叉匹配,返回所有特征匹配结果;True表示只返回互为最佳匹配的结果,删除非一致配对的结果。
  • ⑸ 对于SIFT、SURF描述符,推荐选择欧氏距离L1和L2范数;对于ORB、BRISK、BRIEF描述符,推荐选择汉明距离NORM_HAMMING;对于ORB描述符,当WTA_K=3或4时,推荐使用汉明距离NORM_HAMMING2。

3. 绘制匹配关系函数 cv.drawMatches

在OpenCV中还提供了函数cv.drawMatches,绘制从两个图像中找到的关键点匹配项。

函数原型

cv.drawMatches(img1, keypoints1, img2, keypoints2, matches1to2, outImg[, matchColor, singlePointColor, matchesMask, flags) → outImage
cv.drawMatchesKnn(img1, keypoints1, img2, keypoints2, matches1to2, outImg[, matchColor, singlePointColor, matchesMask, flags] → outImage

参数说明

  • img1、img2:输入图像1、输入图像2。
  • keypoints1、keypoints2:输入图像1、输入图像2中的关键点。
  • matches1to2:绘制的匹配关系,列表,列表元素是匹配结果DMatch。
  • outImg:输出匹配图像,包括图像1、图像2和表示匹配关系的连线。
  • flags:绘制内容的选项标志。
    • DRAW_MATCHES_FLAGS_DEFAULT,默认值,创建匹配输出图像,包括输入图像、匹配关系和单个的关键点。
    • DRAW_MATCHES_FLAGS_NOT_DRAW_SINGLE_POINTS,不绘制没有匹配成功的单个关键点。

4. 例程:特征匹配之暴力匹配(BFMatcher)

本例程先使用SIFT算法特征检测和特征描述,再使用BFMatcher进行特征匹配。例程给出了使用交叉匹配和设置比较阈值筛选匹配结果的实现方法。

# 【1708】特征匹配之暴力匹配(BFMatcher)
import cv2 as cv
from matplotlib import pyplot as plt

if __name__ == '__main__':
    # (1) 读取参考图像
    imgRef = cv.imread("../images/Fig1703a.png", flags=1)
    refer = cv.cvtColor(imgRef, cv.COLOR_BGR2GRAY)  # 参考图像
    height, width = imgRef.shape[:2]  # 图片的高度和宽度
    # 读取或构造检测图像
    imgObj = cv.imread("../images/Fig1703b.png", flags=1)
    object = cv.cvtColor(imgObj, cv.COLOR_BGR2GRAY)  # 目标图像
    # (2) 构造 SIFT 对象,检测关键点,计算特征描述向量
    sift = cv.SIFT.create()  # sift 实例化对象
    kpRef, desRef = sift.detectAndCompute(refer, None)  # 参考图像关键点检测
    kpObj, desObj = sift.detectAndCompute(object, None)  # 检测图像关键点检测
    print("Keypoints: RefImg {}, ObjImg {}".format(len(kpRef), len(kpObj)))  # 2238/1675

    # (3) 特征点匹配,暴力匹配+交叉匹配筛选,返回最优匹配结果
    bf1 = cv.BFMatcher(crossCheck=True)  # 构造 BFmatcher 对象,设置交叉匹配
    matches = bf1.match(desRef, desObj)  # 对描述子 desRef, desObj 进行匹配
    # matches = sorted(matches, key=lambda x: x.distance)
    imgMatches1 = cv.drawMatches(imgRef, kpRef, imgObj, kpObj, matches[:300], None, matchColor=(0,255,0))
    print("(1) bf.match with crossCheck: {}".format(len(matches)))
    print(type(matches), type(matches[0]))
    print(matches[0].queryIdx, matches[0].trainIdx, matches[0].distance)  # DMatch 的结构和用法

    # (4) 特征点匹配,KNN匹配+比较阈值筛选
    bf2 = cv.BFMatcher()  # 构造 BFmatcher 对象
    matches = bf2.knnMatch(desRef, desObj, k=2)  # KNN匹配,返回最优点和次优点 2个结果
    goodMatches = []  # 筛选匹配结果
    for m, n in matches:  # matches 是元组
        if m.distance < 0.7 * n.distance:  # 最优点距离/次优点距离 之比小于阈值0.7
            goodMatches.append([m])  # 保留显著性高度匹配结果
    # good = [[m] for m, n in matches if m.distance<0.7*n.distance]  # 单行嵌套循环遍历
    imgMatches2 = cv.drawMatchesKnn(imgRef, kpRef, imgObj, kpObj, goodMatches, None, matchColor=(0,255,0))
    print("(2) bf.knnMatch:{}, goodMatch:{}".format(len(matches), len(goodMatches)))
    print(type(matches), type(matches[0]), type(matches[0][0]))
    print(matches[0][0].distance)

    plt.figure(figsize=(9, 6))
    plt.subplot(211), plt.axis('off'), plt.title("1. BF MinDistMatch")
    plt.imshow(cv.cvtColor(imgMatches1, cv.COLOR_BGR2RGB))
    plt.subplot(212), plt.axis('off'), plt.title("2. BF KnnMatch")
    plt.imshow(cv.cvtColor(imgMatches2, cv.COLOR_BGR2RGB))
    plt.tight_layout()
    plt.show()

运行结果

Keypoints: RefImg 1058, ObjImg 1015
(1) bf.match with crossCheck: 363
(2) bf.knnMatch:1058, goodMatch:123

程序说明
⑴ 对不同方位和距离拍摄的照片,用SIFT算法进行特征检测和构造特征描述符,特征匹配结果如图17-10所示。
⑵ 子图1是暴力匹配的结果,使用交叉测试进行了筛选。子图2是K近邻匹配的结果,使用阈值测试进行了筛选。图中的连线表示匹配的特征点,单独圆圈表示不匹配的特征点。
⑶ 子图1和子图2的大部分匹配结果都是正确的,但也都存在少数错误的匹配。子图2中的匹配准确率比子图1更高。
⑷ 参考图像中检测出1058个特征点,检测图像中检测出1015个特征点。使用交叉配对测试,得到363组配对;使用比较阈值测试,得到123组配对。阈值测试方法更加严格,准确性也更高。


在这里插入图片描述



【本节完】

版权声明:
youcans@xupt 原创作品,转载必须标注原文链接:(https://blog.csdn.net/youcans/article/details/128253435)
Copyright 2022 youcans, XUPT
Crated:2022-12-10

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

基于统一空间方法的动态切换拥挤(DSC)DSC-MOAGDE算法附matlab代码

✅作者简介&#xff1a;热爱科研的Matlab仿真开发者&#xff0c;修心和技术同步精进&#xff0c;matlab项目合作可私信。 &#x1f34e;个人主页&#xff1a;Matlab科研工作室 &#x1f34a;个人信条&#xff1a;格物致知。 更多Matlab仿真内容点击&#x1f447; 智能优化算法 …

Python编程零基础如何逆袭成为爬虫实战高手之《WIFI破解》(甩万能钥匙十条街)爆赞爆赞~

导语 Hello&#xff0c;大家好呀&#xff01;我是木木子吖&#xff5e; 一个集美貌幽默风趣善良可爱并努力码代码的程序媛一枚。 听说关注我的人会一夜暴富发大财哦~ &#xff08;哇哇哇 这真的爱&#x1f60d;&#x1f60d;&#xff09; 所有文章完整的素材源码都在&#…

dreamweaver网页大作业 我的家乡——南京玄武湖旅游攻略(4页) 学生网页设计作业源码

家乡旅游景点网页作业制作 网页代码运用了DIV盒子的使用方法&#xff0c;如盒子的嵌套、浮动、margin、border、background等属性的使用&#xff0c;外部大盒子设定居中&#xff0c;内部左中右布局&#xff0c;下方横向浮动排列&#xff0c;大学学习的前端知识点和布局方式都有…

Java项目写好了,如何部署上线?看这篇文章吧

嗨&#xff0c;各位小伙伴大家好&#xff0c;你有没有想壹哥呀&#xff1f;前几天有小伙伴给壹哥留言&#xff0c;说自己的项目写好了&#xff0c;想把项目部署到服务器上&#xff0c;这个该怎么实现呢&#xff1f;那么针对这个问题&#xff0c;今天壹哥就带大家走一遍完整的项…

【云计算与大数据计算】大数据物理、集成、安全架构及阿里云飞天系统架构讲解(超详细)

一、物理架构 物理架构 - 企业大数据系统的各层次系统最终要部署到主机节点中,这些节点通过网络连接成 为一个整体,为企业的大数据应用提供物理支撑 &#xff0c;企业大数据系统由多个逻辑层组成&#xff0c;多个逻辑层可以映射到一个物理节点上&#xff0c;也可以映射到多个物…

nacos--基础--1.1--理论--介绍

nacos–基础–1.1–理论–介绍 1、介绍 是阿里的一个开源产品致力于帮助您发现、配置和管理微服务 1.1、参考资料 https://nacos.io/zh-cn/docs/what-is-nacos.html1.2、功能 服务发现中心&#xff1a;动态服务发现服务注册中心&#xff1a;管理注册服务服务配置中心&#…

行为管理(锐捷智慧教室)

大家好&#xff0c;我是小杜&#xff0c;被师傅“强制”休息两天&#xff0c;感觉整个人都升华了&#xff0c;精神满满的&#xff0c;看来还是需要劳逸结合&#xff0c;一味的高强度精神亢奋的情况下其实是事倍功半......。随着学习的深入&#xff0c;师傅也带着我对公司的业务…

PCIe Dma coherent

目录 1.PCIe Dma coherent前言 2.DMA与Cache 的一致性 2.1一致性问题 2.2Coherent DMA buffers 一致性 2.3DMA Streaming Mapping 流式DMA映射 2.4dma_alloc_coherent的例外 2.5SMMU | IOMMU 3.Linux 内核中 DMA 及 Cache 分析 3.1arm 3.2DMA ZONE 3.3DMA ZONE 的内…

南昌市-中安协-安防工程企业设计施工维护能力评价

安防工程企业设计、施工、维护能力评价是指中国安全防范产品行业协会从本行业实际出发&#xff0c;制定评价标准和实施办法&#xff0c;确定其能力等级&#xff0c;并颁发证书的活动。安防工程企业&#xff08;以下称企业&#xff09;设计、施工、维护能力&#xff08;以下称能…

以太网 传统STP生成树简介、STP工作方式简单介绍

2.10.0 以太网 传统STP生成树&#xff08;简介、工作方式&#xff09; 作用&#xff1a; STP&#xff08;Spanning Tree Prortoco&#xff09;生成树协议&#xff0c;它的出现解决了交换机网络环路的问题。 交换机网络中收到BUM帧的时候&#xff0c;将会进行泛洪的操作&…

CSS 父选择器,:has()

在CSS Selectors 4规范中&#xff0c;CSS 引入了一个名为 的新选择器:has()&#xff0c;它最终让我们可以选择父级。这意味着我们可以选择具有特定元素的父元素。目前Safari和Chrome105已经支持。 父选择器如何在 CSS 中工作 在 CSS 中&#xff0c;如果我们想要选择某些东西&a…

【Pygame小游戏】史上最全:《唐诗三百首》合集,每一首都是精华,果断收藏~(学诗+锻炼记忆+Python诗句填空小程序上线啦)

前言 岁岁年龄岁岁心&#xff0c;不负时光不负卿 哈喽&#xff01;我是你们的栗子同学&#xff0c;今天给大家来点儿有趣的—— 有句话说&#xff1a;“读史使人明智&#xff0c;读诗使人灵秀。”唐诗本来就是中国文化的绚丽瑰宝&#xff0c;是每个人都 该学习的人生必修课。…

蚂蚁三面遭分布式血虐,意外收获史诗级分布式笔记手册,从基础到进阶收获满满

学习分布式系统设计的难题在于&#xff0c;这个过程存在一个环境障碍&#xff0c;工作中只有一些中大规模的互联网企业&#xff0c;才有开发大规模分布式系统的场景和需求。这就造成目前只有少数身在一线互联网公司的架构师和开发者&#xff0c;才有机会接触并掌握分布式系统设…

Spring Security入门学习

认识Spring Security Spring Security 是为基于 Spring 的应用程序提供声明式安全保护的安全性框架。Spring Security 提供了完整的安全性解决方案&#xff0c;它能够在 Web 请求级别和方法调用级别处理身份认证和授权。因为基于 Spring 框架&#xff0c;所以 Spring Security…

树莓派Pico开发板与大功率MOSFET/IGBT器件驱动控制24V直流电机技术实践

摘要&#xff1a;本文在介绍MOSFET器件和IGBT器件作为电子开关基本原理的基础上&#xff0c;讲述了Pico与MOSFET&IGBT器件驱动控制24V直流电机硬件接口技术&#xff0c;最后给出了Pico开发板GP15端口控制24V直流电机启停的MicroPython测试程序。 一、实验设备和元器件清单 …

[附源码]Nodejs计算机毕业设计基于Java的智慧停车软件Express(程序+LW)

该项目含有源码、文档、程序、数据库、配套开发软件、软件安装教程。欢迎交流 项目运行 环境配置&#xff1a; Node.js Vscode Mysql5.7 HBuilderXNavicat11VueExpress。 项目技术&#xff1a; Express框架 Node.js Vue 等等组成&#xff0c;B/S模式 Vscode管理前后端分…

React 入门:实战案例 TodoList 对组件的 props 进行限制

文章目录安装 prop-types 库给组件的 props 添加限制给 Header 组件添加限制给 List 组件添加限制给 Item 组件添加限制验证 props 限制完整代码Header 组件完整代码List 组件完整代码Item 组件完整代码本文实现对组件的 props 进行属性的类型和必要性的限制。为什么要对 props…

双十二买什么数码产品比较值?入手超值的数码好物盘点

2022年双十二正式开启倒计时模式&#xff0c;最近看到很多人问什么数码产品值得入手。现如今&#xff0c;数码产品已经贯彻在我们生活的方方面面&#xff0c;在此&#xff0c;我来给大家盘点几款入手超值的数码好物&#xff0c;可以当个参考。 一、蓝牙耳机 推荐产品&#xf…

JUC(6) : LockSupport | 优雅的线程通信工具

一、前言 前文介绍了 CompletableFuture 和 线程池的几种对线程的管理方式后&#xff0c;本质上&#xff0c;通过这些工具&#xff0c;可以直接帮我们对线程进行很好的管理和运作&#xff0c;什么时间需要启动哪个线程&#xff0c;以及线程的执行顺序等。毕竟&#xff0c;线程…

视频监控在油气长输管道巡护管理的应用解决方案

一、方案背景 由于油气产地与消费中心位置的不一致性&#xff0c;常常需要采用长距离的油气管道运输。从偏僻的矿区到繁华的街市&#xff0c;管道架设的环境十分复杂&#xff0c;一旦发生危险&#xff0c;后果将不堪设想。因此&#xff0c;为确保管道安全运行&#xff0c;消除…