ORB_SLAM的ORB特征提取:

ORB_SLAM的ORB特征提取:

参考连接:https://blog.csdn.net/zzpzm/article/details/100583068
https://www.cnblogs.com/alexme/p/11345701.html

Abstract:

ORB 是 Oriented Fast and Rotated Brief 的简称,可以用来对图像中的关键点快速创建特征向量,这些特征向量可以用来识别图像中的对象。
其中,Fast 和 Brief 分别是特征检测算法和向量创建算法。ORB 首先会从图像中查找特殊区域,称为关键点。关键点即图像中突出的小区域,比如角点,比如它们具有像素值急剧的从浅色变为深色的特征。然后 ORB 会为每个关键点计算相应的特征向量。ORB 算法创建的特征向量只包含 1 和 0,称为二元特征向量。1 和 0 的顺序会根据特定关键点和其周围的像素区域而变化。该向量表示关键点周围的强度模式,因此多个特征向量可以用来识别更大的区域,甚至图像中的特定对象。
ORB 的特点是速度超快,而且在一定程度上不受噪点和图像变换的影响,例如旋转和缩放变换等。

FAST 算法

ORB 特征检测的第一步是查找图像中的关键点,而关键点检测算法即使用 FAST 算法。
FAST 是 Features from Accelerated Segments Test 的简称,可以快速选择关键点,算法步骤如下:
给与一个像素点 p,FAST 比较目标 p 圆圈范围中的 16 个像素,每个像素按高于 p,小于 p,或者与 p 相似,分为三类。
在这里插入图片描述注意这里的比较是带有阈值 h 的。对于给定的阈值 h,更亮的像素将是亮度超过 Ip+h 的像素,更暗的像素将是亮度低于 Ip-h 的像素,相似像素将是亮度在这两个值之间的像素。在对像素分类后, 如果圈圈上有 8 个以上的相连像素,暗于或亮于 p 则将像素 p 选作关键点。
而 FAST 如此高效的原因是,仅将 p 与圆圈中的 4 个等距像素相比。这种方法已经证明和比较 16 个周围像素的效果相同。如果至少有一对连续像素的亮度高于或低于 p,则将 p 选作关键点。这种优化使得在整个图像中搜索关键点的时间缩短了四倍。(为什么缩短四倍,如何证明?)
在这里插入图片描述
但是,这些关键点可以像我们提供什么样的信息?对比邻近像素的亮度有何意义?首先观察一下 FAST 算法标记关键点的图像。
在这里插入图片描述可以看出关键点位于亮度有变化的区域,此类区域通常确定了某种边缘,例如猫的爪子。边缘定义了猫的界限,以及脸部区域的界限,因此这些关键点使我们能够识别这只猫,而不是图像中的任何其他对象或背景。

BRIEF 算法

我们已经知道 ORB 如何使用 FAST 确定图像中的关键点,下面我们将了解 ORB 如何使用 BRIEF 算法,并将这些关键点转换为特征向量。

ORB 算法的第二步是将第一个算法发现的关键点变成特征向量,这些特征向量可以共同表示一个对象。

要创建特征向量,ORB 会用到 BRIEF 算法。BRIEF 是 Binary Robust Independent Elementary Features 的简称,它的作用是根据一组关键点创建二元特征向量。正如在简介视频中看到的,二元特征向量又称为二元描述符,是仅包含 1 和 0 的特征向量。在 BRIEF 中 每个关键点由一个二元特征向量描述,该向量一般为 128-512 位的字符串,其中仅包含 1 和 0。注意,这里的“位”是二进制位的简称,1 位只能存储一个二进制值,要么 1 要么是 0.
那么这些0和1怎么来的呢?
在这里插入图片描述BRIEF 如何为每个点创建这些二元描述符?BRIEF 算法首先利用高斯核对给定图像进行平滑处理,以防描述符对高频噪点过于敏感。然后,对于给定关键点,例如猫爪上的这个点。

在这里插入图片描述

BRIEF 从该关键点周围界定好的邻域内随机选择一对像素,关键点周围的邻域称为 Patch,它是一个具有特定像素宽度和高度的正方形。
这里显示的随机对中的第一个像素,是一个蓝色正方形,它是从以关键点为中心的高斯分布中抽取的一个像素,标准偏差或分散趋势为 σ。
这里显示为黄色正方形的像素,是随机对中的第二个像素。它是从以该第一个像素为中心的高斯分布中抽取的像素,标准偏差为 σ/2,经验表明这种高斯选择提高了特征匹配率。

BRIEF 然后开始为关键点构建二元描述符,方法是如下所示地比较这两个像素的亮度。如果第一个像素比第二个亮,则为描述符中的相应位分配值 1,否则分配值 0。

在这个示例中第二个像素比第一个亮,因此我们为特征向量的第一个位分配值 0。特征向量的第一个位对应的是这个关键点的第一个随机点对,然后 BRIEF 会针对同一关键点选择新的随机像素对比较它们的亮度并为特征向量中的下个位分配 1 或 0。

在上面新选取的随机像素中,我们看到现在第一个像素比第二个亮,因此为特征向量中的第二个位分配值 1。

对于 256 位向量,BRIEF 会针对同一关键点重复这一流程 256 次,每个过程会进行两次高斯分布的随机抽取,然后转到下个关键点。接着将 256 个像素亮度比较结果放入该关键点的二元特征向量中。BRIEF 像这样为图像中的每个关键点创建一个向量。

缩放不变性和旋转不变性

ORB 使用 FAST 检测图像中的关键点,并且通过额外的几个步骤确保无论对象的大小或位置如何都能检测到图像中的对象。

给定一个图像 ORB 算法首先开始构建图像金字塔。

图像金字塔是单个图像的多尺度表示法,由一系列原始图像的不同分辨率版本组成。金字塔的每个级别都由上个级别的图像下采样版本组成。下采样是指图像分辨率被降低,比如图像按照 1/2 比例下采样。因此一开始的 4x4 正方形区域现在变成 2x2 正方形。图像的下采样包含更少的像素,并且以 1/2 的比例降低大小。
在这里插入图片描述这是一个包含 5 个级别的图形金字塔示例,在每个级别图像都以 1/2 的比例下采样。到了第四级别图像的分辨率是原始图像的 1/16。ORB 创建好图像金字塔后,它会使用 FAST 算法从每个级别不同大小的图像中快速找到关键点。因为金字塔的每个级别由原始图像的更小版本组成,因此原始图像中的任何对象在金字塔的每个级别也会降低大小。
通过确定每个级别的关键点 ORB 能够有效发现不同尺寸的对象的关键点,这样的话 ORB 实现了部分缩放不变性。这一点很重要,因为对象不太可能在每个图像中的大小都完全一样,尤其是像猫这样的对象某个时刻可能靠近相机,在另一个时刻离相机很远。
在这里插入图片描述现在 ORB 获得了与这个图像金字塔每个级别相关的关键点。在发现金字塔所有级别中的关键点后,ORB 现在为每个关键点分配一个方向,例如朝左或朝右,取决于该关键点周围的强度是如何变化的。
我们详细了解下背后原理。ORB 首先选择金字塔Level 0 中的图像,对于该图像 ORB 将计算关键点的方向。
在这里插入图片描述
方法是首先计算以该关键点为中心的方框中的强度形心。强度形心可以看做给定 patch 中的平均像素强度的位置。计算强度形心后,通过画一条从关键点到强度形心的向量,获得该关键点的方向,如上图所示。这个关键点的方向是向下并朝左,因为这个区域的亮度朝着这个方向增强。
为金字塔级别 0 的图像中的每个关键点分配方向后,ORB 现在为所有其他金字塔级别的图像重复相同流程。需要注意的是,在每个图像金字塔级别,Patch 大小并没有缩减,因此相同 Patch 在每个金字塔级别覆盖的图像区域将更大,导致关键点的大小各不相同。

在这里插入图片描述可以从此处看出这一点。在此图中,圆圈表示每个关键点的大小,更高的金字塔级别中的关键点大小更大。
找到关键点并为其分配方向后,ORB 现在使用修改后的 BRIEF 版本创建特征向量,这个修改后的 BRIEF 版本称为 rBRIEF,即 Rotation-Aware BRIEF。无论对象的方向如何,它都可以为关键点创建相同的向量,使得 ORB 算法具有旋转不变性,意味着它可以在朝着任何角度旋转的图像中检测到相同的关键点。和 BRIEF 一样 rBRIEF 首先在给定关键点周围的已界定 patch 中随机选择 256 个像素对,以构建 256 位向量。然后根据关键点的方向角度旋转这些随机像素对,使随机点的方向与关键点的一致。最后, rBRIEF 对比随机像素对的亮度并相应地分配 1 和 0 创建对应的特征向量,为图像中的所有关键点创建的所有特征向量集合称之为 ORB 描述符。

代码实现:python

import copy

import cv2
import matplotlib.pyplot as plt


plt.rcParams['figure.figsize'] = [14.0, 7.0]

#get image
training_image= cv2.imread('../Picture/mingren.jpeg')
#cv2.imshow("mingren",training_image)

#cv  to   gray
training_gray=cv2.cvtColor(training_image,cv2.COLOR_BGR2RGB)

plt.rcParams['figure.figsize'] = [14.0, 7.0]

#create ORB
orb = cv2.ORB_create(200, 2.0)
keypoints, descriptor = orb.detectAndCompute(training_gray, None)

# #复制图像和直接等于不同,复制地址不同,等于相同。
keyp_without_size =copy.copy(training_image)
keyp_with_size = copy.copy(training_image)

##换不同的方式输出ORB特征点
cv2.drawKeypoints(training_image, keypoints, keyp_without_size,color = (3, 255, 0))

cv2.drawKeypoints(training_image, keypoints, keyp_with_size,flags = cv2.DRAW_MATCHES_FLAGS_DRAW_RICH_KEYPOINTS)



# 同窗口显示
plt.subplot(121)
plt.title('1')
plt.imshow(keyp_without_size)

plt.subplot(122)
plt.title('2')
plt.imshow(keyp_with_size)
plt.show()

# 显示关键点的长度
print("\nNumber of keypoints Detected: ", len(keypoints))

在这里插入图片描述

ORB的匹配

import cv2
import matplotlib.pyplot as plt
#设置默认数字大小
plt.rcParams['figure.figsize'] = [14.0, 7.0]

# Load image
image1 = cv2.imread('../Picture/mingren.jpeg')

# Load image
image2 = cv2.imread('../Picture/mingren.jpeg')

# 从BGR变成RGB
training_image = cv2.cvtColor(image1, cv2.COLOR_BGR2RGB)
# 从BGR变成RGB
query_image = cv2.cvtColor(image2, cv2.COLOR_BGR2RGB)

# Display 
plt.subplot(121)
plt.title('Image1')
plt.imshow(training_image)
plt.subplot(122)
plt.title('Image2')
plt.imshow(query_image)
plt.show()

# 灰度
training_gray = cv2.cvtColor(training_image, cv2.COLOR_BGR2GRAY)

# 灰度
query_gray = cv2.cvtColor(query_image, cv2.COLOR_BGR2GRAY)

#设置ORB算法的参数,指定要定位的关键点的最大数量和

#金字塔参数
orb = cv2.ORB_create(1000, 2.0)

#在灰度训练和查询图像中找到关键点,并计算它们的ORB描述符。

#需要None参数来表明我们在这两种情况下都没有使用掩码。
keypoints_train, descriptors_train = orb.detectAndCompute(training_gray, None)
keypoints_query, descriptors_query = orb.detectAndCompute(query_gray, None)

# 创建一个Brute Force Matcher对象。将crossCheck设置为True,这样BFMatcher将只返回一致

#对。当有足够的匹配时,这种技术通常以最少的离群值产生最佳结果。
bf = cv2.BFMatcher(cv2.NORM_HAMMING, crossCheck = True)

# Perform the matching between the ORB descriptors of the training image and the query image
matches = bf.match(descriptors_train, descriptors_query)

#执行训练图像和查询图像的ORB描述符之间的匹配
matches = sorted(matches, key = lambda x : x.distance)

#将训练图像中的关键点与查询图像中最匹配的关键点连接起来。

#最佳匹配对应于排序匹配列表中的第一个元素,因为它们是那些

#距离较短。我们绘制前300个mathces,并使用flags = 2绘制匹配的关键点

#没有大小或方向。
result = cv2.drawMatches(training_image, keypoints_train, training_image, keypoints_query, matches[:300], query_gray, flags = 2)

# Display the best matching points
plt.title('ORB匹配')
plt.imshow(result)
plt.show()
#打印在图像中检测到的关键点的数量
print("Number of Keypoints Detected In The Training Image: ", len(keypoints_train))

#打印在图像中检测到的关键点的数量
print("Number of Keypoints Detected In The Query Image: ", len(keypoints_query))

#打印在图像中检测到的关键点的数量
print("\nNumber of Matching Keypoints Between The Training and Query Images: ", len(matches))

在这里插入图片描述
在这里插入图片描述

  • 1
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值