目标

在这一章中

  • 我们将了解FAST算法的基础知识
  • 我们将发现在FAST算法中使用OpenCV功能的角落。

理论

我们看到了几个特征检测器,其中许多确实很好。但是当从实时应用的角度来看,它们的速度不够快。一个最好的例子是SLAM(同步定位和测绘)移动机器人,它的计算资源有限。

为了解决这个问题,Edward Rosten和Tom Drummond于2006年在他们的论文 "Machine learning for high-speed corner detection "中提出了FAST(Features from Accelerated Segment Test)算法(后来在2010年修订)。以下是该算法的基本摘要。更多细节请参考原始论文(所有图片均来自原始论文)。

使用FAST进行特征检测

  1. 在图像中选择一个像素p,该像素将被识别为一个兴趣点或不是。让它的强度为Ip
  2. 选择适当的阈值t
  3. 考虑在被测试的像素周围有一个16个像素的圆。(见下面的图片)
  4. 现在,如果在圆形(16个像素)中存在一组n个连续的像素,它们都比Ip+t更亮,或者都比Ip-t更暗,那么像素p就是一个角。(在上图中显示为白色虚线)。
  5. 有人提出了一个高速测试,以排除大量的非角点。这个测试只检查1、9、5和13的四个像素(首先测试1和9是否太亮或太暗。如果是的话,再检查5和13)。如果p是一个角,那么其中至少有三个必须都比Ip+t更亮或比Ip-t更暗。如果这两者都不是,那么p就不可能是一个角。然后,通过检查圆圈中的所有像素,可以将全段测试标准应用于通过的候选人。这个检测器本身就表现出很高的性能,但也有几个弱点:
  • 对于n<12的情况,它不能拒绝那么多的候选者。
  • 像素的选择不是最佳的,因为它的效率取决于问题的排序和角落出现的分布。
  • 高速测试的结果被扔掉了。
  • 多个特征被检测到彼此相邻。

前3点是用机器学习的方法解决的。最后一个是用非最大抑制法解决的。

机器学习角点检测器

  1. 选择一组图像进行训练(最好是来自目标应用领域)。
  2. 在每个图像中运行FAST算法,以找到特征点。
  3. 对于每个特征点,将其周围的16个像素存储为一个向量。
  4. 对所有的图像都这样做,得到特征向量P。
    这16个像素中的每个像素(例如x)可以有以下三种状态之一:

openCV根据四个点画边 opencv四边形检测_opencv

  1. 根据这些状态,特征向量P被细分为3个子集,Pd, Ps, Pb。
  2. 定义一个新的布尔变量,Kp,如果p是一个角,则为真,否则为假。
  3. 使用ID3算法(决策树分类器)来查询每个子集,使用变量Kp来获取关于真实类别的知识。它选择产生关于候选像素是否是角落的最多信息的x,由Kp的熵来衡量。
  4. 这将递归地应用于所有的子集,直到其熵为零。
  5. 这样创建的决策树被用于其他图像的快速检测。
非最大值抑制

检测相邻位置的多个兴趣点是另一个问题。它是通过使用非最大抑制来解决的。

  1. 为所有检测到的特征点计算一个分数函数,即V。V是p和周围16个像素值的绝对差异之和。
  2. 考虑两个相邻的关键点并计算它们的V值。
  3. 丢弃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',0) # `<opencv_root>/samples/data/blox.jpg`
# 用默认值启动FAST对象
fast = cv.FastFeatureDetector_create()
# 找到并画出关键点
kp = fast.detect(img,None)
img2 = cv.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)) )
cv.imwrite('fast_true.png', img2)
# 禁用nonmaxSuppression
fast.setNonmaxSuppression(0)
kp = fast.detect(img, None)
print( "Total Keypoints without nonmaxSuppression: {}".format(len(kp)) )
img3 = cv.drawKeypoints(img, kp, None, color=(255,0,0))
cv.imwrite('fast_false.png', img3)

请看结果。第一张图片显示的是有非最大限度抑制的FAST,第二张是没有非最大限度抑制的:

openCV根据四个点画边 opencv四边形检测_openCV根据四个点画边_02

其他资源

  1. Edward Rosten和Tom Drummond,“高速转角检测的机器学习”,载于第九届欧洲计算机视觉会议,第一卷,2006年,第430-443页(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. 模式分析和机器智能,2010年,第32卷,第105-119页(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)。