本文转载自:http://livezingy.com/sift-in-opencv3-1/
SIFT算法的实现过程大致如下:对源图像进行高斯模糊处理,根据源图尺寸和相关设定参数生成图像的高斯金字塔和高斯差分金字塔(DOG尺度空间),在DOG尺度空间中搜索特征点,计算尺度,构建特征描述子。本文以SIFT的参数为主线来尝试说明SIFT算法的原理。
SIFT算法图像匹配的效果图如下图所示,接下来会有文章分析surf特征检测,sift特征匹配和surf特征匹配的代码在下一篇文章中将一并给出。
【OpenCV】SIFT原理与源码分析
SIFT算法详解
上述参考资料中将SIFT算法的原理讲述的非常清楚,受益匪浅,感谢原作者。
SIFT算法并未被集成到opencv3.1中,它属于opencv_contrib, opencv_contrib的编译方法可以参考cmake-gui和vs2013编译opencv和opencv_contrib源码.
在opencv3.1中,实现SIFT算法的文件为opencv_contrib\modules\xfeatures2d\src\sift.cpp,SIFT的构造函数:
SIFT相关参数的简要介绍如下:
nfeatures:特征点数目(算法对检测出的特征点排名,返回最好的nfeatures个特征点)。
nOctaveLayers:金字塔中每组的层数(算法中会自己计算这个值,后面会介绍)。
contrastThreshold:过滤掉较差的特征点的对阈值。contrastThreshold越大,返回的特征点越少。
edgeThreshold:过滤掉边缘效应的阈值。edgeThreshold越大,特征点越多(被过滤掉的越少)。
sigma:金字塔第0层图像高斯滤波系数,也就是σ。
参数nfeatures指定最终返回的特征点数量,并不影响SIFT特征检测的结果,本文不对该参数进行分析。参数nOctaveLayers和sigma主要影响图像高斯金字塔的构成,而contrastThreshold和edgeThreshold则影响在DOG中寻找极值点的过程与结果。根据SIFT的四个参数的作用范围,本文先讲述以下5个部分:高斯金字塔,高斯模糊,高斯差分金字塔(DOG算子),空间极值点检测,消除极值点的边缘响应;然后本文会给出用SIFT算法进行图像匹配的范例。
首先我们来看一下SIFT算法中图像的高斯金字塔。图像的金字塔模型是指,将原始图像不断降阶采样,得到一系列大小不一的图像,由大到小,从下到上构成的塔状模型。
金字塔的第一层是根据参数sigma进行高斯模糊处理后的源图,第二层的尺寸则是源图像长宽各一半,第三层是第二层长宽的各一半,以此类推。金字塔的总层数由源图像中长与宽的较小值决定,计算方法如图中的nOctaves的计算公式。
每一层金字塔总包含(nOctaveLayers+3)层相同尺寸的图像,同层金字塔尺寸相同,但每一层都进行了不同系数的高斯模糊处理,这一点会在高斯模糊一节中详述。第N层金字塔的第一层图是第N-1层金字塔的最后一层图的resize处理。
根据金字塔层数的计算公式,我绘制了源图像尺寸与金字塔层数的趋势图。由趋势图可知,金字塔层数随图像尺寸变化及其缓慢,且不同尺寸源图像的顶层金字塔的尺寸基本相当。
高斯模糊是一种图像滤波器,本文讲述的高斯模糊以高斯模糊的实验结果和数据为主。高斯金字塔的每一层由个(nOctaveLayers+3)图层组成。表格中的i表示每层金字塔中图层的序号,同层金字塔不同图层之间的高斯模糊参数计算方法如下图所示。
sigma值的大小对高斯模糊的结果到底影响有多大呢?我们先来看一下相同图片经过不同高斯模糊系数处理后的结果:
在实际计算时,使用高斯金字塔每组中相邻上下两层图像相减,得到高斯差分图像,在高斯差分图像上进行极值检测。极值点的初步探查是通过同一组内各DOG相邻两层图像之间比较完成的。为了寻找DoG函数的极值点,每一个像素点要和它所有的相邻点比较,看其是否比它的图像域和尺度域的相邻点大或者小。如图所示,中间的检测点和它同尺度的8个相邻点和上下相邻尺度对应的9×2个点共26个点比较,以确保在尺度空间和二维图像空间都检测到极值点。
初步认定某个点为极值点,需要遍历DOG金字塔中每一个点,若
a.当前点的绝对值>threshold
b.当前点的值>0,则当前点的值大于周围26个点的值;若当前点的值<0,则当前点的值小于周围26的点的值;
同时满足以上两个条件,则初步判定其为极值点。
其中,threshold的计算公式如下:
int threshold = cvFloor(0.5 * contrastThreshold / nOctaveLayers * 255 * SIFT_FIXPT_SCALE)
需要强调的是SIFT算法要求的输入图像深度为CV_8U,因此SIFT算法中处理的图像矩阵中的值为0~255,因此threshold应该也在此范围内才有意义。其中, SIFT_FIXPT_SCALE=1, cvFloor为向下取整,例如0.01的cvFloor为零。所以0.01<(contrastThreshold / nOctaveLayers)<2为大范围。在此大范围之内,考虑到DOG空间的形成原理,可以计算当前图像最大值与最小值之差,根据该值进一步缩小contrastThreshold / nOctaveLayers的设定范围。
在参考文献SIFT算法详解 中,作者提出“一个定义不好的高斯差分算子的极值在横跨边缘的地方有较大的主曲率,而在垂直边缘的方向有较小的主曲率。”。作者也有详细讲述SIFT算法中消除边缘响应算法的原理,这里就不再重复说明了。对于算法的使用者来讲,需要知道根据消除边缘响应算法的原理,参数edgeThreshold的设定至越小,边缘点的条件越强,滤除的极值点越多,返回的特征点越少;edgeThreshold越大,被滤掉的极值点越少,特征点越多。