0. 概述
在深度学习大红大紫之前,计算机视觉领域先后出现了Harris角点检测、SIFT方法、SURF方法、ORB算法、FAST等算法,本文对上述方法进行全面的总结与阐述,作为深度学习特征点检测的前奏与铺垫,同时在非足量数据时采用常规方法亦可以使用。
1. Harris角点检测
1.1 理论基础
Harris角点检测器的最初目的是检测角点和边缘,以便在图像序列中进行运动分析。追踪边缘的原因是,它们可以获得高级特征,因为它们可以提供对不同目标、表面和纹理的洞察。然而,在帧与帧之间匹配边缘是一项非常困难的任务,因此有必要先跟踪角点然后使用边缘填充。
1.1.1 角点corner定义
在图像中,角点是两条边相交的区域。事实上,Harris原始论文认为角点应该是特征检测的基石(双关语),因为它们具有以下特征:
- 离散性 — 角点占据了一个独特而狭小的空间(而不是一个连续体)
- 可靠性 — 可能在帧与帧之间的相似区域中再次出现
- 有意义 — 剧烈变化的角点通常来自实际物体,而不是阴影或反射光
一个角点是两条边相交的区域
- 因为角点是两个边缘的连接点,它代表了两个边缘变化的方向上的点。图像梯度有很高的变化。这种变化是可以用来帮助检测角点。
既然角点反应了梯度的变化,可以先从梯度说起。
作为建立梯度直觉的前奏,可以从角点的 x(水平)和 y(垂直)梯度入手。这里可以使用 Sobel 算子来计算两个方向的梯度。
图 1.角点的水平 x方向 和垂直y方向图像梯度
在图 1 的最左侧,我们有一个添加噪声的角点的图像。中间两个图像是图像的 x 和 y 梯度。图 1 最右侧是 x VS y 梯度的散点图。中心的大聚类来自平滑区域,这些区域具有小梯度,并且由于添加了噪声值为非零。x 和 y 梯度中的大值分别在右侧和顶部形成聚类,这些聚类源于角点导致的每个方向的像素变化。
下面是水平边缘的角点,以更好地理解正在发生的事情。
图2.水平边缘的水平x方向和垂直y方向图像梯度
在图 2 最右边的图中,我们可以看到由梯度平滑区域形成的位于中心的簇,但是由于垂直梯度中的值较大,在上面形成一个较小的簇。当我们沿垂直方向对图像取横段面时,左图水平边缘处【颜色过度区域】会产生很大的垂直梯度,从而在我们的散点图上产生这个聚类,垂直边缘的情况类似。 这意味着可以使用 x 和 y 方向的图像梯度变化检测角点。
- 如果 x 和 y 梯度方向的变化都很大时,则表示存在角点
- 如果 x 和 y 梯度方向的变化有一个方向很大,则表示位于边缘处
- x 和 y 梯度方向的变化都很小,表明表面是平滑的
这很直观,Harris Corner Detector 基于上述视角提供了一种便捷方法来检测具有相似逻辑的角点。
1.1.2 Morvec角点检测器
Harris Corner Detector 实质是 Morvec 的 Corner Detector 的扩展,那么首先直观地介绍Morvec 角点检测器,然后从数学上介绍前者。
考虑图像的单个窗口的透视,在这个窗口的正中心有一个正在测试的像素,现在想确定这个像素是否是一个角点,可以向多个方向滑动窗口,并观察每个方向的总像素强度(所有窗口像素的总和)。 在下面的图 3 中,我们可以看到有三种不同类型的图像特征需要考虑。
图3.平滑、边缘和角点区域的比较
区域分类的方法类似于上面的梯度直觉,因为图像梯度描述了方向变化的强度。Morvec的方法在每个像素周围放置一个窗口,并根据窗口沿每个方向移动时像素强度的不同变化对其进行分类(图3所示三类)。但是,只考虑了四个方向的偏移:
当4个偏移产生的最小变化超过阈值时,可以声明为一个角点:
用数学方式表示 Morvec 方法,其中窗口以 (x,y) 为中心,并产生偏移 (u,v) 。所有偏移的斑块强度之间的平方差 (SSD) 之和就是总变化 E。
不足之处:
- 只考虑一小部分方向的偏移
- 由于采用矩形窗口,响应带有噪声
- 没有考虑 E 的整个变化,只考虑最小值
1.1.3 Harris角点检测器
为了解决了上述不足,Harris 角点检测器被提出用于更可靠地检测角点和边缘。
基本思想:
• 在一个小的窗口内很容易识别的点视为角点
• 沿任意方向滑移一个小的窗口,将导致像素强度出现剧烈变化
为了考虑每一个小的位移,而不仅仅是四个方向的位移,我们使用关于位移原点(x,y) 的泰勒展开来得出一个方便的分析表达式。这假设图像的水平和垂直导数存在于 (x,y) 和 (x+u,y+v) 处。
令 ,则泰勒展开式如下:
其中,
上述表达式中,A,B,C 表示为采用一阶导数的平方与窗口 w 的卷积。
如果我们使用标准的 3x3 窗口,那么总共会有 8 个偏移量(8近邻每个领域计算一次shift)。
上面得到的总强度变化 E 的解析表达式是二次形式的,它使得能够方便地通过 M 矩阵的特征值来研究它在原点的形状。
特征向量是捕获数据中基本模式的基础向量,而特征值则描述了每个主(特征向量)方向的方差。换言之,由其各自的特征值缩放的特征向量构成了一个椭球体的轴,该椭球体包含了数据的散点图。在本例中,特征值描述了每个主方向上图像强度的变化。在下面的图 4 中,可以看到由特征向量/值形成的椭球体包含 x VS y 图像梯度的散点图。
图4.PCA椭圆,包含 3x3 窗口中角点的 x 和 y 梯度的散点图
M 矩阵的特征值描述了每个主方向上图像强度的变化
这使我们能够根据 M 矩阵的特征值评估图像的窗口像素,我们甚至不需要特征向量,也就是仅有特征值的大小就足够了,因为它们描述了考虑了所有方向时梯度的总变化。
图5.角点/边缘响应区域
因此,特征值的大小和关系决定了一个region是边缘轮廓、角点还是平滑处
- if and are small, then is small and the region is flat;
- if or viceversa, then and the region is an edge;
- if and both eigenvalues are large, then R is large and the region is a corner.
图6.角点/边缘响应区域划分
上图 5 中的角点响应轮廓显示了我们如何将每个像素分类为平面、边缘或角点
- 平滑 — 当两个特征值都较小时(E 将为平缓)
- Edge — 当一个特征值很大而另一个特征值很小时(E 将呈山脊状)
- 角点— 当两个特征值都很大时(E 将出现极端峰值)
此外,我们可以凭经验推导出一个角响应表达式,该表达式不涉及直接计算特征值,也不涉及明确考虑每个(x,y)位移。它只涉及计算矩阵 M 的行列式和迹,同时设置一个超参数 k,通常取值范围为,[0.04,0.06],使我们能够控制哪些区域被认为是平滑的或不平滑的。
如果将M的特征值改写为,则上述表达式为:
Harris 角点响应 R 在角点区域为正,在边缘区域为负,在平滑区域为小。仅使用此值,我们就可以找到角点和边。
计算角点响应的算法步骤为:
- 计算水平和垂直图像导数
- 计算导数的乘积
- 将高斯平滑核与每个乘积导数进行卷积 → 任何类型的模糊都应该有助于减少噪声
- 计算转角响应:
- 获得强角的阈值角响应:R > thresh
1.1.4 Harris角点检测示例
在下图中,我们展示了Harris角点检测器的实际应用。使用上述方程10计算角点响应图(下图由中右上图),其中。左下图表示 时获得的阈值角响应。在应用非极大值抑制后获得的角点检测结果显示于右下角图像中。
1.2 代码实现
在图像中搜索有价值的特征点时,使用角点是一种不错的方法。 角点是很容易在图像中定位的局部特征, 并且大量存在于人造物体中(例如墙壁、 门、 窗户、 桌子等产生的角点)。 角点的价值在于它是两条边缘线的接合点, 是一种二维特征,可以被精确地定位(即使是子像素级精度)。 与此相反的是位于均匀区域或物体轮廓上的点以及在同一物体的不同图像上很难重复精确定位的点。 Harris特征检测是检测角点的经典方法。
这里仅展示GoodFeaturesToTrackDetector + SiftDescriptorExtractor的组合方式的代码,其他组合不再演示。
#include "opencv2/highgui/highgui.hpp"
#include "opencv2/imgproc/imgproc.hpp"
#include <iostream>
#include <stdio.h>
#include <stdlib.h>
using namespace cv;
using namespace std;
/// Global variables
Mat src, src_gray;
int thresh = 200;
int max_thresh = 255;
char* source_window = "Source image";
char* corners_window = "Corners detected";
/// Function header
void cornerHarris_demo( int, void* );
/** @function main */
int main( int argc, char** argv )
{
/// Load source image and convert it to gray
src = imread( argv[1], 1 );
cvtColor( src, src_gray, CV_BGR2GRAY );
/// Create a window and a trackbar
namedWindow( source_window, CV_WINDOW_AUTOSIZE );
createTrackbar( "Threshold: ", source_window, &thresh, max_thresh, cornerHarris_demo );
imshow( source_window, src );
cornerHarris_demo( 0, 0 );
waitKey(0);
return(0);
}
/** @function cornerHarris_demo */
void cornerHarris_demo( int, void* )
{
Mat dst, dst_norm, dst_norm_scaled;
dst = Mat::zeros( src.size(), CV_32FC1 );
/// Detector parameters
int blockSize = 2;
int apertureSize = 3;
double k = 0.04;
/// Detecting corners
cornerHarris( src_gray, dst, blockSize, apertureSize, k, BORDER_DEFAULT );
/// Normalizing
normalize( dst, dst_norm, 0, 255, NORM_MINMAX, CV_32FC1, Mat() );
convertScaleAbs( dst_norm, dst_norm_scaled );
/// Drawing a circle around corners
for( int j = 0; j < dst_norm.rows ; j++ )
{ for( int i = 0; i < dst_norm.cols; i++ )
{
if( (int) dst_norm.at<float>(j,i) > thresh )
{
circle( dst_norm_scaled, Point( i, j ), 5, Scalar(0), 2, 8, 0 );
}
}
}
/// Showing the result
namedWindow( corners_window, CV_WINDOW_AUTOSIZE );
imshow( corners_window, dst_norm_scaled );
}
2. SIFT
2.1 理论基础
SIFT
算法由 David Lowe
在 1999
年提出,并在SIFT论文中详细阐述。
2.2 代码实现
SURF算法是SIFT算法的加速版, 而SIFT(尺度不变特征转换, ScaleInvariant Feature Transform) 是另一种著名的尺度不变特征检测法。我们知道,SURF相对于SIFT而言,特征点检测的速度有着极大的提升,所以在一些实时视频流物体匹配上有着很强的应用。而SIFT因为其巨大的特征计算量而使得特征点提取的过程异常花费时间,所以在一些注重速度的场合难有应用场景。但是SIFT相对于SURF的优点就是,由于SIFT基于浮点内核计算特征点,因此通常认为, SIFT算法检测的特征在空间和尺度上定位更加精确,所以在要求匹配极度精准且不考虑匹配速度的场合可以考虑使用SIFT算法。
SIFT特征检测的代码我们仅需要对上面的SURF代码作出一丁点修改即可。
3. SURF
3.1 理论基础
SURF
(Speeded Up Robust Features
) 是一种基于 SIFT
算法的改进版本,它在计算效率和描述子的稳健性方面进行了优化。SURF
算法由 Herbert Bay
等人于 2006
年提出,详见SURF论文。
3.2 代码实现
特征检测的视觉不变性是一个非常重要的概念。 但是要解决尺度不变性问题,难度相当大。 为解决这一问题,计算机视觉界引入了尺度不变特征的概念。 它的理念是, 不仅在任何尺度下拍摄的物体都能检测到一致的关键点,而且每个被检测的特征点都对应一个尺度因子。 理想情况下,对于两幅图像中不同尺度的的同一个物体点, 计算得到的两个尺度因子之间的比率应该等于图像尺度的比率。近几年, 人们提出了多种尺度不变特征,本节介绍其中的一种:SURF特征。 SURF全称为“加速稳健特征”(Speeded Up Robust Feature),我们将会看到,它们不仅是尺度不变特征,而且是具有较高计算效率的特征。
我们首先进行常规的特征提取和特征点匹配,看看效果如何。
4. orb
4.1 理论基础
ORB
(Oriented FAST and Rotated BRIEF
)也是一种目前常用的计算机视觉算法,用于图像特征提取和描述。它是在FAST
角点检测器和BRIEF
描述子算法的基础上进行改进,详见ORB论文。
4.2 代码实现
ORB是ORiented Brief的简称,是brief算法的改进版。ORB算法比SIFT算法快100倍,比SURF算法快10倍。在计算机视觉领域有种说法,ORB算法的综合性能在各种测评里较其他特征提取算法是最好的。
ORB算法是brief算法的改进,那么我们先说一下brief算法有什么去缺点。
BRIEF的优点在于其速度,其缺点是:
- 不具备旋转不变性
- 对噪声敏感
- 不具备尺度不变性
而ORB算法就是试图解决上述缺点中1和2提出的一种新概念。值得注意的是,ORB没有解决尺度不变性。
5. FAST
5.1 理论基础
5.2 代码实现
FAST(加速分割测试获得特征, Features from Accelerated Segment Test) 。 这种算子专门用来快速检测兴趣点, 只需要对比几个像素,就可以判断是否为关键点。
跟Harris检测器的情况一样, FAST算法源于对构成角点的定义。FAST对角点的定义基于候选特征点周围的图像强度值。 以某个点为中心作一个圆, 根据圆上的像素值判断该点是否为关键点。 如果存在这样一段圆弧, 它的连续长度超过周长的3/4, 并且它上面所有像素的强度值都与圆心的强度值明显不同(全部更黑或更亮) , 那么就认定这是一个关键点。
用这个算法检测兴趣点的速度非常快, 因此十分适合需要优先考虑速度的应用。 这些应用包括实时视觉跟踪、 目标识别等, 它们需要在实
时视频流中跟踪或匹配多个点。
可以使用FastFeatureDetector 进行特征点提取,因为opencv没有提供fast专用的描述子提取器,所以我们借用SiftDescriptorExtractor 来实现描述子的提取。
6. 参考资料
1. Harris Corner and Edge Detector
2. https://www.baeldung.com/cs/harris-corner-detection
3. https://www.cnblogs.com/skyfsm/p/7401523.html
5. https://www.cnblogs.com/AndyJee/p/3734805.html
6.详解计算机视觉中的特征点检测:Harris / SIFT / SURF / ORB-腾讯云开发者社区-腾讯云
7.详解SIFT、SURF和ORB特征点检测和描述算法_stitch python surf sift orb-CSDN博客