当前位置: 首页 > news >正文

python数字图像处理基础(九)——特征匹配

目录

      • 蛮力匹配(ORB匹配)
      • RANSAC算法
      • 全景图像拼接

蛮力匹配(ORB匹配)

Brute-Force匹配非常简单,首先在第一幅图像中选取一个关键点然后依次与第二幅图像的每个关键点进行(描述符)距离测试,最后返回距离最近的关键点.

对于BF匹配器,首先我们必须使用**cv2.BFMatcher()**创建 BFMatcher 对象。它需要两个可选的参数:

  • normType:它指定要使用的距离测量,默认情况下,它是cv2.NORM_L2,它适用于SIFT,SURF等(cv2.NORM_L1也在那里)。对于基于二进制字符串的描述符,如ORB,BRIEF,BRISK等,应使用cv2.NORM_HAMMING,使用汉明距离作为度量,如果ORB使用WTA_K == 3or4,则应使用cv2.NORM_HAMMING2
  • crossCheck:默认值为False。如果设置为True,匹配条件就会更加严格,只有到A中的第i个特征点与B中的第j个特征点距离最近,并且B中的第j个特征点到A中的第i个特征点也是最近时才会返回最佳匹配,即这两个特征点要互相匹配才行

两个重要的方法是BFMatcher.match()BFMatcher.knnMatch(), 第一个返回最佳匹配, 第二种方法返回k个最佳匹配,其中k由用户指定.

使用cv2.drawMatches()来绘制匹配的点,它会将两幅图像先水平排列,然后在最佳匹配的点之间绘制直线。如果前面使用的BFMatcher.knnMatch(),现在可以使用函数cv2.drawMatchsKnn为每个关键点和它的个最佳匹配点绘制匹配线。如果要选择性绘制就要给函数传入一个掩模.

一对一匹配 BFMatcher.match()

import numpy as np
import cv2
from matplotlib import pyplot as pltimg1 = cv2.imread('./image/girl1.jpg')
img2 = cv2.imread('./image/girl2.jpg')sift = cv2.SIFT_create()# kp代表特征点 des每个点对应特征向量
kp1, des1 = sift.detectAndCompute(img1, None)
kp2, des2 = sift.detectAndCompute(img2, None)bf = cv2.BFMatcher(crossCheck=True)  # 可选对象crossCheck# 1对1匹配
matches = bf.match(des1, des2)
matches = sorted(matches, key=lambda x: x.distance)  # 排序,通过距离来度量img3 = cv2.drawMatches(img1, kp1, img2, kp2, matches[:30], None, flags=2)  # matches[:10] 距离前十的给显示出来,即显示十条匹配线cv2.imshow('img', img3)
cv2.waitKey(0)
cv2.destroyAllWindows()

k对最佳匹配 BFMatcher.knnMatch()

import numpy as np
import cv2
from matplotlib import pyplot as pltimg1 = cv2.imread('./image/girl1.jpg')
img2 = cv2.imread('./image/girl2.jpg')sift = cv2.SIFT_create()# kp代表特征点 des每个点对应特征向量
kp1, des1 = sift.detectAndCompute(img1, None)
kp2, des2 = sift.detectAndCompute(img2, None)# k对最佳匹配
bf = cv2.BFMatcher()
matches = bf.knnMatch(des1, des2, k=2)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)cv2.imshow('img', img3)
cv2.waitKey(0)
cv2.destroyAllWindows()

RANSAC算法

蛮力匹配是一种简单而直观的匹配方法,适用于小规模的特征点匹配。通过比较所有可能的特征点对,找到最佳匹配。而RANSAC算法则通过随机采样和一致性检验,从包含噪声的数据中估计出正确的模型参数,对于一些存在噪声和异常值的情况,RANSAC能够更稳健地估计模型。

利用RANSAC算法计算变换矩阵

RANSAC是"RANdom SAmple Consensus"(随机一致采样)的缩写。该方法是用来找到正确模型来拟合带有噪声数据的迭代方法。给定一个模型,例如点集之间的单应性矩阵。基本的思想是:数据中包含正确的点和噪声点,合理的模型应该能够在描述正确数据点的同时摒弃噪声点。

此外还有ORB匹配、SIFT的特征匹配、基于FLANN的匹配器的匹配,等等

全景图像拼接

全景图像拼接是将多张图像拼接成一张全景图的任务。在这个过程中,特征点匹配和单应性矩阵估计是关键的步骤。你提到的使用SIFT找到特征点,并通过单应性矩阵将图像进行变换,是一种常见的方法。这样可以在不同视角或位置拍摄的图像中找到对应的特征点,从而实现拼接。

通过SIFT找特征点

关于单应性矩阵(H矩阵):

利用两个图像中至少四个特征点能够求解一个单应性矩阵(homography matrix),然后用这个单应性矩阵能够将图像1中的某个坐标变换到图像2中对应的位置。然而,矩阵的推导是来自于相机在不同位姿拍摄同一个三维平面,所以使用opencv计算单应性矩阵的时候前提是两个图像对应区域必须是同一平面。

当进行全景图像拼接时,常常需要使用RANSAC算法估计单应性矩阵。下面是一个简单的示例代码,其中包括特征点匹配、RANSAC算法和全景图像拼接的步骤。

import cv2
import numpy as npdef find_keypoints_and_descriptors(image):# 使用SIFT算法找到图像的关键点和描述符sift = cv2.SIFT_create()kp, des = sift.detectAndCompute(image, None)return kp, desdef match_keypoints(des1, des2):# 使用BFMatcher进行特征点匹配bf = cv2.BFMatcher()matches = bf.knnMatch(des1, des2, k=2)# 使用比值测试排除不好的匹配good = []for m, n in matches:if m.distance < 0.75 * n.distance:good.append(m)return gooddef ransac_homography(matches, kp1, kp2, reproj_thresh=4.0):# 将匹配的关键点转换为numpy数组src_pts = np.float32([kp1[m.queryIdx].pt for m in matches]).reshape(-1, 1, 2)dst_pts = np.float32([kp2[m.trainIdx].pt for m in matches]).reshape(-1, 1, 2)# 使用RANSAC算法估计单应性矩阵H, mask = cv2.findHomography(src_pts, dst_pts, cv2.RANSAC, reproj_thresh)return Hdef stitch_images(image1, image2, H):# 将图像1进行透视变换,将其叠加到图像2上rows1, cols1 = image1.shape[:2]rows2, cols2 = image2.shape[:2]warp_img1 = cv2.warpPerspective(image1, H, (cols1 + cols2, rows2))warp_img1[:rows2, :cols2] = image2return warp_img1if __name__ == "__main__":# 读取两张图像img1 = cv2.imread('image1.jpg')img2 = cv2.imread('image2.jpg')# 找到关键点和描述符kp1, des1 = find_keypoints_and_descriptors(img1)kp2, des2 = find_keypoints_and_descriptors(img2)# 进行特征点匹配matches = match_keypoints(des1, des2)# 使用RANSAC估计单应性矩阵H = ransac_homography(matches, kp1, kp2)# 进行全景图像拼接result = stitch_images(img1, img2, H)# 显示拼接结果cv2.imshow('Panorama', result)cv2.waitKey(0)cv2.destroyAllWindows()

为了达到更好的拼接效果,可能需要使用更复杂的图像配准和融合技术。


相关文章:

python数字图像处理基础(九)——特征匹配

目录 蛮力匹配&#xff08;ORB匹配&#xff09;RANSAC算法全景图像拼接 蛮力匹配&#xff08;ORB匹配&#xff09; Brute-Force匹配非常简单&#xff0c;首先在第一幅图像中选取一个关键点然后依次与第二幅图像的每个关键点进行&#xff08;描述符&#xff09;距离测试&#x…...

k8s的对外服务ingress

1、service的作用体现在两个方面 &#xff08;1&#xff09;集群内部&#xff1a;不断跟踪pod的变化&#xff0c;更新deployment中的pod对象&#xff0c;基于pod的ip地址不断变化的一种服务发现机制 &#xff08;2&#xff09;集群外部&#xff1a;类似于负载均衡器&#xff…...

[足式机器人]Part2 Dr. CAN学习笔记- Kalman Filter卡尔曼滤波器Ch05-3+4

本文仅供学习使用 本文参考&#xff1a; B站&#xff1a;DR_CAN Dr. CAN学习笔记 - Kalman Filter卡尔曼滤波器 Ch05-34 3. Step by step : Deriation of Kalmen Gain 卡尔曼增益/因数 详细推导4. Priori/Posterrori error Covariance Martix 误差协方差矩阵 3. Step by step :…...

关于前端面试中forEach方法的灵魂7问?

目录 前言 一、forEach方法支持处理异步函数吗&#xff1f; 二、forEach方法在循环过程中能中断吗&#xff1f; 三、forEach 在删除自己的元素后能重置索引吗&#xff1f; 四、forEach 的性能相比for循环哪个好&#xff1f; 五、使用 forEach 会不会改变原来的数组&#…...

AI小程序添加深度合成类目解决办法

基于文言一心和gpt等大模型做了一个ai助理小程序&#xff0c;在提交“一点AI助理”小程序时&#xff0c;审核如下&#xff1a; 失败原因1 审核失败原因 你好&#xff0c;你的小程序涉及提供提供文本深度合成技术 (如: AI问答) 等相关服务&#xff0c;请补充选择&#xff1a;深度…...

C/C++ BM6判断链表中是否有环

文章目录 前言题目解决方案一1.1 思路阐述1.2 源码 解决方案二2.1 思路阐述2.2 源码 总结 前言 做了一堆单链表单指针的题目&#xff0c;这次是个双指针题&#xff0c;这里双指针的作用非常明显。 题目 判断给定的链表中是否有环。如果有环则返回true&#xff0c;否则返回fal…...

【Java 设计模式】结构型之适配器模式

文章目录 1. 定义2. 应用场景3. 代码实现结语 适配器模式&#xff08;Adapter Pattern&#xff09;是一种结构型设计模式&#xff0c;用于将一个类的接口转换成客户端期望的另一个接口。这种模式使得原本由于接口不兼容而不能一起工作的类可以一起工作。在本文中&#xff0c;我…...

使用函数计算,数禾如何实现高效的数据处理?

作者&#xff1a;邱鑫鑫&#xff0c;王彬&#xff0c;牟柏旭 公司背景和业务 数禾科技以大数据和技术为驱动&#xff0c;为金融机构提供高效的智能零售金融解决方案&#xff0c;服务银行、信托、消费金融公司、保险、小贷公司等持牌金融机构&#xff0c;业务涵盖消费信贷、小…...

卷积和滤波对图像操作的区别

目录 问题引入 解释 卷积 滤波 问题引入 卷积和滤波是很相似的&#xff0c;都是利用了卷积核进行操作 那么他们之间有什么区别呢&#xff1f; 卷积&#xff1a;会影响原图大小 滤波&#xff1a;不会影响原图大小 解释 卷积 我们用这样一段代码来看 import torch.nn as …...

李沐深度学习-线性回归从零开始

# 核心Tensor&#xff0c;autograd import torch from IPython import display import numpy as np import random from matplotlib import pyplot as pltimport syssys.path.append(路径) from d2lzh_pytorch import * backward()函数:一次小批量执行完在进行反向传播 线性回归…...

CentOS 8.5 安装图解

特特特别的说明 CentOS发行版已经不再适合应用于生产环境&#xff0c;客观条件不得不用的话&#xff0c;优选7.9版本&#xff0c;8.5版本次之&#xff0c;最次6.10版本&#xff08;比如说Oracle 11GR2就建议在6版本上部署&#xff09;&#xff01; 引导和开始安装 选择倒计时结…...

好用的流程图工具

分享工作中常用的装逼工具 目前市面上的流程图或者思维导图工具挺多的&#xff0c;但是有的会限制使用数量或者收费&#xff0c;典型的有processon、Xmind&#xff0c;推荐今天Mermaid(官网)。 快速上手 中文教程&#xff1a;Mermaid 初学者用户指南 | Mermaid 中文网。我们选择…...

数据结构:链式栈

stack.h /* * 文件名称&#xff1a;stack.h * 创 建 者&#xff1a;cxy * 创建日期&#xff1a;2024年01月18日 * 描 述&#xff1a; */ #ifndef _STACK_H #define _STACK_H#include <stdio.h> #include <stdlib.h>typedef struct stack{int data…...

openssl3.2 - 官方demo学习 - mac - gmac.c

文章目录 openssl3.2 - 官方demo学习 - mac - gmac.c概述笔记END openssl3.2 - 官方demo学习 - mac - gmac.c 概述 使用GMAC算法, 设置参数(指定加密算法 e.g. AES-128-GCM, 设置iv) 用key执行初始化, 然后对明文生成MAC数据 官方注释给出建议, key, iv最好不要硬编码出现在程…...

HugggingFace 推理 API、推理端点和推理空间相关模型部署和使用以及介绍

HugggingFace 推理 API、推理端点和推理空间相关模型部署和使用以及介绍。 Hugging Face是一家开源模型库公司。 2023年5月10日&#xff0c;Hugging Face宣布C轮1亿美元融资&#xff0c;由Lux Capital领投&#xff0c;红杉资本、Coatue、Betaworks、NBA球星Kevin Durant等跟投…...

python的tabulate包在命令行下输出表格不对齐

用tabulate可以在命令行下输出表格。 from tabulate import tabulate# 定义表头 headers [列1, 列2, 列3]# 每行的内容 rows [] rows.append((张三,数学,英语)) rows.append((李四,信息科技,数学))# 使用 tabulate 函数生成表格 output tabulate(rows, headersheaders, tab…...

LLM之幻觉(二):大语言模型LLM幻觉缓减技术综述

LLM幻觉缓减技术分为两大主流&#xff0c;梯度方法和非梯度方法。梯度方法是指对基本LLM进行微调&#xff1b;而非梯度方法主要是在推理时使用Prompt工程技术。LLM幻觉缓减技术&#xff0c;如下图所示&#xff1a; LLM幻觉缓减技术值得注意的是&#xff1a; 检索增强生成&…...

C# 使用多线程,关闭窗体时,退出所有线程

this.Close(); 只是关闭当前窗口&#xff0c;若不是主窗体的话&#xff0c;是无法退出程序的&#xff0c;另外若有托管线程&#xff08;非主线程&#xff09;&#xff0c;也无法干净地退出&#xff1b;Application.Exit(); 强制所有消息中止&#xff0c;退出所有的窗体&…...

数据结构实验6:图的应用

目录 一、实验目的 1. 邻接矩阵 2. 邻接矩阵表示图的结构定义 3. 图的初始化 4. 边的添加 5. 边的删除 6. Dijkstra算法 三、实验内容 实验内容 代码 截图 分析 一、实验目的 1&#xff0e;掌握图的邻接矩阵的存储定义&#xff1b; 2&#xff0e;掌握图的最短路径…...

Spring Boot整合JUnit

引言 测试是软件开发过程中不可或缺的一环&#xff0c;而JUnit作为Java生态中最流行的测试框架之一&#xff0c;与Spring Boot的整合为开发者提供了一套强大的测试工具。本文将讨论Spring Boot整合JUnit的技术细节、最佳实践以及测试驱动开发&#xff08;TDD&#xff09;的优雅…...

uniapp写小程序实现清除缓存(存储/获取/移除/清空)

在uni-app中&#xff0c;可以使用uni.setStorageSync和uni.getStorageSync来进行数据的存储和获取。而移除缓存数据可以使用uni.removeStorageSync&#xff0c;清空缓存数据可以使用uni.clearStorageSync。 以下是使用示例&#xff1a; 存储数据&#xff1a; uni.setStorage…...

js菜单隐藏显示

1、树状结构对应的表: 2、生成menulist的SQL语句 select {"id":"MenuID","parent":"ParentID","FirstLvMenu":"FirstLvMenu", "text":"MenuName","url":"MenuUrl",&quo…...

学习Spring的第五天(Bean的依赖注入)

Bean的依赖注入有两种方式: 一 . 常规Bean的依赖注入 很简单,不过多赘述了,注意ref: 是构造函数或set方法的参数,一般为对象, value: 是构造函数或set方法的参数,一般为值. 看下图 1.1 下面来演示一下集合数据类型的关于Bean的依赖注入 1.1.1这是List的注入(演示泛型为Strin…...

GAN在图像数据增强中的应用

在图像数据增强领域&#xff0c;生成对抗网络&#xff08;GAN&#xff09;的应用主要集中在通过生成新的图像数据来扩展现有数据集的规模和多样性。这种方法特别适用于训练数据有限的情况&#xff0c;可以通过增加数据的多样性来提高机器学习模型的性能和泛化能力。 以下是GAN在…...

Git推送本地文件到仓库

1. 在 Gitee 上创建一个新的仓库&#xff1a; 登录到 Gitee&#xff08;https://gitee.com&#xff09;账号。在 Gitee 主页上选择 "新建仓库" 或类似选项。输入仓库名称和描述&#xff0c;并选择其他相关选项&#xff08;如公开/私有&#xff09;。确认创建仓库 …...

Django笔记(一):环境部署

目录 Python虚拟环境 安装virtualenv 创建环境 激活环境 关闭&#xff1a; 安装Django VSCode配置 Python插件 Django插件 解释器选择 Django部署 创建项目 创建app 创建模板 编写视图 编写路由 启动服务器 访问 Python虚拟环境 安装virtualenv pip i…...

用Pytorch实现线性回归模型

目录 回顾Pytorch实现步骤1. 准备数据2. 设计模型class LinearModel代码 3. 构造损失函数和优化器4. 训练过程5. 输出和测试完整代码 练习 回顾 前面已经学习过线性模型相关的内容&#xff0c;实现线性模型的过程并没有使用到Pytorch。 这节课主要是利用Pytorch实现线性模型。…...

WordPress模板层次与常用模板函数

首页&#xff1a; home.php index.php 文章页&#xff1a; single-{post_type}.php – 如果文章类型是videos(即视频)&#xff0c;WordPress就会去查找single-videos.php(WordPress 3.0及以上版本支持) single.php index.php 页面&#xff1a; 自定义模板 – 在WordPre…...

HarmonyOS应用开发者高级认证试题库(鸿蒙)

目录 考试链接&#xff1a; 流程&#xff1a; 选择&#xff1a; 判断 单选 多选 考试链接&#xff1a; 华为开发者学堂华为开发者学堂https://developer.huawei.com/consumer/cn/training/dev-certification/a617e0d3bc144624864a04edb951f6c4 流程&#xff1a; 先进行…...

系分备考计算机网络传输介质、通信方式和交换方式

文章目录 1、概述2、传输介质3、网络通信4、网络交换5、总结 1、概述 计算机网路是系统分析师考试的常考知识点&#xff0c;本篇主要记录了知识点&#xff1a;网络传输介质、网络通信和数据交换方式等。 2、传输介质 网络的传输最常见的就是网线&#xff0c;也就是双绞线&…...