[特征提取与匹配]基于Open CV使用SIFT提取特征,并使用FLANN完成单应性匹配

news2025/1/15 6:58:12

关于单应性

单应性:当一张图是另一张图的一个透视畸变时,在两张图中寻找彼此的一种情况

实现步骤

  1. 导入需要的库;
  2. 读取两张灰度图像作为匹配对象;
  3. 创建SIFT对象,用于检测SIFT特征点并计算描述子;
  4. 在两张图像中分别检测SIFT特征点,并计算每个特征点的描述子,即将其转换为若干长度固定的向量;
  5. 自定义参数执行基于FLANN的匹配。FLANN是一种快速最近邻搜索算法,可以在高维空间中快速搜索最相似的数据点。这里指定使用FLANN索引类型为KDTREE,并指定树的数量为5;
  6. 指定搜索参数,其中checks表示执行检查或者遍历的次数。checks越大,可以提供的精度也就越高,但是计算成本也就更高;
  7. 使用FlannBasedMatcher对象对两组SIFT描述子之间进行k近邻匹配,返回值为列表的列表,每个内部列表至少包含一个匹配项,且不超过k个匹配项,各匹配项从最佳(最短距离)到最差依次排序;
  8. 应用乘数为0.7的劳氏比率检验,剔除不稳定的匹配对。这是一种基于距离比值来剔除不稳定匹配对的方法,可以排除掉一些明显不合理的匹配对;
  9. 至少需要10个好的匹配点才能进行透视变换;
  10. 将good_matches中的特征点转换为numpy数组形式,并重塑为三维形式;
  11. 寻找单应性,计算变换矩阵M和掩模mask。cv2.findHomography方法可以将源图像中的四边形映射到目标图像中的四边形,从而计算出变换矩阵。其中RANSAC算法是一种随机抽样一致性算法,用于估计基础矩阵或单应性矩阵等模型参数;
  12. 在图像img1中绘制所有与img0匹配的线段。通过透视变换,可以将img0的四个角映射到img1中,并计算出新的四个角坐标dst_corners;
  13. 在图像img1中绘制由两个点(x0, y0)和(x1, y1)组成的线段,颜色为白色,粗细为3。这里使用cv2.line方法绘制线段;
  14. 显示绘制结果。

Code

import numpy as np
import cv2
from matplotlib import pyplot as plt

MIN_NUM_GOOD_MATCHES = 10

img0 = cv2.imread('other/B11643_6_15.png',
                  cv2.IMREAD_GRAYSCALE)
img1 = cv2.imread('other/B11643_6_16.png',
                  cv2.IMREAD_GRAYSCALE)

cv2.imshow("result", img0)
cv2.waitKey()

# Perform SIFT feature detection and description.
sift = cv2.xfeatures2d.SIFT_create()
kp0, des0 = sift.detectAndCompute(img0, None)
kp1, des1 = sift.detectAndCompute(img1, None)

# Define FLANN-based matching parameters.
FLANN_INDEX_KDTREE = 1
index_params = dict(algorithm=FLANN_INDEX_KDTREE, trees=5)
search_params = dict(checks=50)

# Perform FLANN-based matching.
flann = cv2.FlannBasedMatcher(index_params, search_params)
matches = flann.knnMatch(des0, des1, k=2)

# Find all the good matches as per Lowe's ratio test.
good_matches = []
for m, n in matches:
    if m.distance < 0.7 * n.distance:
        good_matches.append(m)

if len(good_matches) >= MIN_NUM_GOOD_MATCHES:
    src_pts = np.float32(
        [kp0[m.queryIdx].pt for m in good_matches]).reshape(-1, 1, 2)
    dst_pts = np.float32(
        [kp1[m.trainIdx].pt for m in good_matches]).reshape(-1, 1, 2)

    M, mask = cv2.findHomography(src_pts, dst_pts, cv2.RANSAC, 5.0)
    mask_matches = mask.ravel().tolist()

    h, w = img0.shape
    src_corners = np.float32(
        [[0, 0], [0, h-1], [w-1, h-1], [w-1, 0]]).reshape(-1, 1, 2)
    dst_corners = cv2.perspectiveTransform(src_corners, M)
    dst_corners = dst_corners.astype(np.int32)

    # Draw the bounds of the matched region based on the homography.
    num_corners = len(dst_corners)
    for i in range(num_corners):
        x0, y0 = dst_corners[i][0]
        if i == num_corners - 1:
            next_i = 0
        else:
            next_i = i + 1
        x1, y1 = dst_corners[next_i][0]
        cv2.line(img1, (x0, y0), (x1, y1), 255, 3, cv2.LINE_AA)

    # Draw the matches that passed the ratio test.
    img_matches = cv2.drawMatches(
        img0, kp0, img1, kp1, good_matches, None,
        matchColor=(0, 255, 0), singlePointColor=None,
        matchesMask=mask_matches, flags=2)

    # Show the homography and good matches.
    plt.imshow(img_matches)
    plt.show()
else:
    print("Not enough matches good were found - %d/%d" % \
          (len(good_matches), MIN_NUM_GOOD_MATCHES))

输出

result

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

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

相关文章

提效篇 |当项目紧急入场,如何先测量后校正?

施工队进场后&#xff0c;设计院还没交桩怎么办&#xff1f; 部分工程由于设计与施工间隔时间较久&#xff0c;导致控制点被破坏、复测未通过怎么办&#xff1f; 工期紧张&#xff0c;难道只能干等吗&#xff1f; 答案是&#xff1a;先测量后校正&#xff01;与常规RTK作业不…

tensorflow基础

tensorflow基础 &#xff08;一&#xff09;编程模型&#xff08;1&#xff09;编程模型中的运行机制&#xff08;2&#xff09;编写hello world程序&#xff08;3&#xff09;使用注入机制进行代码编写&#xff08;4&#xff09;保存和载入模型的方法介绍&#xff08;4.1&…

代码随想录|day58|单调栈part01 ● 739. 每日温度 ● 496.下一个更大元素 I

739. 每日温度 链接&#xff1a;代码随想录 今天正式开始单调栈&#xff0c;这是单调栈一篇扫盲题目&#xff0c;也是经典题。 大家可以读题&#xff0c;思考暴力的解法&#xff0c;然后在看单调栈的解法。 就能感受出单调栈的巧妙 fvfdvsf fdfd ddf fdd fd fsd 496.下一个更…

轻量级服务器nginix:如何实现Spring项目的负载均衡

这里写目录标题 一 生成war包并给数据库导入数据1.1生成war包1.2 向数据库中导入数据 二 启动Tomcat三 配置负载均衡并启动Nginx1.cent121这台虚拟机上2.检测两个tomcat的运行状态3.配置nginx4.启动4.1 nginx报错4.2 成功启动项目 四 命令总结 一 生成war包并给数据库导入数据 …

docker和k8s基础介绍

一 Docker介绍 1.1 docker是什么 Docker 是一个开源项目&#xff0c; 诞生于 2013 年初&#xff0c;最初是 dotCloud 公司内部的一个业余项目。它基于 Google 公司推出的 Go 语言实现。 项目后来加入了 Linux 基金会&#xff0c;遵从了 Apache 2.0协议&#xff0c; 项目代码在…

SQL——索引

&#x1f4a1; 索引 在关系型数据库中&#xff0c;索引是一种单独的、物理上的对数据库表中的一列或多列的值进行排序的一种存储结构&#xff0c;他是某个表中的一列或着若干列值的集合和相应的指向表中物理标识这些值的数据页的逻辑指针清单&#xff08;类似于图书目录&#x…

RF技术设计的机械数码一体化防盗锁

机械数码一体化防盗锁在传统锁具的基础上增加了一个受控的弹子&#xff0c;只能通过设置过的合法钥匙开启&#xff0c;并且增加了防盗报警功能。本文介绍了基于PIC单片机、RF技术和无线数据传输技术的机械数码一体化防盗锁的设计。 引言 机械锁和数码锁是我们日常生活中最常见的…

CDGA|数据监管越来越严,数据治理发展何去何从?

尽管数据监管越来越严格&#xff0c;但仍然存在许多机会。事实上&#xff0c;数据监管的加强可能会促进金融科技行业更好地运用数据&#xff0c;激发金融科技行业更多的创新和合作,创造更多的价值和机会。 推动金融机构重视数据安全和隐私保护 促使他们采取更严格的安全措施&a…

Ueditor 富文本编辑器 插入 m3u8 和 mp4 视频(PHP)

当前环境&#xff1a;PHP、Ueditor的版本是1.4.3 新的需求是&#xff0c;需要在Ueditor 富文本编辑器中&#xff0c;插入视频播放&#xff0c;并且视频格式有MP4&#xff0c;也有M3U8。 百度编辑器默认的是embed&#xff0c;需要修改下配置。 ueditor.all.js和 ueditor.confi…

C++vector的动态扩容,为何是1.5倍或者是2倍

1. vector如何进行扩容 当插入元素时&#xff0c;如果size capacity&#xff0c;触发扩容机制。 拷贝元素释放旧空间 2. 如何避免扩容导致效率低 在插入前&#xff0c;预估好vector的容量&#xff0c;通常使用reserve。如果没有reserve&#xff0c;边插边扩容&#xff0c;…

ROS学习7:ROS机器人导航仿真

【Autolabor初级教程】ROS机器人入门 1. 概述 在 ROS 中机器人导航 (Navigation) 由多个功能包组合实现&#xff0c;ROS 中又称之为导航功能包集&#xff0c;关于导航模块&#xff0c;官方介绍如下 一个二维导航堆栈&#xff0c;它接收来自里程计、传感器流和目标姿态的信息&a…

汽车智能化「出海」红利

在高阶智能座舱中&#xff0c;车载导航产品作为与用户体验息息相关的模块之一&#xff0c;同样也进入了升级迭代周期。 基于高精度地图渲染、高精度定位算法、AR等技术的车道级导航、AR导航等产品快速上车&#xff0c;但同时随着人机交互多模发展以及3D沉浸式用户体验需求趋势下…

DataX-在Windows上实现postgresql同步数据到mysql

场景 DataX-阿里开源离线同步工具在Windows上实现Sqlserver到Mysql全量同步和增量同步: DataX-阿里开源离线同步工具在Windows上实现Sqlserver到Mysql全量同步和增量同步_霸道流氓气质的博客-CSDN博客 在上面实现sqlserver到mysql的数据同步之后&#xff0c;如果要实现postg…

FPGA/Verilog HDL/AC620零基础入门学习——8*8同步FIFO实验

实验要求 该项目主要实现一个深度为8、位宽为8bit的同步FIFO存储单元。模块功能应包括读控制、写控制、同时读写控制、FIFO满状态、FIFO空状态等逻辑部分。 该项目由一个功能模块和一个testbench组成。其中功能模块的端口信号如下表所示。 提示&#xff1a; &#xff08;1&a…

Sqoop 从入门到精通

Sqoop Sqoop 架构解析 概述 Sqoop是Hadoop和关系数据库服务器之间传送数据的一种工具。它是用来从关系数据库如&#xff1a;MySQL&#xff0c;Oracle到Hadoop的HDFS&#xff0c;并从Hadoop的文件系统导出数据到关系数据库。 传统的应用管理系统&#xff0c;也就是与关系型数…

【微服务笔记24】微服务组件之Sleuth + Zipkin实现服务调用链路追踪功能

这篇文章&#xff0c;主要介绍微服务组件之Sleuth Zipkin实现服务调用链路追踪功能。 目录 一、Sleuth链路追踪 1.1、什么是Sleuth 1.2、Sleuth专业术语 &#xff08;1&#xff09;Span &#xff08;2&#xff09;Trace &#xff08;3&#xff09;工作原理 1.3、Sleuth…

月薪15K必会技术,如何从0到1学习性能测试,5个操作安排的明明白白

目录 【开幕】武林秘籍惊现江湖 【第一幕】该不该预测一个初始值&#xff1f; 【第二幕】从单线程开始 【第三幕】用命令行形式跑性能测试&#xff0c;然后观察机器性能。 【第四幕】控制吞吐&#xff01;控制吞吐&#xff01;控制吞吐&#xff01; 【第五幕】武林秘籍重…

10 dubbo源码学习_线程池

1. 线程模型&线程池介绍1.1 线程池1.2 线程模型 2. 线程池源码分析2.1 FixedThreadPool2.2 CachedThreadPool2.3 LimitedThreadPool 3. 线程模型源码3.1 AllDispatcher3.2 DirectDispatcher3.3 MessageOnlyDispatcher3.4 ExecutionDispatcher3.5 ConnectionOrderedDispatch…

Visual Studio C# WinForm开发入门(6):TreeView 控件使用

TreeView控件用树显示节点层次。 例如&#xff1a;顶级目录是根(C:)&#xff0c;C盘下的每个子目录都是子节点&#xff0c;而每个子目录又都有自己的子节点 TreeView属性和方法&#xff1a; 属性说明CheckBoxes表示节点旁边是否出现复选框ImageList指定一个包含节点图标的Imag…

Spring Cloud Gateway 服务网关的部署与使用详细介绍

为什么需要服务网关 传统的单体架构中只需要开放一个服务给客户端调用&#xff0c;但是微服务架构中是将一个系统拆分成多个微服务&#xff0c;如果没有网关&#xff0c;客户端只能在本地记录每个微服务的调用地址&#xff0c;当需要调用的微服务数量很多时&#xff0c;它需要…