博客中已经介绍了很多图像特征检测算子,我们可以用LoG或者DoG检测图像中的Blobs(斑点检测),可以根据图像局部的自相关函数来求得Harris角点(Harris角点),后面又提到了两种十分优秀的特征点及它们的描述方法SIFT特征与SURF特征。SURF特征算是为了提高运算效率对SIFT特征的一种近似,虽然在有些实验环境中已经达到了实时,但是我们实践工程应用中,特征点的提取与匹配只是整个应用算法中的一部分,所以我们对于特征点的提取必须有更高的要求,从这一点来看前面介绍的的那些特征点方法都不可取。
为了解决这个问题,Edward Rosten和Tom Drummond在2006年发表的“Machine learning for high-speed corner detection[1]”文章中提出了一种FAST特征,并在2010年对这篇论文作了小幅度的修改后重新发表[2]。FAST的全称为Features From Accelerated Segment Test。Rosten等人将FAST角点定义为:若某像素点与其周围领域内足够多的像素点处于不同的区域,则该像素点可能为角点。也就是某些属性与众不同,考虑灰度图像,即若该点的灰度值比其周围领域内足够多的像素点的灰度值大或者小,则该点可能为角点。
图1 FAST特征点示意图
现在,如果在这个大小为16个像素的圆上有n n个连续的像素点,它们的像素值要么都比I p +t Ip+t大,要么都比I p −t Ip−t小,那么它就是一个角点。(如图1中的白色虚线所示)。n n的值可以设置为12或者9,实验证明选择9可能会有更好的效果。
上面的算法中,对于图像中的每一个点,我们都要去遍历其邻域圆上的16个点的像素,效率较低。我们下面提出了一种高效的测试(high-speed test)来快速排除一大部分非角点的像素。该方法仅仅检查在位置1,9,5和13四个位置的像素,首先检测位置1和位置9,如果它们都比阈值暗或比阈值亮,再检测位置5和位置13。如果P P是一个角点,那么上述四个像素点中至少有3个应该必须都大于I p +t Ip+t或者小于I p −t Ip−t,因为若是一个角点,超过四分之三圆的部分应该满足判断条件。如果不满足,那么p p不可能是一个角点。对于所有点做上面这一部分初步的检测后,符合条件的将成为候选的角点,我们再对候选的角点,做完整的测试,即检测圆上的所有点。
上面的算法效率实际上是很高的,但是有点一些缺点:
当我们设置n<12 n<12时就不能使用快速算法来过滤非角点的点;
检测出来的角点不是最优的,这是因为它的效率取决于问题的排序与角点的分布;
对于角点分析的结果被丢弃了;
多个特征点容易挤在一起。
S p→x =⎧ ⎩ ⎨ ⎪ ⎪ d,s,b, I p→x ≤I p –tI p −t≤I p→x <I p +tI p +t≤I p→x (darker)(similar)(brighter) Sp→x={d,Ip→x≤Ip–t(darker)s,Ip−t≤Ip→x
P b ={p∈P:S p→x =b} Pb={p∈P:Sp→x=b}
换句话说,对于任意给定的位置x x,它都可以把所有图像中的点分为三类,第一类P d Pd包括了所有位置x x处的像素在阈值t t下暗于中心像素,第二类P s Ps包括了所有位置x x处的像素在阈值t t下近似于中心像素,P b Pb包括了所有位置x x处的像素在阈值t t下亮于中心像素。从邻近的位置选取了多个特征点是另一个问题,我们可以使用Non-Maximal Suppression来解决。
在OpenCV中进行FAST特征提取的函数为FAST。它一共有4个参数,第一个参数是输入的图像,第二个是返回的特征点,第三个是定义的阈值,第四个决定是否使用非极大值抑制。
void FAST(InputArray image, vector& keypoints, int threshold, bool nonmaxSuppression=true )
C++: void FASTX(InputArray image, vector& keypoints, int threshold, bool nonmaxSuppression, int type)
另外还有一个接口为FASTX,它提供了第五个参数type用来指定FAST检测中像素邻域圆的参数:TYPE_9_16、TYPE_7_12、TYPE_5_8。
#include
#include
#include
#include
using namespace cv;
using namespace std;
int main(int argc, char** argv)
{
Mat img = imread("box.png");
std::vector keypoints;
FAST(img, keypoints, 20);
//-- Draw keypoints
Mat img_keypoints;
drawKeypoints(img, keypoints, img_keypoints, Scalar::all(-1), DrawMatchesFlags::DEFAULT);
//-- Show detected (drawn) keypoints
imshow("Keypoints", img_keypoints);
waitKey(0);
return 0;
}
FAST算法比其他已知的角点检测算法要快很多倍,但是当图片中的噪点较多时,它的健壮性并不好,而且算法的效果还依赖于一个阈值t t。而且FAST不产生多尺度特征而且FAST特征点没有方向信息,这样就会失去旋转不变性。
[1] 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.
[2] 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.