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的美…...

golang面试
算法: 1.提取二进制位最右边的 r i & (~i 1) 2.树上两个节点最远距离,先考虑头结点参与不参与。 3.暴力递归改dp。 1.确定暴力递归方式。 2.改记忆化搜索 3.严格表方式: 分析可变参数变化范围,参数数量决定表维度、 …...

基于"WT2605C的智能血压计:AI对话引领个性化健康管理新时代,健康守护随时在线
在当今快节奏的生活中,健康管理已成为我们日常不可或缺的一部分。随着科技的进步,智能设备正逐步融入我们的日常生活,为健康管理带来前所未有的便捷与智能化。今天,让我们共同探索WT2605C AI在线方案如何在血压计中发挥革命性作用…...

redis高级教程
一 关系型数据库和 NoSQL 数据库 数据库主要分为两大类:关系型数据库与 NoSQL 数据库 关系型数据库 ,是建立在关系模型基础上的数据库,其借助于集合代数等数学概念和方法来处理数据库中的数据主流的 MySQL 、 Oracle 、 MS SQL Server 和 D…...

prfm命令初探
1. 前言 在查看一段neon代码时,发现有如下片段,为使用汇编进行数据预取操作。这是一个新的知识点,记录一下学习过程。 __asm__ volatile("prfm pldl2keep,[%0, #8192] \n""prfm pldl1keep,[%0, #1024] \n":"r"…...

AI大模型需要学什么?怎么学?从零基础入门大模型(保姆级),从这开始出发!
一.初聊大模型 1.为什么要学习大模型? 在学习大模型之前,你不必担心自己缺乏相关知识或认为这太难。我坚信,只要你有学习的意愿并付出努力,你就能够掌握大模型,并能够用它们完成许多有意义的事情。在这个快速变化的时代…...

python自述3
Python 条件控制 if语句的一般形式如下所示: if condition_1: statement_block_1 elif condition_2: statement_block_2 else: statement_block_3 Python 中用 elif 代替了 else if,所以if语句的关键字为:if – elif – else。 注意: 1、每个条件后面要使用冒号 :,表…...

Redis常见的数据结构
Redis底层的数据结构是Redis高效存储和操作数据的基础,Redis提供了五种基本的数据类型,每种类型在底层都有对应的数据结构来实现。这五种数据类型分别是:字符串(String)、哈希(Hash)、列表(List…...

批量插入insert到SQLServer数据库,BigDecimal精度丢失解决办法,不动代码,从驱动层面解决
概述 相信很多人都遇到过,使用sql server数据库,批量插入数据时,BigDecimal类型出现丢失精度的问题,网上也有很多人给出过解决方案,但一般都要修改应用代码,不推荐。 丢失精度的本质是官方的驱动有BUG造成…...

随手记:uniapp小程序登录方式和小程序使用验证码登录
小程序登录方式: 方式一:小程序授权登录 通过uni.login获取 临时登录凭证code,向后端换取token。 <u-button type"primary" shape"circle" click"login">登 录</u-button>login() {uni.login({p…...

【Hadoop|HDFS篇】DataNode概述
1. DataNode的工作机制 1)一个数据块在DataNode上以文件形式存储在磁盘上,包括两个文件,一个是数据本身,一个是元数据包括数据块的长度,块数据的校验和,以及时间戳。 2)DataNode启动后向NameNod…...