opencv 进阶16-基于FAST特征和BRIEF描述符的ORB(图像匹配)

在计算机视觉领域,从图像中提取和匹配特征的能力对于对象识别、图像拼接和相机定位等任务至关重要。实现这一目标的一种流行方法是
ORB(Oriented FAST and Rotated Brief)特征检测器和描述符。ORB 由 Ethan Rublee
等人开发,结合了两种现有技术的优势——FAST(加速分段测试特征)和Brief(二进制鲁棒独立基本特征)——为特征提取和匹配提供了强大而高效的解决方案。

在本文中,我们将深入研究 ORB 的内部工作原理,探讨它如何充当特征检测器和描述符、其关键组件以及与其他特征提取方法相比的优势。

  1. FAST特征检测器

加速分割测试的特征(Feature from Accelerated Segment
Test,FAST)算法是通过分析16个像素的圆形邻域来实现的。FAST算法把邻域内每个像素标记为比特定阈值更亮或更暗,该阈值是相对于圆心定义的。如果邻域包含若干标记为更亮或更暗的一系列连续像素,那么这个邻域就被视为角点。

FAST是一种角点检测算法,可以有效识别图像中的角点或关键点。通过利用简单的强度阈值方案和最小化计算,它的设计速度比传统的角点检测器更快。FAST 检查候选像素周围的一圈像素,如果有足够数量的连续像素比候选像素更亮或更暗,则将其分类为角点。

  1. BRIEF

另外,二值鲁棒独立基本特征(Binary Robust Independent Elementary
Feature,BRIEF)并非特征检测算法,而是一个描述符。我们来更深入地研究一下描述符的概念,然后再来研究BRIEF。

在前面用SIFT和SURF分析图像时,整个过程的核心是调用
detectAndCompute函数。此函数执行两个不同的步骤——检测和计算,它们返回2个不同的结果(耦合到一个元组中)。

检测结果是一组关键点,计算结果是这些关键点的一组描述符。这意味着OpenCV的cv2.SIFT和cv2.SURF类都实现了检测和描述算法。请记住,原始的SIFT和SURF不是特征检测算法。

OpenCV的cv2.SIFT实现了DoG特征检测和SIFT描述,而OpenCV的cv2.SURF实现了快速Hessian特征检测和SURF描述。
关键点描述符是图像的一种表示,充当特征匹配的通道,因为你
可以比较两幅图像的关键点描述符并发现它们的共性。BRIEF是目前最快的描述符之一。BRIEF背后的理论相当复杂,但是可以这样说,BRIEF采用一系列优化,使其成为特征匹配的一个非常好的选择。

蛮力匹配

蛮力匹配器是一个描述符匹配器,它比较两组关键点描述符并生成匹配列表。之所以称为蛮力匹配,是因为在该算法中几乎不涉及优化。对于第一个集合中的每个关键点描述符,匹配器将之与第二个集合中的每个关键点描述符进行比较。每次比较产生一个距离值,并基于最小距离选择最佳匹配。

概括地说,在计算中,“蛮力”一词是指将所有可能组合(例如,破解已知长度密码的所有可能的字符组合)的穷举按优先级排序的方法。相反,优先考虑速度的算法可能会跳过一些可能性,并试图走一条捷径来找到看似最合理的解决方案。

OpenCV提供了一个cv2.BFMatcher类,支持几种蛮力特征匹配的方法。

  1. ORB算法原理
    ORB算法将FAST特征点的检测方法和BRIEF特征描述子结合起来,并在它们的基础上做了改进与优化。

首先,它利用FAST特征点检测的方法来检测特征点,然后利用Harris角点的度量方法,从FAST特征点中挑选出Harris角点响应值最大的N个特征点。其中Harris角点的响应函数定义为:

R=detM−k(trace(M))2

在现在生活中,我们从不同的距离,不同的方向、角度、不同的光照条件下观察一个物体时,物体的大小、形状,明暗都会有所不同。但是我们仍然可以判断它是一个物体。理想的特征描述子应该具备这些性质,即在大小、方向、明暗不同的图像中,同一特征点应具有足够相似的描述子,称之为描述子的可复现性。

但是ORB并没有解决尺度不一致的问题,在OpenCV的ORB实现中采用了图像金字塔来改善这方面的性能,我们通过构建高斯金字塔,然后在每一层金字塔图像上检测角点,来实现尺度不变性。ORB主要解决了BRIEF描述子不具备旋转不变性的问题,ORB论文种提出了一种利用灰度质心法来解决这个问题,灰度质心法假设角点的灰度与质心之间存在一个偏移,这个向量可以用于表示一个方向。对于任意一个特征点p来说,我们定义p的邻域像素的矩为:

在这里插入图片描述

其中I(x,y)为点(x,y)处的灰度值,q 为质心,i,j=0,1。那么我们可以得到图像的质心为:

在这里插入图片描述

那么特征点与质心的夹角定义为FAST特征点的方向:

在这里插入图片描述
为了提高算法的旋转不变性,需要确保 x 和 y 在半径为r 的圆形区域内,即x,y∈[−r,r],r 等于邻域半径。

特征点的描述

ORB选择了BRIEF作为特征描述方法,但是我们知道BRIEF不具备旋转不变性,所以我们要给BRIEF加上旋转不变性,把这种方法称为"Steer BRIEF"。 对于任何一个特征点来说,它的BRIEF描述子是一个长度为n的二值码串,这个二值码串是由特征点邻域n个点对生成的,我们现在讲这2n个点(xi,yi),i=1,2,…,2n组成一个矩阵S:

在这里插入图片描述
Calonder建议为每个块的旋转和投影集合分别计算BRIEF描述子,但代价昂贵。ORB中采用了一个更有效的方法:使用邻域方向θ和对应的转矩阵Rθ,构建S 的一个校正版本Sθ:

在这里插入图片描述
其中:

在这里插入图片描述
而θ 即我们为特征点求得的主方向。

即我们把坐标轴旋转]theta,计算以主方向为坐标系的匹配点对,如下图:

在这里插入图片描述
实际上,我们可以把角度离散化,即把360度分为12份,每一份是30度,然后我们对这个12个角度分别求得一个Sθ,这样我们就创建了一个查找表,对于每一个θ,我们只需要查表即可快速得到它的点的集合Sθ。

解决描述子的区分性

BRIEF令人惊喜的特性之一是:对于n维的二值串的每个特征位,所有特征点在该位上的值都满足一个均值接近于0.5,而方差很大的高斯分布。方差越大,说明区分性越强,那么不同特征点的描述子就表现出来越大差异性,对匹配来说不容易误配。但是当我们把BRIEF沿着特征点的方向调整为Steered BRIEF时,均值就漂移到一个更加分散式的模式。可以理解为有方向性的角点关键点对二值串则展现了一个更加均衡的表现。而且论文中提到经过PCA对各个特征向量进行分析,得知Steered BRIEF的方差很小,判别性小,各个成分之间相关性较大。

为了减少Steered BRIEF方差的亏损,并减少二进制码串之间的相关性,ORB使用了一种学习的方法来选择一个较小的点对集合。方法如下:

首先建立一个大约300k关键点的测试集,这些关键点来自于PASCAL2006集中的图像。

对于这300k个关键点中的每一个特征点,考虑它的31×31的邻域,我们将在这个邻域内找一些点对,不同于BRIEF中要先对这个Patch内的点做平滑,再用以Patch中心为原点的高斯分布选择点对的方法。

ORB为了去除某些噪声点的干扰,选择了一个5×5大小的区域的平均灰度来代替原来一个单点的灰度,这里5×5区域内图像平均灰度的计算可以用积分图的方法。我们知道31×31的Patch里共有N=(31−5+1)×(31−5+1)个这种窗口,那么我们要N个子窗口中选择2个子窗口的话,共有C2N种方法。所以对于300k中每一个特征点,我们都可以从它的31×31大小的邻域中提取一个很长的二进制串,长度为M=C2N,表示为:

在这里插入图片描述
那么当300k个关键点全部进行上面的特征提取之后,我们就得到了一个300k×M的矩阵,矩阵中的每个元素值为0或者1.

对该矩阵的每个列向量,也就是每个点对在300k个特征点上的测试结果,计算其均值。把所有的列向量按均值进行重新排序。排好后,组成了一个向量T,T的每一个元素都是一个列向量。进行贪婪搜索,从T中把排在第一的那个列放到R中,T中就没有这个点对的测试结果了,然后把T中的排在下一个的列与R中的所有元素比较,计算它们的相关性,如果相关超过了某一事先设定好的阈值,就扔了它,否则就把它方到R里面。

重复上面的步骤,直到R中有256个列向量位置。

如果把T全部找完也没有找到256个,那么我们可以把相关的阈值调高一些,再尝试一遍。这样,我们就得到了256个点对。上面这个过程我们称它为rBRIEF。

OpenCV实现

ORB中有很多参数可以设置,在OpenCV中它可以通过ORB来创建一个ORB检测器。

cv2.ORB_create([,nfeatues[,scaleFactor[,nlevels[,edgeThreshold[,firstLevel[,WTA_K[,[scoreType,[patchSize,fastThreshold]]]]]]]]])

参数说明:

  • nfeatures :最多提取的特征点的数量;
  • scaleFactor : 金字塔图像之间的尺度参数,类似于SIFT中的k;
  • nlevels: 高斯金字塔的层数;
  • edgeThreshold :边缘阈值,这个值主要是根据后面的patchSize来定的,靠近边缘edgeThreshold以内的像素是不检测特征点的。
  • firstLevel-:看过SIFT都知道,我们可以指定第一层的索引值,这里默认为0。
  • WET_K : 用于产生BIREF描述子的点对的个数,一般为2个,也可以设置为3个或4个,那么这时候描述子之间的距离计算就不能用汉明距离了,而是应该用一个变种。OpenCV中,如果设置WET_K = 2,则选用点对就只有2个点,匹配的时候距离参数选择NORM_HAMMING,如果WET_K设置为3或4,则BIREF描述子会选择3个或4个点,那么后面匹配的时候应该选择的距离参数为NORM_HAMMING2。
  • scoreType :用于对特征点进行排序的算法,你可以选择HARRIS_SCORE,也可以选择FAST_SCORE,但是它也只是比前者快一点点而已。
  • patchSize :用于计算BIREF描述子的特征点邻域大小。

示例:使用ORB描述符进行Brute-Force匹配:

示例代码:


import cv2

def orb_test():
    # 加载图片  灰色
    img1 = cv2.imread('images\\quexiao\\2.png')
    gray1 = cv2.cvtColor(img1, cv2.COLOR_BGR2GRAY)
    img2 = cv2.imread('images\\quexiao\\2-1.png')

    gray2 = cv2.cvtColor(img2, cv2.COLOR_BGR2GRAY)
    image1 = gray1.copy()
    image2 = gray2.copy()

    '''
    1.使用ORB算法检测特征点、描述符
    '''
    orb = cv2.ORB_create(128)
    keypoints1, descriptors1 = orb.detectAndCompute(image1, None)
    keypoints2, descriptors2 = orb.detectAndCompute(image2, None)
    # 在图像上绘制关键点
    image1 = cv2.drawKeypoints(image=image1, keypoints=keypoints1, outImage=image1, color=(255, 0, 255),
                               flags=cv2.DRAW_MATCHES_FLAGS_DRAW_RICH_KEYPOINTS)
    image2 = cv2.drawKeypoints(image=image2, keypoints=keypoints2, outImage=image2, color=(255, 0, 255),
                               flags=cv2.DRAW_MATCHES_FLAGS_DRAW_RICH_KEYPOINTS)
    # 显示图像
    cv2.imshow('orb_keypoints1', image1)
    cv2.imshow('orb_keypoints2', image2)
    cv2.waitKey(20)

    '''
    2、匹配
    '''
    # 使用汉明距离,创建BF匹配器,并进行匹配() 新版本不支持
   # matcher = cv2.BFMatcher_create(cv2.HAMMING_NORM_TYPE, crossCheck=True)
    matcher = cv2.BFMatcher_create(cv2.NORM_HAMMING, crossCheck=True)
    matchePoints = matcher.match(descriptors1, descriptors2)
    print(type(matchePoints), len(matchePoints), matchePoints[0])
    # 按照距离从小到大排序,选取最优匹配的
    sorted(matchePoints, key=lambda x: x.distance)
    # 绘制最优匹配点
    outImg = None
    outImg = cv2.drawMatches(img1, keypoints1, img2, keypoints2, matchePoints[:10], outImg, matchColor=(0, 255, 0),
                             flags=cv2.DRAW_MATCHES_FLAGS_DEFAULT)
    cv2.imshow('matche', outImg)
    cv2.waitKey(0)
    cv2.destroyAllWindows()

    cv2.waitKey(0)
    cv2.destroyAllWindows()


if __name__ == '__main__':
    orb_test()

在这里插入图片描述

实验原图:
2.png
请添加图片描述

2-1.png
请添加图片描述

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

IDEA中导入多module的Maven项目无法识别module的解决办法

首先举个栗子 这是正常的多module工程(spring cloud项目) 正常工程.png 这是导入出现问题的多module工程 导入出现问题的工程.png 原因: 出现该问题,是由于打开工程的时候IDEA只编译了最外层的pom.xml文件,而内部的…

【分享】华为设备登录安全配置案例

微思网络www.xmws.cn,2002年成立,专业IT认证培训21年,面向全国招生! 微 信 号 咨 询: xmws-IT 华为HCIA试听课程:超级实用,华为VRP系统文件详解【视频教学】华为VRP系统文件详解 华为HCIA试听课…

机器学习在大数据分析中的应用

文章目录 机器学习在大数据分析中的原理机器学习在大数据分析中的应用示例预测销售趋势客户细分和个性化营销 机器学习在大数据分析中的前景和挑战前景挑战 总结 🎉欢迎来到AIGC人工智能专栏~探索机器学习在大数据分析中的应用 ☆* o(≧▽≦)o *☆嗨~我是IT陈寒&…

Android SDK 上手指南||第四章 应用程序结构

第四章 应用程序结构 本教程将主要以探索与了解为主要目的,但后续的系列文章则将进一步带大家深入学习如何创建用户界面、响应用户交互操作以及利用Java编排应用逻辑。我们将专注于大家刚刚开始接触Android开发时最常遇到的项目内容,但也会同时涉及一部…

SpringBoot内嵌Tomcat连接池分析

文章目录 1 Tomcat连接池1.1 简介1.2 架构图1.2.1 JDK线程池架构图1.2.2 Tomcat线程架构 1.3 核心参数1.3.1 AcceptCount1.3.2 MaxConnections1.3.3 MinSpareThread/MaxThread1.3.4 MaxKeepAliveRequests1.3.5 ConnectionTimeout1.3.6 KeepAliveTimeout 1.4 核心内部线程1.4.1 …

shell脚本免交互

一.Here Document免交互 1.免交互概述 使用I/O重定向的方式将命令列表提供给交互式程序 是一种标准输入&#xff0c;只能接收正确的指令或命令 2.格式&#xff1a; 命令 <<标记 ....... 内容 #标记之间是传入内容 ....... 标记 注意事项 标记可以使用任意的合法…

“深度学习”学习日记:Tensorflow实现VGG每一个卷积层的可视化

2023.8.19 深度学习的卷积对于初学者是非常抽象&#xff0c;当时在入门学习的时候直接劝退一大班人&#xff0c;还好我坚持了下来。可视化时用到的图片&#xff08;我们学校的一角&#xff01;&#xff01;&#xff01;&#xff09;以下展示了一个卷积和一次Relu的变化 作者使…

2023国赛数学建模思路 - 案例:最短时间生产计划安排

文章目录 0 赛题思路1 模型描述2 实例2.1 问题描述2.2 数学模型2.2.1 模型流程2.2.2 符号约定2.2.3 求解模型 2.3 相关代码2.4 模型求解结果 建模资料 0 赛题思路 &#xff08;赛题出来以后第一时间在CSDN分享&#xff09; https://blog.csdn.net/dc_sinor?typeblog 最短时…

网络安全—黑客—自学笔记

想自学网络安全&#xff08;黑客技术&#xff09;首先你得了解什么是网络安全&#xff01;什么是黑客&#xff01; 网络安全可以基于攻击和防御视角来分类&#xff0c;我们经常听到的 “红队”、“渗透测试” 等就是研究攻击技术&#xff0c;而“蓝队”、“安全运营”、“安全…

Mac Flutter web环境搭建

获取 Flutter SDK 下载以下安装包来获取最新的 stable Flutter SDK将文件解压到目标路径, 比如: cd ~/development $ unzip ~/Downloads/flutter_macos_3.13.0-stable.zip 配置 flutter 的 PATH 环境变量&#xff1a; export PATH"$PATH:pwd/flutter/bin" // 这个命…

无类别域间路由(Classless Inter-Domain Routing, CIDR):理解IP网络和子网划分(传统的IP地址类ABCDE:分类网络)

文章目录 无类别域间路由&#xff08;CIDR&#xff09;&#xff1a;理解IP网络和子网划分引言传统的IP地址类关于“IP地址的浪费” IP地址与CIDRIP地址概述网络号与主机号CIDR记法&#xff08;网络 网络地址/子网掩码&#xff09;网络和广播地址 CIDR的优势减少路由表项缓解IP…

Android 面试之Glide做了哪些优化?

前言 Glide可以说是最常用的图片加载框架了&#xff0c;Glide链式调用使用方便&#xff0c;性能上也可以满足大多数场景的使用&#xff0c;Glide源码与原理也是面试中的常客。 但是Glide的源码内容比较多&#xff0c;想要学习它的源码往往千头万绪&#xff0c;一时抓不住重点.…

0101读写分离测试-jdbc-shardingsphere-中间件

文章目录 1 前言2、创建SpringBoot程序2.1、创建项目2.2、添加依赖2.3、生成实体类、service与Mapper1.5、配置读写分离 2、测试2.1、读写分离测试2.2、事务测试2.3、负载均衡测试 结语 1 前言 shardingshpere-jdbc定位为轻量级 Java 框架&#xff0c;在 Java 的 JDBC 层提供的…

文心一言 VS 讯飞星火 VS chatgpt (79)-- 算法导论7.4 4题

四、请用go语言&#xff0c;证明:RANDOMIZED-QUICKSORT 期望运行时间是 Ω(nlgn)。 文心一言&#xff1a; 首先&#xff0c;为了证明RANDOMIZED-QUICKSORT的期望运行时间是Ω(nlg n)&#xff0c;我们需要证明在最坏的情况下&#xff0c;该算法的运行时间是O(nlg n)。然后&…

elelementui组件

一、按钮 1、按钮样式 使用type、plain、round和circle属性来定义 Button 的样式。 2、主要代码 <el-row><el-button>默认按钮</el-button><el-button type"primary">主要按钮</el-button><el-button type"success">…

antd5源码调试环境启动(MacOS)

将源码下载至本地 这里antd5 版本是5.8.3 $ git clone gitgithub.com:ant-design/ant-design.git $ cd ant-design $ npm install $ npm start前提&#xff1a;安装python3、node版本18.14.0(这是本人当前下载的版本&#xff09; python3安装教程可参考&#xff1a;https://…

06-微信小程序-注册程序-场景值

06-微信小程序-注册程序 文章目录 注册小程序参数 Object object案例代码 场景值场景值作用场景值列表案例代码 注册小程序 每个小程序都需要在 app.js 中调用 App 方法注册小程序实例&#xff0c;绑定生命周期回调函数、错误监听和页面不存在监听函数等。 详细的参数含义和使…

框架分析(2)-React

框架分析&#xff08;2&#xff09;-React 专栏介绍React核心思想关键特性和功能组件化开发单向数据流JSX语法强大的生态系统 优缺点分析优点缺点 专栏介绍 link 主要对目前市面上常见的框架进行分析和总结&#xff0c;希望有兴趣的小伙伴们可以看一下&#xff0c;会持续更新的…

树莓派和windows之间文件传输

方案一&#xff1a;FileZilla 在电脑上下载FileZilla软件并打开&#xff0c;输入配置信息&#xff0c;用户名/密码、树莓派的IP地址,点击“快速连接” 方案二&#xff1a;samba 树莓派安装 samba 软件 sudo apt-get install samba samba-common-bin 修改配置文件 / etc /samba…

Python搭建http文件服务器实现手机电脑文件传输功能

第一种代码的界面如下&#xff1a;&#xff08;有缺点&#xff0c;中文乱码&#xff09; # !/usr/bin/env python3 # -*- coding:utf-8 _*-"""Simple HTTP Server With Upload. python -V3.6 This module builds on http.server by implementing the standard G…