OpenCV Python FAST(Features from Accelerated Segment Test) 算法角点检测
【目标】
- 理解FAST算法的理论基础;
- 用OpenCV里的FAST 检测角点;
【理论】
我们看到了几个特征检测器,其中很多都非常好。但是从实时应用程序的角度来看,它们还不够快。一个最好的例子是SLAM ( Simultaneous Localization and Mapping ) 移动机器人,它的计算资源有限。
作为一种解决方案,FAST (feature from Accelerated Segment Test) 算法由Edward Rosten 和 Tom Drummond 在2006年的论文《Machine learning for high-speed corner detection 》中提出,(后来在2010年进行了修订)。下面是对该算法的基本总结。详情请参考原论文(所有图片均取自原论文)。
利用FAST进行特征检测
- 选择一个像素 p(被判断是否为感兴趣的点), 设它的亮度为 Ip;
- 选择一个适当的阈值 t;
- 假定该点的 16 邻域将被用于测试;
- 如果 p 周围有n个连续点亮于 p, 或者 暗于 p, 则该点为 FAST 的角点。n 一般选择为 12;
- 一个快速的去除非角点的方法是,只测试考虑1、9、5、13等点,亮度同时超过或低于 p 点的像素超过3个,则认为是角点,否则为非角点。它有以下缺点:
- 当 n < 12 时,它不会拒绝尽可能多的候选;
- 像素的选择不是最有的,因为它的效率取决于问题的顺序和角点的分布;
- 高速测试的结果被丢弃;
- 多个特征点相邻;
前三点是用机器学习方法解决的。最后一个是使用非最大抑制来解决的。
机器学习角点检测器
- 选择一批图像用于训练,最好是选择应用领域的图像;
- 运行FAST算法在每张图像中找到特征点。
- 对于每个特征点,存储其 16 个邻域像素为一个 vector,对所有图像都进行;
- 对于每个像素来说,都可能存在3种以下情况:
- 基于这些状态,这些特征向量被分为3个子集 P d , P s , P b P_d,P_s,P_b Pd,Ps,Pb
- 定义一个布尔向量, K p K_p Kp, 如果 p p p 是角点,则为真,否则为假;
- 利用ID3算法 (决策树分类器)使用变量 K p K_p Kp查询每个子集
- 这将递归应用所有子集,直到熵为零;
- 这样创建的决策树用于其他图像的快速检测;
非极大抑制
在相邻位置检测多个兴趣点是另一个问题。采用非极大抑制法求解。
- 为所有检测到的特征点计算一个评分函数 V V V, V V V 是 p p p 与周围16个像素值的绝对差值之和;
- 考虑两个相邻的关键点并计算它们的 V V V值。
- 丢弃 V V V值较低的。
总结
该算法比其他的角点检测快几倍;但是对于噪声来说并不鲁棒,依赖于阈值;
【代码】
import numpy
import cv2
from matplotlib import pyplot as plt
# 读取图片
img = cv2.imread("assets/blox.jpg", 0)
colorim = cv2.imread("assets/blox.jpg", 1)
# 创建Fast检测
fast = cv2.FastFeatureDetector_create()
# Fast 特征检测
kp = fast.detect(img, None)
# 画特征点
img2 = cv2.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)) )
# 关闭非极大值抑制
fast.setNonmaxSuppression(0)
kp = fast.detect(img, None)
print("Total Keypoints without nonmaxSuppression: {}".format(len(kp)))
img3 = cv2.drawKeypoints(img, kp, None, color=(255, 0, 0))
cv2.imshow("img2", img2)
cv2.imshow("img3", img3)
cv2.waitKey(0)
cv2.destroyAllWindows()
- 输出
Threshold: 10
nonmaxSuppression:True
neighborhood: 2
Total Keypoints with nonmaxSuppression: 431
Total Keypoints without nonmaxSuppression: 1575
【接口】
- FastFeatureDetector_create
cv2.FastFeatureDetector_create( [, threshold[, nonmaxSuppression[, type]]] ) -> retval
- type: FastFeatureDetector::DetectorType; TYPE_5_8/TYPE_7_12/TYPE_9_16
# 获得算法名称ID,
# Reimplemented in cv::AKAZE, cv::KAZE, cv::SimpleBlobDetector, cv::GFTTDetector, cv::AgastFeatureDetector, cv::FastFeatureDetector, cv::MSER, cv::ORB, cv::BRISK, cv::SIFT, and cv::AffineFeature.
cv.FastFeatureDetector.getDefaultName( ) -> retval
# 是否采用了非极大值抑制
cv.FastFeatureDetector.getNonmaxSuppression( ) -> retval
# FAST的阈值
cv.FastFeatureDetector.getThreshold( ) -> retval
# FAST Detector 类型
cv.FastFeatureDetector.getType( ) -> retval
# 设置非极大值抑制
cv.FastFeatureDetector.setNonmaxSuppression( f ) -> None
# 设置阈值
cv.FastFeatureDetector.setThreshold( threshold ) -> None
# 设置类型
cv.FastFeatureDetector.setType( type ) -> None
【参考】
- OpenCV 官方文档
- 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. Pattern Analysis and Machine Intelligence, 2010, vol 32, pp. 105-119.
- FastFeatureDetector Class Reference