OpenCV ORB角点检测匹配和偏移计算
OpenCV ORB角点检测匹配和偏移计算
- 1. 简介
- 2. ORB角点检测匹配和偏移计算
- 2.1. 创建平移图片
- 2.2. ORB角点检测
- 2.3. ORB角点匹配
- 2.4. 计算变换矩阵
1. 简介
首先通过 cv2.ORB_create 创建ORB检测器 orb,
然后通过 orb.detectAndCompute 检测两张图片获得ORB角点,
接着通过匹配器 cv2.BFMatcher 进行配对,
最后通过 cv2.findHomography 计算变换矩阵。
2. ORB角点检测匹配和偏移计算
2.1. 创建平移图片
首先我们先创建一个平移图片作为两个比较的图片
from cv2 import cv2
import numpy as np# 读取图片文件
demo_file_path = 'img1.png'
img = cv2.imdecode(np.fromfile(demo_file_path, dtype=np.uint8), cv2.IMREAD_UNCHANGED)
cv2.imshow('origin img', img)# 平移变量
T_x, T_y = 10, 20# 旋转变量 0°
angles = 0
sin_phi, cos_phi = np.sin(np.radians(angles)), np.cos(np.radians(angles))# 构造仿射变换矩阵H 2*3
H = np.float32([[cos_phi, -sin_phi, T_x],[sin_phi, cos_phi, T_y]])
np.set_printoptions(suppress=True)
print(H)# 仿射变换
new_img = cv2.warpAffine(img, H, (img.shape[1], img.shape[0]))# 保存图片
cv2.imencode('.png', new_img)[1].tofile('img2.png')
cv2.imshow('new img', new_img)
cv2.waitKey(0)
平移x轴10个像素点,y轴20个像素点,其他不变,如下图所示:

仿射变换矩阵 H H H,这里纯平移,所以也是就平移矩阵,如下:
[[ 1. -0. 10.][ 0. 1. 20.]]
关于透视变换参考:《OpenCV 透视变换》
2.2. ORB角点检测
import cv2
import numpy as np# 读取两个连续图像
img1 = cv2.imread('img1.png')
img2 = cv2.imread('img2.png')# 初始化ORB检测器
orb = cv2.ORB_create(nfeatures=500)# 检测关键点和描述符
kp1, des1 = orb.detectAndCompute(img1, None)
kp2, des2 = orb.detectAndCompute(img2, None)# 显示ORB角点
keypoints_img1 = cv2.drawKeypoints(img1, kp1, None, color=(0,255,0), flags=0)
keypoints_img2 = cv2.drawKeypoints(img2, kp2, None, color=(0,255,0), flags=0)
cv2.imshow('Keypoints Image1', keypoints_img1)
cv2.imshow('Keypoints Image2', keypoints_img2)
首先通过 cv2.ORB_create 创建ORB检测器 orb,
然后通过 orb.detectAndCompute 检测两张图片获得ORB角点
然后通过 cv2.drawKeypoints 将角点可视化,如下图:

2.3. ORB角点匹配
# 创建匹配器
bf = cv2.BFMatcher(cv2.NORM_HAMMING, crossCheck=True)
matches = bf.match(des1, des2)# 根据匹配结果排序,取较优的50个
matches = sorted(matches, key = lambda x:x.distance)[:50]# 显示匹配关系
matches_img = cv2.drawMatches(img1, kp1, img2, kp2, matches, None, flags=2)
cv2.imshow('Matches Image', matches_img)
通过 cv2.BFMatcher 创建匹配器,其中有两个参数:
-
normType:它指定要使用的距离量度。
默认是 cv2.NORM_L2,对于SIFT,SURF 效果较佳
对于二进制字符串的描述子,比如ORB,BRIEF,BRISK等,应该用cv2.NORM_HAMMING(汉明距离度量)
使用,如果ORB检测器的 WTA_K 设置 3或者4,应该用cv2.NORM_HAMMING2 -
crossCheck:匹配器为每个查询描述符找到 k 个距离最近的匹配描述符;
默认为 False,为 True 时,只返回满足交叉验证条件的匹配结果。

2.4. 计算变换矩阵
# 提取匹配点
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)# 计算变换矩阵
H, mask = cv2.findHomography(src_pts, dst_pts, cv2.RANSAC, 5.0)
matchesMask = mask.ravel().tolist() # 可用于cv2.drawMatches可视化匹配关系的掩模
np.set_printoptions(suppress=True)
print(H)# 可视化变换结果
offset_img = cv2.warpPerspective(img1, H, (img1.shape[1], img1.shape[0]))
cv2.imshow('Offset Image', offset_img)cv2.waitKey(0)
cv2.destroyAllWindows()
提取匹配点两个图片的src_pts和dst_pts,通过 cv2.findHomography 计算变换矩阵
可以看到计算出来的透视变换矩阵可以看到结果为x轴平移,与实际一致
[[ 1. 0. 10.][-0. 1. 20.][-0. 0. 1.]]
那么,显示变换结果也将一致,如下图:

谢谢
相关文章:
OpenCV ORB角点检测匹配和偏移计算
OpenCV ORB角点检测匹配和偏移计算 1. 简介2. ORB角点检测匹配和偏移计算2.1. 创建平移图片2.2. ORB角点检测2.3. ORB角点匹配2.4. 计算变换矩阵 1. 简介 首先通过 cv2.ORB_create 创建ORB检测器 orb, 然后通过 orb.detectAndCompute 检测两张图片获得ORB角点&…...
图文详解ChatGPT-o1完成论文写作的全流程
学境思源,一键生成论文初稿: AcademicIdeas - 学境思源AI论文写作 本月中旬OpenAI发布了OpenAI o1系列新的AI模型。 据OpenAI介绍,这些模型旨在花更多时间思考后再做出反应,就像人一样。通过训练,它们学会改进思维过…...
在线体验Sketch中文版,免费下载即刻上手!
Sketch是一款轻量而高效的矢量设计工具,助力全球设计师创造了诸多惊艳作品。安装Sketch的优势主要体现在其矢量编辑、控件和样式功能上。而下载安装“Sketch中文版”即时设计同样出色,它作为一站式设计平台,功能更全面。即时设计拥有纯中文的…...
Redis——缓存
目录 前言 一、缓存基本概念 1.概念 2.二八定律 二、使用 Redis 作为缓存 三、缓存的更新策略 1.定期生成 2.实时生成 四、Redis 内存淘汰机制 1.通用淘汰策略 (1)FIFO (2)LRU (3)LFU &#…...
RHCSA笔记三
第二章 linux中执行命令 命令格式 命令分为两类 内置命令:由 shell 程序自带的命令 外部命令:有独立的可执行程序文件,文件名即命令名 格式 主命令 参数 操作对象 # 注意: 下面是对于命令的语法的一些符号的说明࿱…...
【python】sorted() list.sort()
文章目录 sorted()和list.sort()sorted 函数sorted()根据键对字典排序根据字典的键排序根据字典的值排序将排序结果转换回字典 list.sort() 方法总结 keylambda student: student[age] sorted()和list.sort() 在Python中,sorted 函数和 list.sort() 方法都可以用来…...
训练集alpaca、sharegpt格式
LLaMA-Factory微调支持的格式 支持 alpaca 格式和 sharegpt 格式的数据集。 Alpaca格式 格式: [{"instruction": "人类指令(必填)","input": "人类输入(选填)","output": "模型回答(必填)","syst…...
Hive的数据存储格式
目录 一、前言 二、存储格式 2.1、文本格式(TextFile) 2.1.1、定义与特点 2.1.2、存储与压缩 2. 1.3、使用场景 2.2、行列式文件(ORCFile) 2.2.1、ORC的结构 2.2.2、ORC的数据类型 2.2.3、ORC的压缩格式 2.2.3、ORC存储…...
Linux Rsyslog 配置
1、Linux Rsyslog客户端配置 1)安装rsyslog yum install rsyslog 2)启用TCP或UDP传输 vim /etc/rsyslog.conf# Provides UDP syslog reception #若启用UDP进行传输,则取消下面两行的注释 #$ModLoad imudp #$UDPServerRun 514# Provide…...
python实现放烟花效果庆祝元旦
马上就要2025年元旦啦,提前祝大家新年快乐 完整代码下载地址:https://download.csdn.net/download/ture_mydream/89926458...
模型训练识别手写数字(二)
模型训练识别手写数字(一)使用手写数字图像进行模型测试 一、生成手写数字图像 1. 导入所需库 import cv2 import numpy as np import oscv2用于计算机视觉操作。 numpy用于处理数组和图像数据。 os用于文件和目录操作。 2. 初始化画布 canvas np.z…...
深入Vue2
frontend Vue2 学习内容参考 /在线运行 Element 学习内容参考 /视频教学 vue2 1. vue 实例 当一个 Vue 实例被创建时,它将 data 对象中的所有的 property 加入到 Vue 的响应式系统中 但是当使用Object.freeze(),会阻止修改现有的 property&#x…...
opencv-rust 系列3: Create_mask
前言: 这里只是opencv-rust自带示例的中文注解. 略微增加了一些代码也是我在调试时用到的. 调试方法可参见前文. 一. 这个程序还是有点难度的, 关键点在于: 创建了遮罩. 直接调用一个函数, 还是很简单的.窗口事件处理. 注册窗口回调函数, 用以处理鼠标事件进程同步和互斥锁. 为…...
Go语言初识
一、Go语言概述 Go语言是为了取代C和java的地位,既要保留C的简洁,也追求java的规模化开发 并行及分布式的支持,使得开发多核及多机器集群程序如同单机一样简单 Go语言从语言级别支持协程(goroutine, 轻量级线程),Go语言…...
Android Activity SingleTop启动模式使用场景
通知栏 当用户点击通知栏中的通知时,可以使用单顶启动模式来打开对应的活动,并确保只有一个实例存在。 简单集成极光推送 创建应用 获取appkey参数 切换到极光工作台 极光sdk集成 Project 根目录的主 gradle 配置 Module 的 gradle 配置 Jpush依赖配置 配置推送必须…...
PHP 代码执行相关函数
函数 说明 示例代码 ${} 用于复杂的变量解析,通常在字符串内用来解析变量或表达式。可以配合 eval 或其他动态执行代码的功能,用于间接执行代码。 eval(${flag}); eval() 用于执行一个字符串作为 PHP 代码。可以执行任何有效的 PHP 代码片段。没有…...
五周年,继续破浪前行
五周年,TapData 再一次带着自己的“乘风破浪”大队,在一个阳光明媚的日子里,把生日过在了海上。 头顶日升日落,这条属于全体 Tap-pers 的航船,再次校准航向,在船长的带领下,驶向下一个晴好的明…...
【操作系统】Linux之进程管理一
第1关:获取进程常见属性 ret.pidgetpid(); ret.ppidgetppid(); 第2关:进程创建操作-fork pid_t pid fork(); if(pid-1) printf("创建进程失败!"); else if(pid0) printf("Children"); else printf("Parent"); …...
C语言_数据在内存中的存储
1. 整数在内存中的存储 计算机中的整数有三种2进制表示方法 :原码、反码、补码。 三种表示方式均有符号位和数值位两个部分,最高一位的是符号位,剩下的都是数值位。符号位用“0”表示“正”,用“1”表示“负”。 正数的原、反、…...
华为原生鸿蒙操作系统:我国移动操作系统的新篇章
华为原生鸿蒙操作系统:我国移动操作系统的新篇章 引言 在移动操作系统领域,苹果iOS和安卓系统一直占据主导地位。然而,随着华为原生鸿蒙操作系统的正式发布,这一格局正在发生深刻变化。作为继苹果iOS和安卓系统后的全球第三大移动…...
在 Nginx Stream 层“改写”MQTT ngx_stream_mqtt_filter_module
1、为什么要修改 CONNECT 报文? 多租户隔离:自动为接入设备追加租户前缀,后端按 ClientID 拆分队列。零代码鉴权:将入站用户名替换为 OAuth Access-Token,后端 Broker 统一校验。灰度发布:根据 IP/地理位写…...
Java多线程实现之Callable接口深度解析
Java多线程实现之Callable接口深度解析 一、Callable接口概述1.1 接口定义1.2 与Runnable接口的对比1.3 Future接口与FutureTask类 二、Callable接口的基本使用方法2.1 传统方式实现Callable接口2.2 使用Lambda表达式简化Callable实现2.3 使用FutureTask类执行Callable任务 三、…...
Module Federation 和 Native Federation 的比较
前言 Module Federation 是 Webpack 5 引入的微前端架构方案,允许不同独立构建的应用在运行时动态共享模块。 Native Federation 是 Angular 官方基于 Module Federation 理念实现的专为 Angular 优化的微前端方案。 概念解析 Module Federation (模块联邦) Modul…...
《基于Apache Flink的流处理》笔记
思维导图 1-3 章 4-7章 8-11 章 参考资料 源码: https://github.com/streaming-with-flink 博客 https://flink.apache.org/bloghttps://www.ververica.com/blog 聚会及会议 https://flink-forward.orghttps://www.meetup.com/topics/apache-flink https://n…...
QT: `long long` 类型转换为 `QString` 2025.6.5
在 Qt 中,将 long long 类型转换为 QString 可以通过以下两种常用方法实现: 方法 1:使用 QString::number() 直接调用 QString 的静态方法 number(),将数值转换为字符串: long long value 1234567890123456789LL; …...
AI书签管理工具开发全记录(十九):嵌入资源处理
1.前言 📝 在上一篇文章中,我们完成了书签的导入导出功能。本篇文章我们研究如何处理嵌入资源,方便后续将资源打包到一个可执行文件中。 2.embed介绍 🎯 Go 1.16 引入了革命性的 embed 包,彻底改变了静态资源管理的…...
Unity | AmplifyShaderEditor插件基础(第七集:平面波动shader)
目录 一、👋🏻前言 二、😈sinx波动的基本原理 三、😈波动起来 1.sinx节点介绍 2.vertexPosition 3.集成Vector3 a.节点Append b.连起来 4.波动起来 a.波动的原理 b.时间节点 c.sinx的处理 四、🌊波动优化…...
用机器学习破解新能源领域的“弃风”难题
音乐发烧友深有体会,玩音乐的本质就是玩电网。火电声音偏暖,水电偏冷,风电偏空旷。至于太阳能发的电,则略显朦胧和单薄。 不知你是否有感觉,近两年家里的音响声音越来越冷,听起来越来越单薄? —…...
在QWebEngineView上实现鼠标、触摸等事件捕获的解决方案
这个问题我看其他博主也写了,要么要会员、要么写的乱七八糟。这里我整理一下,把问题说清楚并且给出代码,拿去用就行,照着葫芦画瓢。 问题 在继承QWebEngineView后,重写mousePressEvent或event函数无法捕获鼠标按下事…...
MySQL 主从同步异常处理
阅读原文:https://www.xiaozaoshu.top/articles/mysql-m-s-update-pk MySQL 做双主,遇到的这个错误: Could not execute Update_rows event on table ... Error_code: 1032是 MySQL 主从复制时的经典错误之一,通常表示ÿ…...
