本博客内容来源于网络以及其他书籍,结合自己学习的心得进行重编辑,因为看了很多文章不便一一标注引用,如图片文字等侵权,请告知删除。
学习笔记目录----->传送门 <-----
前言
有关角点的知识可以在Harris角点学习笔记中查看。虽然有很多的角点检测算法,有一些也能够达到实时,但是我们要在实时性更高的系统上使用,比如vslam,则需要更快点的角点提取算法,来为其他操作节省时间。
那么Edward Rosten和Tom Drummond于2006年提出了一种FAST特征点检测方法,并在2010年稍作修改后发表了《Features From Accelerated Segment Test》,简称FAST(也确实是快,优秀的命名)。接下来,我们详细解析一下FAST角点检测方法
FAST角点检测思路
FAST角点定义与合理性
总的来说FAST角点检测还是比较简单的,那么让我们来看看作者是怎么定义FAST角点的
- FAST角点:若某像素与其周围邻域内足够多的像素点相差较大,则该像素可能是角点。
我们来看一个例子,帮助理解:
从上图上我们可以看出,放大后的右图中心像素点P的灰度值明显要比周围圆上的像素点1-16的灰度值要小,并且很多的像素值的相差比较大,则此点就有可能是角点。
这个通过对比平坦的图以及边缘图还是比较好理解的,在平坦的图上,周围的像素点应该和中心点的差距是比较小;在边缘上,周围的像素点应该一半差距比较大,一半基本上没有差距;而在角点上,应该时大多数的差距比较大,而少数的差距比较小。
所以提取特征点,就是通过一定的特征划分,将不同的像素点分开,属于同一特征下的在某个维度具有极高的结构或属性相似性。
FAST算法流程
在上述我们理解FAST角点定义的合理性之后,我们来看一下,FAST角点算法的流程,仍旧以上面的图为例。
- 我们仍旧选择一个点,不妨仍设这个点为像素点P。我们首先把它的亮度值设为Ip。
- 虑以该像素点为中心的一个半径等于3像素的离散化的Bresenham圆,这个圆的边界上有16个像素,分别为p1 ~ p16,亮度值分别为Ip1 ~ Ip16。
- 我们选定一个阈值t,t做什么的我们接下来看。
- 首先计算p1、p9、p5、p13(分别在四个方向的四个点)与中心p的像素差,若它们的绝对值有至少3个超过阈值t,则当做候选角点,再进行下一步考察;否则,不可能是角点;
- 在p是候选点的情况下,计算p1到p16这16个点与中心p的像素差,若它们有至少连续9个超过阈值(也可以测试其他大小,实验表明9的效果更好),则是角点;否则,不是角点。
- 对完整图进行1-5 的角点判断。
-
对完整图像进行非极大值抑制,目的去除小区域内多个重复的特征点:
7.3. 得分计算公式如下(公式中用V表示得分,t表示阈值):
7.1. 计算特征点出的FAST得分值(或者说响应值),即16个点与中心差值的绝对值总和。
7.2. 判断以特征点p为中心的一个邻域(可以设为3x3或着5x5)内,若有多个特征点,则判断每个特征点的响应值,如果p是其中最大的,则保留,否则,删除。如果只有一个特征点,就保留。
FAST角点检测性能
可以看出FAST特征点的计算方式非常简单,计算速度也是相对于其他方式也是非常快的,但是还是有一些缺点:
- 在首先的四点检测里,只有2个点同中心点不相似,也并不能说明这不是角点(我们是不是可以在这优化一下,保留更多的角点)。
- 前面的四点检测结果和后面的16点检测的计算有一定重复。
- 检测出来的角点不一定是最优的,这是因为它的效率取决于问题的排序与角点的分布。
虽然FAST有一些缺点,但并不妨碍FAST角点检测,是一个优秀的方法,其中使用最常见的就是为其他特征点的提取,进行快速的过滤。比如先进性FAST特征提取,在进行Harris角点去,就可以加快,整个Harris角点提取的速度了。 再比如在ORB-SLAM中,orb特征点的提取就依赖了FAST角点提取的快速稳定。在之后我们会讲解关于ORB特征点的提取。
OpenCV 使用中FAST角点检测效果[代码]
#include <iostream>
#include <opencv2/opencv.hpp>
int main(int argc, char *argv[])
{
int thread_value = 30;
cv::Mat orignal_image = cv::imread (argv[1]);
cv::Mat gray_image , after_fast_image;
cv::cvtColor (orignal_image,gray_image,CV_BGR2GRAY); // 灰度变换
std::vector<cv::KeyPoint> keypoints;
cv::FAST(gray_image, keypoints,thread_value);
cv::drawKeypoints(orignal_image, keypoints, after_fast_image, cv::Scalar::all(-1), cv::DrawMatchesFlags::DEFAULT);
cv::imshow("after_fast_corner", after_fast_image);
cv::imwrite("after_fast_corner.png",after_fast_image);
cv::waitKey(0);
return 0;
}
下面是我自己选的一张图出来的效果,可以看到在角点检测的效果还是不错的,角点的地方还是找的比较密集的,当然和阈值的设置也有关系,可以去对比我Harris的效果去做对比。
重要的事情说三遍:
如果您看到我的文章对您有所帮助,那就点个赞呗 ( * ^ __ ^ * )
如果您看到我的文章对您有所帮助,那就点个赞呗( * ^ __ ^ * )
如果您看到我的文章对您有所帮助,那就点个赞呗( * ^ __ ^ * )
任何人或团体、机构全部转载或者部分转载、摘录,请保留本博客链接或标注来源。博客地址:开飞机的乔巴
作者简介:开飞机的乔巴(WeChat:zhangzheng-thu),现主要从事机器人抓取视觉系统以及三维重建等3D视觉相关方面,另外对slam以及深度学习技术也颇感兴趣,欢迎加我微信或留言交流相关工作。