特征点匹配——FAST特征点检测
FAST(Fast Feature Detection)是一种高速角点检测算法,在ECCV 2006上发表于Edward Rosten的论文《Machine learning for high-speed corner detection》中。该算法通过判断以特征点为中心的圆周上的像素点变化来检测特征点,并结合机器学习方法提高了检测效率和准确性。原始方法通过检查16个像素点的变化趋势来判断特征点,并引入快速过滤机制以减少计算量;然而该方法存在对阈值敏感、假定像素分布等问题。为了解决这些问题,作者提出了一种基于学习的特征点检测方法:首先在多张图像中提取角点作为训练数据,并利用决策树对这些数据进行分类;然后通过决策树进行特征点检测并结合非最大值抑制消除密集特征点。此外,在OpenCV中并未直接使用此算法的原因在于其主要针对通用场景而非特定场景下的优化目标。
该算法Fast是一种基于计算机视觉领域高速角点检测的技术,在ECCV 2006会议上首次发布并提出了一种新的方法论。通过其论文标题《机器学习在快速角点检测中的应用》可以看出,这种方法的核心目标即为快速精确地识别图像中的关键点。
一、原始检测方法
为了确定一个点p是否为特征点,则需绘制以p为中心的圆,并观察该圆周围共有多少个像素。
在此基础上,在这些16个像素中,至少需要找到n个连续的像素序列满足其灰度均高于或低于I_p加上/减去t。
若上述条件得到满足,则可判定该点为特征点;否则则不被视为特征点。
其中参数t通常取值为12。

在进行图像特征点检测时,必须遍历图像中的每一个像素。然而,在实际应用中发现,并非所有像素都具有显著的特征属性。因此,在传统方法中会对每一个像素执行上述的检测流程,这必然导致大量时间的消耗。为了优化计算效率,在论文中提出了一种新的非特征判别策略:对于输入图像中的每一个目标候选区域(如图所示),我们首先提取第1、5、9、13号位置的像素值进行比较判断;如果这4个位置中的任意一个不满足与周围值的关系,则可以直接判定该区域不具备显著特性并予以剔除;反之,则需进一步执行第4步操作以确定最终结果。这种方法在很大程度上降低了运算复杂度并提高了算法运行效率;然而,在实际应用过程中仍存在以下不足:当参数n小于12时无法采用上述方法对非角点实施快速筛选;其次,在处理边缘情况时可能忽略一些关键信息;此外,在实际运行过程中发现这种方法存在一定的局限性;最后,在某些特定条件下可能会导致错误结果出现
二、基于学习的特征点检测方法
这种基于学习的特征点检测方法分成两个阶段,如下所示:
阶段1: 对你需要检测的场景的多张图像进行角点提取,在提取的过程中,使用你给定的和一个合适的阈值进行检测,同时这里不使用上面提出的先检测4个像素点的方法(因为你选择的可能小于12啊)。这样我们就提取到了许多的特征点,作为训练数据。
对于圆上的16像素点位置x \in \{1,...,16\},若选择一个位置x对上面得到的特征点集进行划分,划分为3个部分,如下:
在进一步处理中,在第二阶段中,在采用ID3算法构建一棵决策树的过程中,在某个特定的像素位置上进行图像特征划分时,则需计算集合P的熵值K(其中c代表角点的数量),以及非角点的数量\overline c。基于此基础所得出的信息增益值即为此处关注的核心指标。
在信息增益最大的位置上实施划分,在此过程中获得一棵决策树。当遇到类似情况时,则采用该决策树来进行特征点检测。
三、非最大值抑制
在角点检测过程中,还存在一个关键问题:如何解决特征点过于密集导致重叠的问题?
在此处中S_{bright}代表的是16个邻域像素点中灰度值超过I_p + t的所有像素点集合;而S_{dark}则包含了那些灰度值低于I_p - t的所有像素点。直至完成整个FAST特征点检测流程时,在OpenCV库中并未提供基于学习方法来识别特征点的原因也很简单因为OpenCV库显然是不针对特定场景设计的。例如,在OpenCV中使用FAST算法的具体操作如下:
#include <opencv2\imgproc\imgproc.hpp>
#include <opencv2\highgui\highgui.hpp>
#include <opencv2\features2d\features2d.hpp>
#include <vector>
using namespace std;
using namespace cv;
int main()
{
Mat img = imread("1.jpg");
vector<KeyPoint> keypoints; //KeyPoint是opencv中定义的特征点类
FastFeatureDetector fast(40); //定义FAST特征检测器,这里的40是算法中的阈值t
fast.detect(img, keypoints); //检测img图像,特征点存在keypoints中
for (size_t i = 0; i < keypoints.size(); i++)
{
circle(img, Point(keypoints[i].pt.x, keypoints[i].pt.y), 2, Scalar(0, 255, 0), 1);
}
imshow("1.jpg", img);
waitKey(0);
return 0;
}
值得注意的是,在OpenCV库中还存在一个名为FAST[函数]的功能。我最初使用的这个功能进行测试时发现了一些问题——然而检测结果却不尽如人意。这表明实际检测结果与预期不符。

