OpenCV学习笔记-角点检测的FAST算法

一、原理

在实时的视频流处理中,需要对每一帧特征提取,对算法处理速度上有很高的要求,传统的SIFT,Harris等特征点提取很难满足。由此提出Fast(Features from Accelerated Segment Test),由于不涉及尺度,梯度,等复杂运算,Fast检测器速度非常快。它使用一定邻域内像元的灰度值与中心点比较大小去判断是否为一个角点。但它的缺点是不具有方向性,尺度不变性。

二、使用FAST算法进行特征提取

1、在图像中选取一个像素点,来判断它是不是关键点。Ip等于像素点的灰度值。

2、选择适当的阈值εd。
3、如下图所示在像素点P的以固定半径为圆的边上选择16个像素点(图中白色框出的位置),与中心点像素值Ip做差。

4、如果在这16个像素点钟存在n个连续像素点的灰度值都高于Ip+εd,或者低于Ip-εd,那么像素点p就被认为是一个角点。n的选取值一般有 9、10、11、12。
5、 为了获得更快的结果,还采用了额外的加速办法。 如果测试了候选点周围每隔90度角的4个点(1,9,5,13),应该至少有3个和候选点的灰度值差足够大,否则则不用再计算其他点,直接认为该候选点不是特征点 候选点周围的圆的选取半径是一个很重要的参数,上图采用半径为3,共有16个周边像素需要比较。
这个检测器的效率很高,但是它有如下几条缺点:
1、当n<12时不会丢弃很多候选点(也就是获得的候选点会比较多)
2、检测出来的角点不是最优的,这是因为它的效果是依靠角点外围的排列和分布
3、高速测试的结果被抛弃
4、检测到的很多特征点是连在一起的


前三个问题可以使用机器学习的方法解决。最后一个可以使用non-maximal suppression

三、机器学习的角点检测

1、选择一个图片集合进行学习(最好是来自于目标应用定义域)。
2、在每一张图上运行FAST算法,找到特征点。
3、对于每个特征点,存储它周围的16个像素点到一个vector中。为所有的图片做同样的事,得到它们所有特征点的vector P
4、每一个特征点的16个像素点都属于下面三类中的一种。

5、根据这些像素点的分类,特征向量P也被分为三个子集:P_d, P_s, P_b。
6、定义一个新的布尔变量K_p。如果P是角点就设置为True,如果不是就设置为False。
7、使用ID3算法(决策树分类器)来查询每一个子集
8、递归计算所以的子集知道它的熵为0
9、将构建好的决策树运用于其他图像的FAST检测。

扫描二维码关注公众号,回复: 1475226 查看本文章
四、非极大值抑制
使用极大值抑制的方法可以解决检测到的特征点相连的问题

1、为每一个检测到的特征点计算它的分数函数(score function)V。V是 像素点P 和它周围16个像素点的差值的绝对值之和。
2、考虑两个相邻的特征点,并比较它们的v值。
3、v 值较低的点将会被剔除。

五、OpenCV中的FAST特征检测器
和OpenCV中其他特征检测器的调用相同。如果你想,你可以指定一个阙值,或者决定是否使用non-maximal suppression来判断邻近特征点。

对于相邻特征点,OpenCV定义了三个flags:
  • cv2.FAST_FEATURE_DETECTOR_TYPE_5_8
  • cv2.FAST_FEATURE_DETECTOR_TYPE_7_12
  • cv2.FAST_FEATURE_DETECTOR_TYPE_9_16

具体代码:
import cv2 as cv
import numpy as np
from matplotlib import pyplot as plt


img = cv.imread('img/blox.jpg')

gray = cv.cvtColor(img, cv.COLOR_BGR2GRAY)
fast = cv.FastFeatureDetector_create()
kp = fast.detect(gray, None)
kp_img = cv.drawKeypoints(img, kp, None, color=(255, 0, 0))

print('Threshold ', fast.getThreshold())
print('nonmaxSuppression ', fast.getNonmaxSuppression())
print('neighborhood: ', fast.getType())
print('num', len(kp))
cv.imshow('fast_true', kp_img)

#不使用非极大值抑制
fast.setNonmaxSuppression(0)
kp = fast.detect(gray, None)
print( 'num', len(kp))
kp_img_no = cv.drawKeypoints(img, kp, None, color=(255, 0, 0))
cv.imshow('fast_flase', kp_img_no)

cv.namedWindow('img',cv.WINDOW_AUTOSIZE)
cv.imshow('img',img)
cv.waitKey(0)
cv.destroyAllWindows()

猜你喜欢

转载自blog.csdn.net/qq_36387683/article/details/80572595