目标
在本章中,
- 我们将了解 FAST 算法的基础知识
- 我们将使用 OpenCV 功能来查找 FAST 算法的角点。
理论
我们已经看到了几种特征检测器,其中许多都非常好。但是从实时应用的角度来看,它们的速度不够快。一个最好的例子是 SLAM(即时定位与地图构建)移动机器人,它具有有限的计算资源。
为了解决这个问题,Edward Rosten 和 Tom Drummond 在 2006 年的论文《用于高速角点检测的机器学习》(后来在 2010 年修订)中提出了 FAST(来自加速分割测试的特征)算法。下面是该算法的基本摘要。更多详细信息请参阅原始论文(所有图像均来自原始论文)。
使用 FAST 进行特征检测
- 在图像中选择一个像素 \(p\) ,该像素将被识别为兴趣点。设其强度为 \(I_p\)。
- 选择适当的阈值 \(t\)。
- 考虑以被测像素为中心的 16 个像素的圆。(请参见下图)
image
- 现在,如果圆(16 个像素)中存在一组 \(n\) 个连续像素,它们都比 \(I_p + t\) 亮,或者都比 \(I_p − t\) 暗,则像素 \(p\) 是角点。(如上图中的白色虚线所示)。\(n\) 被选为 12。
- 提出了一个高速测试来排除大量非角点。此测试仅检查 1、9、5 和 13 处的四个像素(首先测试 1 和 9 是否太亮或太暗。如果是,则检查 5 和 13)。如果 \(p\) 是角点,则其中至少三个必须都比 \(I_p + t\) 亮或比 \(I_p − t\) 暗。如果两者都不是,则 \(p\) 不能是角点。然后可以通过检查圆中的所有像素将完整的分段测试标准应用于通过的候选像素。此检测器本身表现出高性能,但存在几个缺点
- 对于 n < 12,它不会拒绝很多候选像素。
- 像素的选择不是最佳的,因为其效率取决于问题的排序和角点外观的分布。
- 高速测试的结果被丢弃。
- 多个特征被检测到彼此相邻。
前 3 点通过机器学习方法解决。最后一个使用非极大值抑制解决。
机器学习角点检测器
- 选择一组用于训练的图像(最好来自目标应用领域)
- 在每个图像中运行 FAST 算法以找到特征点。
- 对于每个特征点,将周围的 16 个像素存储为向量。对所有图像执行此操作以获取特征向量 \(P\)。
- 这 16 个像素中的每个像素(例如 \(x\))可以具有以下三种状态之一
image
- 根据这些状态,特征向量 \(P\) 被细分为 3 个子集,\(P_d\),\(P_s\),\(P_b\)。
- 定义一个新的布尔变量 \(K_p\),如果 \(p\) 是角点,则为 true,否则为 false。
- 使用 ID3 算法(决策树分类器)来查询每个子集,使用变量 \(K_p\) 来了解有关真实类的信息。它选择 \(x\),它通过 \(K_p\) 的熵来衡量,可以产生关于候选像素是否为角点的最多信息。
- 递归地将其应用于所有子集,直到其熵为零。
- 如此创建的决策树用于在其他图像中进行快速检测。
非极大值抑制
在相邻位置检测多个兴趣点是另一个问题。它通过使用非极大值抑制来解决。
- 为所有检测到的特征点计算得分函数 \(V\)。\(V\) 是 \(p\) 和 16 个周围像素值之间的绝对差之和。
- 考虑两个相邻的关键点并计算它们的 \(V\) 值。
- 丢弃 \(V\) 值较低的那个。
总结
它比其他现有的角点检测器快几倍。
但是它对高水平的噪声不鲁棒。它依赖于阈值。
OpenCV 中的 FAST 特征检测器
它被称为 OpenCV 中的任何其他特征检测器。如果需要,可以指定阈值,是否应用非极大值抑制,要使用的邻域等。
对于邻域,定义了三个标志,cv.FAST_FEATURE_DETECTOR_TYPE_5_8、cv.FAST_FEATURE_DETECTOR_TYPE_7_12 和 cv.FAST_FEATURE_DETECTOR_TYPE_9_16。以下是如何检测和绘制 FAST 特征点的简单代码。
import numpy as np
import cv2 as cv
from matplotlib import pyplot as plt
img =
cv.imread(
'blox.jpg', cv.IMREAD_GRAYSCALE)
fast = cv.FastFeatureDetector_create()
kp = fast.detect(img,None)
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)) )
void drawKeypoints(InputArray image, const std::vector< KeyPoint > &keypoints, InputOutputArray outImage, const Scalar &color=Scalar::all(-1), DrawMatchesFlags flags=DrawMatchesFlags::DEFAULT)
绘制关键点。
CV_EXPORTS_W bool imwrite(const String &filename, InputArray img, const std::vector< int > ¶ms=std::vector< int >())
将图像保存到指定文件。
CV_EXPORTS_W Mat imread(const String &filename, int flags=IMREAD_COLOR_BGR)
从文件加载图像。
查看结果。第一张图像显示了带有 nonmaxSuppression 的 FAST,第二张图像显示了没有 nonmaxSuppression 的 FAST
image
附加资源
- Edward Rosten 和 Tom Drummond,“用于高速角点检测的机器学习”,载于第九届欧洲计算机视觉会议,第 1 卷,2006 年,第 430-443 页。
- Edward Rosten、Reid Porter 和 Tom Drummond,“更快更好:一种角点检测的机器学习方法”,载于 IEEE Trans。模式分析和机器智能,2010 年,第 32 卷,第 105-119 页。