FAST(Features fromaccelerated segment test)是一种角点检测方法,它可以用于特征点的提取,并完成跟踪和映射物体。FAST角点检测算法最初是由Edward Rosten和Tom Drummond提出,该算法最突出的优点是它的计算效率。正如它的缩写名字,它很快而且事实上它比其他著名的特征点提取方法(如SIFT,SUSAN,Harris)都要快。而且如果应用机器学习方法的话,该算法能够取得更佳的效果。正因为它的快速特点,FAST角点检测方法非常适用于实时视频处理的领域。
该算法的基本原理是使用圆周长为16个像素点(半径为3的Bresenham圆)来判定其圆心像素P是否为角点。在圆周上按顺时针方向从1到16的顺序对圆周像素点进行编号。如果在圆周上有N个连续的像素的亮度都比圆心像素的亮度Ip加上阈值t还要亮,或者比圆心像素的亮度减去阈值还要暗,则圆心像素被称为角点。因此要想成为角点,必须满足下列两个条件之一:
条件1:集合S由圆周上N个连续的像素x组成,Ix > Ip + t;
条件2:集合S由圆周上N个连续的像素x组成,Ix < Ip - t。
N一般选择为12。
在一幅图像中,非角点往往是占多数,而且非角点检测要比角点检测容易得多,因此首先剔除掉非角点将大大提高角点检测速度。由于N为12,所以编号为1,5,9,13的这4个圆周像素点中应该至少有三个像素点满足角点条件,圆心才有可能是角点。因此首先检查1和9像素点,如果I1和I9在[Ip –t, Ip + t]之间,则圆心肯定不是角点,否则再检查5和13像素点。如果这4个像素中至少有三个像素满足亮度高于Ip+t或低于Ip –t,则进一步检查圆周上其余像素点。
以上方法还是有不够鲁棒的地方,但可以通过机器学习和非极大值抑制的方法来增强鲁棒性。由于opencv中相关的函数没有使用机器学习,因此我们这里只介绍非极大值抑制的方法。由于分割测试并没有计算角点响应函数,因此常规的非极大值抑制方法并不适用于FAST算法。下面是FAST的非极大值抑制方法:
1、计算得分函数,它的值V是特征点与其圆周上16个像素点的绝对差值中所有连续10个像素中的最小值的最大值,而且该值还要大于阈值t;
2、在3×3的特征点邻域内(而不是图像邻域),比较V;
3、剔除掉非极大值的特征点。
FAST角点检测方法的具体步骤为:
1、在圆周上的部分像素点上,进行非角点的检测;
2、如果初步判断是角点,则在圆周上的全部像素点上进行角点检测;
3、对角点进行非极大值抑制,得到角点输出。
在opencv中,实现FAST算法的核心函数有两个,它们的原型为:
void FAST(InputArray image, vector<KeyPoint>& keypoints, int threshold, bool nonmaxSuppression=true )
void FASTX(InputArray image, vector<KeyPoint>& keypoints, int threshold, bool nonmaxSuppression, int type)
image为输入图像,要求是灰度图像
keypoints为检测到的特征点向量
threshold为阈值t
nonmaxSuppression为是否进行非极大值抑制,true表示进行非极大值抑制
type为选取圆周像素点的个数,是8(FastFeatureDetector::TYPE_5_8)、12(FastFeatureDetector::TYPE_7_12)还是16(FastFeatureDetector::TYPE_9_16)。该参数是FAST函数和FASTX函数的区别,事实上,FAST函数是调用FASTX函数,而传入的type值为FastFeatureDetector::TYPE_9_16。
FAST角点检测方法是在sources/modules/features2d/src/fast.cpp文件内定义的:void FAST(InputArray _img, std::vector<KeyPoint>& keypoints, int threshold, bool nonmax_suppression)
{
//调用FASTX函数
FASTX(_img, keypoints, threshold, nonmax_suppression, FastFeatureDetector::TYPE_9_16);
}
FASTX函数的作用是调用一个函数模板,模板的参数值是根据参数type的不同而定义的所使用的圆周像素的个数:
void FASTX(InputArray _img, std::vector<KeyPoint>& keypoints, int threshold, bool nonmax_suppression, int type)
{
switch(type) {
case FastFeatureDetector::TYPE_5_8:
FAST_t<8>(_img, keypoints, threshold, nonmax_suppression);
break;
case FastFeatureDetector::TYPE_7_12:
FAST_t<12>(_img, keypoints, threshold, nonmax_suppression);
break;
case FastFeatureDetector::TYPE_9_16:
#ifdef HAVE_TEGRA_OPTIMIZATION
if(tegra::FAST(_img, keypoints, threshold, nonmax_suppression))
break;
#endif
FAST_t<16>