opencv实战项目二十三:基于BEBLID描述符的特征点匹配实现表盘校正
提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档
文章目录
- 前言
- 一、特征点匹配介绍
- 二、特征点检测
- 三、特征描述符计算
- 四,描述符的匹配筛选
- 五,根据匹配结果映射图片
- 六,整体代码:
- 七,效果:
前言
在数字化时代,图像处理技术的应用日益广泛,其中表盘校正作为一项重要技术,在工业自动化、智能监控、时间同步等领域发挥着至关重要的作用。传统的表盘校正方法往往依赖于人工操作,不仅效率低下,而且精度难以保证。随着计算机视觉技术的飞速发展,基于算法的自动表盘校正技术逐渐成为研究热点。
本文将为您介绍一种基于BEBLID(Binary Efficient Boosted Local Identity Features)特征点匹配技术的表盘校正方法。BEBLID作为一种高效的特征描述符,以其独特的优势在众多特征点匹配算法中脱颖而出。本文将从原理、实现步骤以及实际应用等方面,详细阐述如何利用特征点匹配实现表盘的自动校正。
一、特征点匹配介绍
特征点匹配是计算机视觉中的一项核心技术,它能够帮助计算机识别和理解图像中的关键特征,进而实现图像间的对齐、拼接、物体识别等功能。特征点匹配的实现步骤主要包括以下几个方面:
-
特征点检测:首先,在图像中检测出具有显著特征的点。这些特征点可以是角点、边缘点或其他具有独特性质的点。常用的特征点检测算法有SIFT、SURF、ORB等。
-
特征描述符计算:对每个检测到的特征点,计算一个描述符,这个描述符是对特征点周围图像区域的一个定量描述。描述符应具有对图像变换(如缩放、旋转、光照变化等)的不变性。常见的描述符算法有SIFT描述符、SURF描述符、ORB描述符等。
-
特征点匹配:使用特征描述符,通过匹配算法在两幅图像之间找到对应的特征点对。匹配算法通常基于描述符之间的距离,距离越小,匹配度越高。常用的匹配算法有暴力匹配、FLANN等。
-
匹配筛选:由于匹配过程中可能会产生错误的匹配,因此需要筛选出可靠的匹配点。常用的方法包括最近邻距离比测试(NNDR)和RANSAC(随机抽样一致)算法。
-
变换模型估计:利用筛选后的匹配点对,估计一个变换模型(如仿射变换、透视变换等),这个模型描述了两幅图像之间的几何关系。
-
变换应用:将估计的变换模型应用到一幅图像上,以校正图像或实现图像间的对齐。
特征点匹配在计算机视觉领域具有广泛的应用,如图像拼接、三维重建、物体识别等。通过特征点匹配,计算机可以更好地理解图像内容,实现图像的自动处理和分析。
二、特征点检测
特征点检测是计算机视觉中的一个关键步骤,它涉及到在图像中识别出具有独特性质的点,这些点在图像的后续处理中起着至关重要的作用。特征点通常具有以下特点:
- 角点:这些点是图像中物体的边缘的交叉点,它们在图像中具有显著的梯度变化
- 边缘点:这些点位于物体的边缘上,它们的梯度值在某个方向上有一个显著的峰值。
- 中心点:这些点位于物体的中心,它们的梯度值在各个方向上都比较均匀。
- 局部极值点:这些点在局部区域内具有最高的梯度值。
常见的特征点检测的算法有常用的特征点检测算法有SIFT(尺度不变特征变换)、SURF(加速稳健特征)、ORB(Oriented FAST and Rotated BRIEF)等。本次使用的是ORB特征点检测法,
ORB(Oriented FAST and Rotated BRIEF)是一种特征点检测和描述符计算的算法,它是由David G. Lowe和Bruno Lepeletier在2011年提出的。ORB算法结合了FAST(Features from Accelerated Segment Test)和BRIEF(Binary Robust Independent Elementary Features)算法,旨在提供一种快速且稳健的特征检测和描述方法。ORB算法首先使用FAST角点检测器在图像中检测角点。FAST角点检测器通过检测图像中局部区域的边缘变化来确定角点。对于每个检测到的角点,ORB算法计算其方向,并将该方向信息存储在关键点描述中。ORB算法的主要优点是它的高计算效率和稳健性。由于它使用了二进制描述符,因此计算速度非常快。同时,由于BRIEF描述符对光照变化、旋转和尺度变化具有一定的不变性,ORB算法在实际应用中表现出了较好的稳健性。
在opencv中提供了其api为cv2.ORB_create(nfeatures=None, scaleFactor=1.2, nlevels=8, edgeThreshold=31, firstLevel=0, WTA_K=2, scoreType=cv2.ORB_FAST_SCORE, patchSize=31)
,函数介绍:
nfeatures:可选参数,用于指定要检测的最大特征点数量。如果设置为 None,则检测所有检测到的特征点。
scaleFactor:图像金字塔的缩放因子,用于在不同尺度下检测特征点。
nlevels:图像金字塔的层数。
edgeThreshold:用于FAST角点检测的边缘阈值。
firstLevel:图像金字塔的起始层数。
WTA_K:在描述符计算过程中,用于选择K个最佳描述符的参数。
scoreType:描述符的评分类型。
patchSize:用于描述符计算的局部区域大小。
本次只使用orb计算特征点,不计算描述符,故只设置nfeatures特征,并调用类中detect方法检测特征点,使用如下:
detector = cv2.ORB_create(10000)
kpts1 = detector.detect(img1, None)
三、特征描述符计算
描述符是图像特征点的量化表示,它通过对特征点周围图像区域的特征进行编码,从而能够在不依赖于原始图像数据的情况下识别和匹配特征点。描述符的主要目的是提供一种紧凑且信息丰富的表示,以便在图像匹配和识别任务中使用。
描述符的特点包括:
- 紧凑性:描述符通常是一个固定长度的向量,即使对于高分辨率的图像,其大小也非常小。
- 信息丰富:描述符应该能够提供足够的局部图像信息,以便在不同的图像和不同的视角下识别相同的特征点。
- 不变性:描述符应该对图像的某些变换(如缩放、旋转、光照变化等)保持不变,以便在不同的图像条件下仍然能够准确匹配。
本次使用的描述符为BEBLID描述符,BEBLID描述符基于二进制编码,通过对特征点周围的小区域进行采样,并比较该区域的像素值,来生成一个二进制特征向量。与传统的浮点数描述符相比,BEBLID描述符的计算速度更快,因为它只需要比较像素值是否大于某个阈值,而不是计算像素值的差异。
BEBLID描述符的计算过程包括以下几个步骤:
- 选择特征点周围的局部区域:首先,选择特征点周围的一个小区域作为描述符的计算区域。
- 对局部区域内的像素进行采样:在这个区域内,对像素值进行采样,以生成描述符的样本。
- 对采样到的像素值进行比较:比较相邻像素值的大小,如果一个像素值大于另一个像素值,则标记为1,否则标记为0。
- 生成二进制特征向量:将比较结果组合起来,形成一个二进制特征向量。
- 对特征点进行旋转,重复上述步骤:为了提高描述符的稳健性,可以对特征点进行旋转,并重复上述步骤,以获得多个方向上的描述符。
- 组合描述符:将这些描述符组合起来,形成最终的BEBLID描述符。 优点
BEBLID描述符的主要优点包括:
- 高效计算:由于其二进制编码,BEBLID描述符的计算速度非常快,非常适合实时应用。
- 不变性:BEBLID描述符对图像的某些变换(如缩放、旋转、光照变化等)具有较好的不变性,这使得它能够在不同的图像条件下进行有效的匹配。
BEBLID描述符在opencv的api为:descriptor = cv2.xfeatures2d.BEBLID_create(weight=None)
weight:可选参数,用于指定权重因子。权重因子用于在计算描述符时对图像梯度方向直方图进行加权。如果设置为 None,则使用默认权重。
使用:
descriptor = cv2.xfeatures2d.BEBLID_create(0.75)
kpts1, desc1 = descriptor.compute(img1, kpts1)
四,描述符的匹配筛选
在获得描述符之后,需要对描述符进行匹配和筛选,本次使用的方法为knn匹配,并对匹配后的结果的欧氏距离进行筛选,使用代码:
matcher = cv2.DescriptorMatcher_create(cv2.DescriptorMatcher_BRUTEFORCE_HAMMING)
nn_matches = matcher.knnMatch(desc1, desc2, 2)
matched1 = []
matched2 = []
nn_match_ratio = 2 # Nearest neighbor matching ratio
good_matches = []
for m, n in nn_matches:if m.distance < 0.9 * n.distance:good_matches.append(m)
cv2.DescriptorMatcher_create(cv2.DescriptorMatcher_BRUTEFORCE_HAMMING) 是用于创建一个描述符匹配器的函数。这个匹配器是基于Hamming距离的暴力匹配器(Brute-Force Matcher),它用于在两组描述符之间找到匹配对。其中cv2.DescriptorMatcher_BRUTEFORCE_HAMMING:这是一个枚举值,用于指定匹配器使用Hamming距离来计算描述符之间的相似度。Hamming距离是衡量两个等长字符串差异的指标,对于二进制描述符来说,它计算的是两个描述符中不同位的数量。cv2.DescriptorMatcher_create 函数返回一个描述符匹配器对象,这个对象可以用于在两组描述符之间执行匹配操作。通过这个对象,可以调用其方法来执行匹配,如knnMatch、bruteForceMatch等,本次选择的匹配方法为knnmatch。
五,根据匹配结果映射图片
在获取到特征点之后,使用特征点匹配来估计两幅图像之间的仿射变换矩阵,并应用该变换矩阵到输入图像上,以实现图像的校正。
首先提取匹配的特征点对:
dst_pts = np.float32([kpts1[m.queryIdx].pt for m in good_matches]).reshape(-1, 1, 2)
src_pts = np.float32([kpts2[m.trainIdx].pt for m in good_matches]).reshape(-1, 1, 2)
这两行代码从两组匹配的特征点中分别提取出匹配的特征点对。good_matches 是一个包含匹配对的列表,每个匹配对是一个DMatch对象,包含源图像(img1)中的特征点索引(m.queryIdx)和目标图像(img2)中的特征点索引(m.trainIdx)。
然后使用cv2.estimateAffine2D函数估计两幅图像之间的仿射变换矩阵M。src_pts和dst_pts分别是源图像和目标图像中匹配的特征点对。method=cv2.RANSAC参数表示使用RANSAC(随机抽样一致)算法来估计变换矩阵,这是一种鲁棒的方法,可以处理噪声数据。mask是一个布尔数组,表示哪些匹配点对被用于估计变换矩阵。
M, mask = cv2.estimateAffine2D(src_pts, dst_pts, method=cv2.RANSAC)
最后将仿射变换矩阵应用于图像上:
img2_aligned = cv2.warpAffine(img2, M, (width, height))
六,整体代码:
from __future__ import print_function
import cv2
import numpy as np
import argparseparser = argparse.ArgumentParser(description='Code for feature matching and transforming image 2 to image 1.')
parser.add_argument('--input1', help='Path to input image 1.', default=r'F:\cv_traditional\1.png')
parser.add_argument('--input2', help='Path to input image 2.', default=r'F:\cv_traditional\2.png')args = parser.parse_args()img1 = cv2.imread(args.input1)
img2 = cv2.imread(args.input2)if img1 is None or img2 is None:print('Could not open or find the images!')exit(0)detector = cv2.ORB_create(10000)
descriptor = cv2.xfeatures2d.BEBLID_create(0.75)
kpts1 = detector.detect(img1, None)
kpts2 = detector.detect(img2, None)kpts1, desc1 = descriptor.compute(img1, kpts1)
kpts2, desc2 = descriptor.compute(img2, kpts2)matcher = cv2.DescriptorMatcher_create(cv2.DescriptorMatcher_BRUTEFORCE_HAMMING)
nn_matches = matcher.knnMatch(desc1, desc2, 2)matched1 = []
matched2 = []
nn_match_ratio = 2 # Nearest neighbor matching ratio
good_matches = []
for m, n in nn_matches:if m.distance < 0.9 * n.distance:good_matches.append(m)# 提取匹配点对的坐标
dst_pts = np.float32([kpts1[m.queryIdx].pt for m in good_matches]).reshape(-1, 1, 2)
src_pts = np.float32([kpts2[m.trainIdx].pt for m in good_matches]).reshape(-1, 1, 2)# 估计仿射变换矩阵
M, mask = cv2.estimateAffine2D(src_pts, dst_pts, method=cv2.RANSAC)# 应用仿射变换到img2上
height, width = img1.shape[:2]
img2_aligned = cv2.warpAffine(img2, M, (width, height))# 将变换后的img2与img1进行叠加(此处简单叠加,可根据需要调整)
result = cv2.addWeighted(img1, 0.5, img2_aligned, 0.5, 0)
cv2.imshow('img1', img1)
cv2.imshow('img2', img2)
# 显示结果
cv2.imshow('Aligned Image', img2_aligned)
cv2.waitKey(0)
cv2.destroyAllWindows()
七,效果:
目标图像:

输入图像:

校正图像:

相关文章:
opencv实战项目二十三:基于BEBLID描述符的特征点匹配实现表盘校正
提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档 文章目录 前言一、特征点匹配介绍二、特征点检测三、特征描述符计算四,描述符的匹配筛选五,根据匹配结果映射图片六,整体代码:…...
数据库是全表扫描是怎么扫描法?
全表扫描是数据库服务器用来搜寻表的每一条记录的过程,直到所有符合给定条件的记录返回为止。 在执行全表扫描时,数据库会逐行扫描表中的所有记录,以找到符合查询条件的记录。这种扫描方式适用于没有为查询条件中的字段建立索引的情况。全…...
认准这10款人力资源系统,90%的企业都在用!
本文将为大家推荐十款主流的人力资源系统,为企业选型提供参考! 想象一下,企业在不断发展壮大的过程中,员工数量逐渐增多,人事管理变得越来越复杂。如果没有一个高效的人力资源系统,就如同在大海中航行却没有…...
2024年我的利基出版转型——新战略与重点解析
这篇文章酝酿已久。这是我在网络出版策略上投入数百小时后得出的成果。 像我们这个行业的许多人一样,即网络出版行业,我一直忙于彻底改造整个出版业务。 这是一段漫长的旅程,这是肯定的。 我预感在此过程中还会有更多调整,但我…...
【数据结构】双向链表专题
目录 1.双向链表的结构 2.双向链表的实现 2.1初始化 以参数的形式初始化链表: 以返回值的形式初始化链表: 2.2尾插 2.3打印 2.4头插 2.5尾删 2.6头删 2.7查找 2.8在指定位置之后插入数据编辑 2.9删除pos节点 2.10销毁 3.整理代码 3.1…...
大二上学期计划安排
大二上学期计划安排 学期目标: 加强算法学习,提升算法思维,为以后的算法竞赛做准备学习java知识,学习框架,构建知识体系,深入底层,增强理解增加项目经验,独立完成至少一个项目,并进行交流,优化增强团队凝聚力,营造良好的团队氛围阅读书籍,阅读至少3本以上经典书籍 日常学习安…...
HarmonyOS开发实战( Beta5.0)图片编辑实现马赛克效果详解
鸿蒙HarmonyOS开发往期必看: HarmonyOS NEXT应用开发性能实践总结 最新版!“非常详细的” 鸿蒙HarmonyOS Next应用开发学习路线!(从零基础入门到精通) 介绍 本示例将原图手指划过的区域分割成若干个大小一致的小方格…...
【新书介绍】《JavaScript前端开发与实例教程(微课视频版)(第2版)》
本书重点 无任何基础的初学者,高校JavaScript课程教材。 配套非常全,提供案例源代码、PPT课件、课后习题答案、微课视频、教案、教学大纲、课程实训、期末考试试卷、章节测试、实验报告、学习通建课资源包。 内容简介 JavaScript是开发Web前端必须掌…...
什么是GWAS全基因组关联分析?
什么是全基因组关联分析?(Genome-Wide Association Study,GWAS) 全基因组关联分析(GWAS)是一种在全基因组范围内搜索遗传变异(通常是单核苷酸多态性,SNP)与复杂性状之间关…...
k8s dashboard token 生成/获取
创建示例用户 在本指南中,我们将了解如何使用 Kubernetes 的服务帐户机制创建新用户、授予该用户管理员权限并使用与该用户绑定的承载令牌登录仪表板。 对于以下每个和的代码片段ServiceAccount,ClusterRoleBinding您都应该将它们复制到新的清单文件(如)…...
windows@openssh免密登陆配置@基于powershell快速配置脚本
文章目录 abstract免密自动登录配置介绍👺修改Server配置文件一键脚本修改👺 向ssh server端上传或创建支持免密登录的公钥文件预执行命令👺方式1方式2重启服务以生效👺 傻瓜式配置免密自动登录👺👺准备 操…...
【深度学习】【图像分类】【OnnxRuntime】【Python】VggNet模型部署
【深度学习】【图像分类】【OnnxRuntime】【Python】VggNet模型部署 提示:博主取舍了很多大佬的博文并亲测有效,分享笔记邀大家共同学习讨论 文章目录 【深度学习】【图像分类】【OnnxRuntime】【Python】VggNet模型部署前言Windows平台搭建依赖环境模型转换--pytorch转onnxONN…...
手写排班日历
手写排班日历: 效果图: vue代码如下: <template><div class"YSPB"><div class"title">排班日历</div><div class"banner"><span classiconfont icon-youjiantou click&qu…...
SpringBoot多数据源配置
1、添加依赖 <!-- 数据库驱动 --><!--mysql--><dependency><groupId>mysql</groupId><artifactId>mysql-connector-java</artifactId><version>${mysql-connector-java.version}</version><scope>runtime</sco…...
影响画布微信小程序canvas及skyline和webview用户界面布局的关键流程
影响微信小程序画布canvas及skyline和webview用户界面布局的关键流程 目录 影响微信小程序画布canvas及skyline和webview用户界面布局的关键流程 一、微信小程序canvas开发流程 1.1、官方指南 1.2、客制化开发 第一步:在 WXML 中添加 canvas 组件 第二步&…...
MATLAB图像处理
MATLAB图像处理 MATLAB,作为美国MathWorks公司出品的商业数学软件,以其强大的矩阵运算能力和丰富的函数库,在图像处理领域得到了广泛的应用。MATLAB不仅提供了基础的图像处理功能,还通过图像处理工具箱(Image Process…...
【编程底层思考】性能监控和优化:JVM参数调优,诊断工具的使用等。JVM 调优和线上问题排查实战经验总结
JVM性能监控和优化是确保Java应用程序高效运行的关键环节。以下是一些JVM性能监控和优化的方法,以及使用诊断工具和实战经验的总结: 一、JVM参数调优: 堆大小设置 : - Xms:设置JVM启动时的初始堆大小。 - -Xmx:设置J…...
数据库的实施过程分析
在完成了数据库的逻辑结构设计和物理结构设计后,下一步就是将设计成果转化为现实,这一步骤被称为数据库的实施。数据库实施是数据库开发过程中至关重要的一环,它标志着从设计阶段向实际应用的过渡。本文将为你详细讲解数据库实施的各个关键步…...
【Kubernetes】常见面试题汇总(十二)
目录 36.简述 Kubernetes 的负载均衡器? 37.简述 Kubernetes 各模块如何与 APl Server 通信? 38.简述 Kubernetes Scheduler 作用及实现原理? 36.简述 Kubernetes 的负载均衡器? (1)负载均衡器是暴露服务…...
基于SpringBoot+Vue+MySQL的美术馆管理系统
系统展示 用户前台界面 管理员后台界面 系统背景 随着文化艺术产业的蓬勃发展,美术馆作为展示与传播艺术的重要场所,其管理工作变得日益复杂。为了提升美术馆的运营效率、优化参观体验并加强艺术品管理,我们开发了基于SpringBootVueMySQL的美…...
wordpress后台更新后 前端没变化的解决方法
使用siteground主机的wordpress网站,会出现更新了网站内容和修改了php模板文件、js文件、css文件、图片文件后,网站没有变化的情况。 不熟悉siteground主机的新手,遇到这个问题,就很抓狂,明明是哪都没操作错误&#x…...
AI Agent与Agentic AI:原理、应用、挑战与未来展望
文章目录 一、引言二、AI Agent与Agentic AI的兴起2.1 技术契机与生态成熟2.2 Agent的定义与特征2.3 Agent的发展历程 三、AI Agent的核心技术栈解密3.1 感知模块代码示例:使用Python和OpenCV进行图像识别 3.2 认知与决策模块代码示例:使用OpenAI GPT-3进…...
Qt Widget类解析与代码注释
#include "widget.h" #include "ui_widget.h"Widget::Widget(QWidget *parent): QWidget(parent), ui(new Ui::Widget) {ui->setupUi(this); }Widget::~Widget() {delete ui; }//解释这串代码,写上注释 当然可以!这段代码是 Qt …...
今日学习:Spring线程池|并发修改异常|链路丢失|登录续期|VIP过期策略|数值类缓存
文章目录 优雅版线程池ThreadPoolTaskExecutor和ThreadPoolTaskExecutor的装饰器并发修改异常并发修改异常简介实现机制设计原因及意义 使用线程池造成的链路丢失问题线程池导致的链路丢失问题发生原因 常见解决方法更好的解决方法设计精妙之处 登录续期登录续期常见实现方式特…...
Angular微前端架构:Module Federation + ngx-build-plus (Webpack)
以下是一个完整的 Angular 微前端示例,其中使用的是 Module Federation 和 npx-build-plus 实现了主应用(Shell)与子应用(Remote)的集成。 🛠️ 项目结构 angular-mf/ ├── shell-app/ # 主应用&…...
4. TypeScript 类型推断与类型组合
一、类型推断 (一) 什么是类型推断 TypeScript 的类型推断会根据变量、函数返回值、对象和数组的赋值和使用方式,自动确定它们的类型。 这一特性减少了显式类型注解的需要,在保持类型安全的同时简化了代码。通过分析上下文和初始值,TypeSc…...
论文阅读笔记——Muffin: Testing Deep Learning Libraries via Neural Architecture Fuzzing
Muffin 论文 现有方法 CRADLE 和 LEMON,依赖模型推理阶段输出进行差分测试,但在训练阶段是不可行的,因为训练阶段直到最后才有固定输出,中间过程是不断变化的。API 库覆盖低,因为各个 API 都是在各种具体场景下使用。…...
libfmt: 现代C++的格式化工具库介绍与酷炫功能
libfmt: 现代C的格式化工具库介绍与酷炫功能 libfmt 是一个开源的C格式化库,提供了高效、安全的文本格式化功能,是C20中引入的std::format的基础实现。它比传统的printf和iostream更安全、更灵活、性能更好。 基本介绍 主要特点 类型安全:…...
解析两阶段提交与三阶段提交的核心差异及MySQL实现方案
引言 在分布式系统的事务处理中,如何保障跨节点数据操作的一致性始终是核心挑战。经典的两阶段提交协议(2PC)通过准备阶段与提交阶段的协调机制,以同步决策模式确保事务原子性。其改进版本三阶段提交协议(3PC…...
《信号与系统》第 6 章 信号与系统的时域和频域特性
目录 6.0 引言 6.1 傅里叶变换的模和相位表示 6.2 线性时不变系统频率响应的模和相位表示 6.2.1 线性与非线性相位 6.2.2 群时延 6.2.3 对数模和相位图 6.3 理想频率选择性滤波器的时域特性 6.4 非理想滤波器的时域和频域特性讨论 6.5 一阶与二阶连续时间系统 6.5.1 …...
