在OpenCV里使用FAST算法

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接: https://blog.csdn.net/caimouse/article/details/102667778

目标:了解FAST算法,在OpenCV里使用FAST算法。

 

理论:

前面学习了很多特征检测算法,并且表现得非常优秀。如果想从实时应用方面去使用它们,其实都不行,比如SLAM(Simultaneous Localization and Mapping)在移动机器人方面的应用。SLAM也称为CML (Concurrent Mapping and Localization), 即时定位与地图构建,或并发建图与定位。问题可以描述为:将一个机器人放入未知环境中的未知位置,是否有办法让机器人一边移动一边逐步描绘出此环境完全的地图,所谓完全的地图(a consistent map)是指不受障碍行进到房间可进入的每个角落。

为了解决这种实时应用, Edward Rosten和Tom Drummond在论文《Machine learning for high-speed corner detection》里提出了FAST(Features from Accelerated Segment Test)算法。这个算法的大体思路如下,如果想了解更多的细节可以看原来的论文。

FAST特征检测:

1)在图像里随机选择一点p,无论此点能否成为特征点,假定它的强度为Ip。

2)选择一个合适的阈值t。

3)在像素p周围画一个圆,以p点为圆心,周长上总共有16个元素,如下图所示:

4)现在假定像素p是一个角点,那么在圆周上(这里16个像素)至少有连续n个像素亮度大于Ip+t,或者n个像素亮度小于Ip-t。在这里,看到图片上n是12个,图上白色点划线所示。

5)首先使用一个高速测试的方法来检查出非角点,那就是只要先测试像素1、9、5和13,其实可以先测试1和9,如果满足了再测试5和13。如果p点是一个角点,至少有三个点的亮度大于Ip+t或者小于Ip-t。如果这两个条件都不满足,说明p点不是一个角点。如果通过了快速测试,就可以通过检查圆中的所有像素是否满足上面的要求。虽然这种高速测试方法检测速度很快,但也是有以下几个不足之处:

a)没有办法过滤小于12个连续点的点。

b)像素的选择不是最优的,因为它的效率取决于问题的排序和角的分布。

c)高速测试的结果被丢弃掉。

d)检测得到的特征点容易挤在一起。

前三点是可用用机器学习方法解决,最后一条可以使用非最大值抑制(non-maximal suppression)来解决。

 

机器学习角检测器

1)选择一组用于培训的图像 (最好来自检测目标范围的图像)

2)对每一张图像运用 FAST 算法找到特点.

3)对于每个特征点,将其周围的16个像素存储为一个向量。对所有的图像都这样做,得到特征向量 P 。

4)这16个像素中的每个像素(比如x)都可以有以下三种状态之一:

5)根据这些状态,特征向量 P 被细分为三个子集,  Pd, Ps, Pb。

6)定义一个新的布尔变量 Kp ,如果 p 是一个角,则为真,否则为假。

7)使用ID3算法(决策树分类器)查询每个子集,使用变量 Kp 查询关于真类。它选择产生最多信息量的x作为是否是角的候选,可以 通过计算 Kp 的熵来度量。

8)递归地应用于所有子集,直到它的熵为零。

9)所建立的决策树用于其他图像的快速检测。

 

非最大值抑制

在邻域里检测到多个特征点是一个问题,但是它可以使用非最大值抑制来解决。

1)计算一个分数函数,V代表所有检测到的特征点。V是p和周围16个像素值的绝对差值之和。

2)考虑两个相邻的关键点并计算它们的V值。

3)丢弃V值较低的点。

 

FAST方法比其他现有的角检测方法快几倍,但它对高噪点的图像效果并不好,严重依赖于阈值设定。

在OpenCV里可以使用下面例子来演示:

#python 3.7.4,opencv4.1
#蔡军生 https://blog.csdn.net/caimouse/article/details/51749579
#
import numpy as np
import cv2
from matplotlib import pyplot as plt

#读取文件
img = cv2.imread('szcen1.png')

#使用默认值初始化FAST
fast = cv2.FastFeatureDetector_create()
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)) )

#显示图片
cv2.imshow('img',img2)
           
cv2.waitKey(0)
cv2.destroyAllWindows()

结果输出如下:

 

Threshold: 10

nonmaxSuppression:True

neighborhood: 2

Total Keypoints with nonmaxSuppression: 9338

https://blog.csdn.net/caimouse/article/details/51749579

 

猜你喜欢

转载自blog.csdn.net/caimouse/article/details/102667778