目标
- 理解 FAST 算法的基础
- 使用OpenCV 中的FAST 算法相关函数进行角点检测
介绍
FAST算法(Features from Accelerated Segment Test)是一种用于在图像中快速检测角点的算法。它是一种基于像素的检测方法,具有高效、准确的特点,常用于计算机视觉领域中的特征点提取、图像匹配等任务。
背景
我们前面学习了几个特征检测器,它们大多数效果都很好。但是从实时处理的角度来看,这些算法都不够快。一个最好例子就是SLAM(同步定位与地图构建)、移动机器人,它们的计算资源非常有限。为了解决这个问题,Edward_Rosten 和Tom_Drummond 在2006 年提出了FAST 算法。我们下面将会对此算法进行一个简单的介绍。你可以参考原始文献获得更多细节,本节中的所有图像都是来源于原始文章。
算法步骤
FAST算法的基本思想是通过对像素灰度值的快速比较来判断是否为角点。该算法的主要步骤如下:
- 选择一个像素点作为中心点。
- 选取中心点周围的16个像素点,分别计算它们与中心点的灰度差值。
- 判断中心点是否为角点。如果中心点与连续N个相邻像素点的灰度差值超过一个阈值T,或者与连续M个相邻像素点的灰度差值超过另一个阈值K,则认为中心点是角点。
FAST算法特征提取详细说明
1.在图像中选取一个像素点p,来判断它是不是关键点。Ip 等于像素点p的灰度值。
2.选择适当的阈值t。
3.如下图所示在像素点p 的周围选择16 个像素点进行测试。
4.如果在这16 个像素点中存在n 个连续像素点的灰度值高于于Ip + t,或者低于Ip −t,那么像素点p 就被认为是一个角点。如上图中的虚线所示,n 选取的值为12。
5. 为了获得更快的效果,还采用了额外的加速办法。首先对候选点的周围每个90 度的点:1,9,5,13 j进行测试,(先测1 和19, 如果它们符合阈值要求再测试 5 和13)。如果p 是角点,那么这四个点中至少有3 个要符合阈值要求。如果不是的话肯定不是角点,就放弃。对通过这步测试的点再继续进行测试,看是否有12 的点符合阈值要求。这个检测器的效率很高,但是它有如下几条缺点:
• 当n<12 时它不会丢弃很多候选点(获得的候选点比较多)。
• 像素的选取不是最优的,因为它的效果取决与要解决的问题点和角点的分布情况。
• 告诉测试的结果被抛弃
• 检测到的很多特征点都是连在一起的。
通过不断研究改进,前3 个问题可以通过机器学习的方法解决,最后一个问题可以使用非最大值抑制的方法解决。
机器学习的角点检测器
1. 选择一组训练练图片(最好是跟最后应用相关的图片)。
2. 使用FAST 算法找出每幅图像的特征点。
3. 对每一个特征点,将其周围的16 个像素存储构成一个向量。对所有图像都这样做构建一个特征向量 P。
4. 每一个特征点的16 像素点都属于下列三类中的一种。
5. 根据这些像素点的分类,特征向量 P 也被分为3 个子集:Pd、Ps、Pb
6. 定义一个新的布尔变 Kp,如果p 是角点就设置为Ture,如果不是就设置为False。
7. 使用ID3 算法(决策树分类器)Use the ID3 algorithm (decisiontree classifier) to query each subset using the variable Kp for theknowledge about the true class. It selects the x which yields the most information about whether the candidate pixel is a corner,measured by the entropy of Kp.
8. This is recursively applied to all the subsets until its entropy is zero.
9. 将构建好的决策树用于其他图像的快速的检测。
非极大值抑制
使用极大值抑制的方法可以解决检测到的特征点相连的问题。
- 对所有检测到到特征点构建一个打分函数V。V 就是像素点p 与周围16个像素点差值的绝对值之和。
- 计算临近两个特征点的打分函数V。
- 忽略V 值最低的特征点
总结
- FAST算法的优点是速度快(比其它角点检测算法都快),适用于实时的图像处理任务。但它也有一些限制,例如对于图像噪声较多或纹理不明显的情况下,检测结果可能不准确(噪声很高时不稳定)。
- 在使用FAST算法时,需要根据具体应用场景调整阈值N、阈值T和阈值K的取值,才能获得较好的检测效果。
- 除了FAST算法,还有其他一些常用的角点检测算法,如Harris角点检测、Shi-Tomasi角点检测等,可以根据实际需求选择合适的算法或者根据具体任务结合不同算法使用。
OpenCV的FAST算法实现
和其它特征点检测一样我们可以在OpenCV 中直接使用FAST 特征检测器。如果你愿意的话,你可以设置阈值,是否进行最大值抑制,使用的邻域大小等。邻域可以设置为下列3 中之一:cv2.FAST_FEATURE_DETECTOR_TYPE_5_8, cv2.FAST_FEATURE_DETECTOR_TYPE_7_12和cv2.FAST_FEATURE_DETECTOR_TYPE_9_16。下面是使用FAST 算法进行特征点检测的简单代码。
import numpy as np
import cv2
from matplotlib import pyplot as plt
img = cv2.imread('simple.jpg',0)
# Initiate FAST object with default values
fast = cv2.FastFeatureDetector()
# find and draw the keypoints
kp = fast.detect(img,None)
img2 = cv2.drawKeypoints(img, kp, color=(255,0,0))
# Print all default params
print ("Threshold: ", fast.getInt('threshold'))
print ("nonmaxSuppression: ", fast.getBool('nonmaxSuppression'))
print ("neighborhood: ", fast.getInt('type'))
print ("Total Keypoints with nonmaxSuppression: ", len(kp))
cv2.imwrite('fast_true.png',img2)
# Disable nonmaxSuppression
fast.setBool('nonmaxSuppression',0)
kp = fast.detect(img,None)
print ("Total Keypoints without nonmaxSuppression: ", len(kp))
img3 = cv2.drawKeypoints(img, kp, color=(255,0,0))
cv2.imwrite('fast_false.png',img3)
结果如下。第一幅图是使用了非最大值抑制的结果,第二幅没有使用非最大值抑制。
提醒说明
OpenCV的版本不同,常见特征器的方法可能会有不同,以下也可以参考。
在OpenCV-python中,可以使用cv2.FastFeatureDetector()函数来创建FAST角点检测器。该函数的用法如下:
fast = cv2.FastFeatureDetector_create(threshold=10, nonmaxSuppression=True, type=cv2.FAST_FEATURE_DETECTOR_TYPE_9_16, max_npoints=5000)
其中,参数的含义如下:
- threshold:阈值,用于判断像素点是否为角点。默认值为10。
- nonmaxSuppression:是否进行非最大值抑制,即在相邻的角点中只选择响应最大的角点。默认值为True。
- type:角点检测算法的类型。默认值为cv2.FAST_FEATURE_DETECTOR_TYPE_9_16,表示使用16个像素点进行快速比较。
- max_npoints:最大检测到的角点数量。默认值为5000。
在创建FAST角点检测器后,可以使用fast.detect()函数来检测图像中的角点。
FAST角点检测器的type参数定义了角点检测算法的类型。在OpenCV-python中,提供了以下几种类型:
- cv2.FAST_FEATURE_DETECTOR_TYPE_5_8:使用8个像素点进行快速比较。
- cv2.FAST_FEATURE_DETECTOR_TYPE_7_12:使用12个像素点进行快速比较。
- cv2.FAST_FEATURE_DETECTOR_TYPE_9_16:使用16个像素点进行快速比较。
使用示例:
import cv2
# 读取图像
image = cv2.imread("image.jpg")
# 创建FAST角点检测器
fast = cv2.FastFeatureDetector_create(threshold=10, nonmaxSuppression=True, type=cv2.FAST_FEATURE_DETECTOR_TYPE_9_16, max_npoints=5000)
# 检测角点
keypoints = fast.detect(image, None)
# 绘制角点
image_with_keypoints = cv2.drawKeypoints(image, keypoints, None, color=(0, 255, 0), flags=0)
# 显示结果
cv2.imshow("FAST", image_with_keypoints)
cv2.waitKey(0)
cv2.destroyAllWindows()
在上述示例中,创建FAST角点检测器时,通过参数设置了阈值为10,进行非最大值抑制,使用16个像素点进行快速比较,并设置最大检测到的角点数量为5000。