目标
在这一章中
- 我们将了解FAST算法的基础知识
- 我们将发现在FAST算法中使用OpenCV功能的角落。
理论
我们看到了几个特征检测器,其中许多确实很好。但是当从实时应用的角度来看,它们的速度不够快。一个最好的例子是SLAM(同步定位和测绘)移动机器人,它的计算资源有限。
为了解决这个问题,Edward Rosten和Tom Drummond于2006年在他们的论文 "Machine learning for high-speed corner detection "中提出了FAST(Features from Accelerated Segment Test)算法(后来在2010年修订)。以下是该算法的基本摘要。更多细节请参考原始论文(所有图片均来自原始论文)。
使用FAST进行特征检测
- 在图像中选择一个像素p,该像素将被识别为一个兴趣点或不是。让它的强度为Ip。
- 选择适当的阈值t。
- 考虑在被测试的像素周围有一个16个像素的圆。(见下面的图片)
- 现在,如果在圆形(16个像素)中存在一组n个连续的像素,它们都比Ip+t更亮,或者都比Ip-t更暗,那么像素p就是一个角。(在上图中显示为白色虚线)。
- 有人提出了一个高速测试,以排除大量的非角点。这个测试只检查1、9、5和13的四个像素(首先测试1和9是否太亮或太暗。如果是的话,再检查5和13)。如果p是一个角,那么其中至少有三个必须都比Ip+t更亮或比Ip-t更暗。如果这两者都不是,那么p就不可能是一个角。然后,通过检查圆圈中的所有像素,可以将全段测试标准应用于通过的候选人。这个检测器本身就表现出很高的性能,但也有几个弱点:
-
- 对于n<12的情况,它不能拒绝那么多的候选者。
-
- 像素的选择不是最佳的,因为它的效率取决于问题的排序和角落出现的分布。
-
- 高速测试的结果被扔掉了。
-
- 多个特征被检测到彼此相邻。
前3点是用机器学习的方法解决的。最后一个是用非最大抑制法解决的。
机器学习角点检测器
- 选择一组图像进行训练(最好是来自目标应用领域)。
- 在每个图像中运行FAST算法,以找到特征点。
- 对于每个特征点,将其周围的16个像素存储为一个向量。
- 对所有的图像都这样做,得到特征向量P。
这16个像素中的每个像素(例如x)可以有以下三种状态之一:
- 根据这些状态,特征向量P被细分为3个子集,Pd, Ps, Pb。
- 定义一个新的布尔变量,Kp,如果p是一个角,则为真,否则为假。
- 使用ID3算法(决策树分类器)来查询每个子集,使用变量Kp来获取关于真实类别的知识。它选择产生关于候选像素是否是角落的最多信息的x,由Kp的熵来衡量。
- 这将递归地应用于所有的子集,直到其熵为零。
- 这样创建的决策树被用于其他图像的快速检测。
非最大值抑制
检测相邻位置的多个兴趣点是另一个问题。它是通过使用非最大抑制来解决的。
- 为所有检测到的特征点计算一个分数函数,即V。V是p和周围16个像素值的绝对差异之和。
- 考虑两个相邻的关键点并计算它们的V值。
- 丢弃V值较低的那个。
总结
它比其他现有的角落检测器快几倍。
但它对高水平的噪声并不稳定。它依赖于一个阈值。
OpenCV中的FAST特征检测器
它和OpenCV中的其他特征检测器一样被调用。如果你愿意,你可以指定阈值,是否应用非最大抑制,使用的邻域等。
对于邻域,定义了三个标志:cv.FAST_FEATURE_DETECTOR_TYPE_5_8,cv.FAST_FEATURE_DETECTOR_TYPE_7_12和cv.FAST_FEATURE_DETECTOR_TYPE_9_16。下面是一个关于如何检测和绘制FAST特征点的简单代码。
import numpy as np
import cv2 as cv
from matplotlib import pyplot as plt
img = cv.imread('blox.jpg',0) # `<opencv_root>/samples/data/blox.jpg`
# 用默认值启动FAST对象
fast = cv.FastFeatureDetector_create()
# 找到并画出关键点
kp = fast.detect(img,None)
img2 = cv.drawKeypoints(img, kp, None, color=(255,0,0))
# 打印所有默认参数
print( "Threshold: {}".format(fast.getThreshold()) )
print( "nonmaxSuppression:{}".format(fast.getNonmaxSuppression()) )
print( "neighborhood: {}".format(fast.getType()) )
print( "Total Keypoints with nonmaxSuppression: {}".format(len(kp)) )
cv.imwrite('fast_true.png', img2)
# 禁用nonmaxSuppression
fast.setNonmaxSuppression(0)
kp = fast.detect(img, None)
print( "Total Keypoints without nonmaxSuppression: {}".format(len(kp)) )
img3 = cv.drawKeypoints(img, kp, None, color=(255,0,0))
cv.imwrite('fast_false.png', img3)
请看结果。第一张图片显示的是有非最大限度抑制的FAST,第二张是没有非最大限度抑制的:
其他资源
- Edward Rosten和Tom Drummond,“高速转角检测的机器学习”,载于第九届欧洲计算机视觉会议,第一卷,2006年,第430-443页(Edward Rosten and Tom Drummond, “Machine learning for high speed corner detection” in 9th European Conference on Computer Vision, vol. 1, 2006, pp. 430–443)。
- Edward Rosten, Reid Porter, and Tom Drummond, “Faster and better: a machine learning approach to corner detection” in IEEE Trans. 模式分析和机器智能,2010年,第32卷,第105-119页(Edward Rosten, Reid Porter, and Tom Drummond, “Faster and better: a machine learning approach to corner detection” in IEEE Trans. Pattern Analysis and Machine Intelligence, 2010, vol 32, pp. 105-119)。