通过《图像局部不变性特征与描述》学习SIFT,遇到各种Issue,总结了这篇博客和另外九篇博客。感谢关注,希望可以互相学习,不断提升。转载请注明链接:https://www.cnblogs.com/Alliswell-WP/p/SIFT.html
如果想深入研究SIFT,最好可以一起看,特别是博客中颜色加重部分,为自己批注。加入了自己的总结,红字和紫色标识。有问题请及时联系博主:Alliswell_WP
SIFT四步骤和特征匹配及筛选:
步骤一:建立尺度空间,即建立高斯差分(DoG)金字塔dog_pyr
步骤二:在尺度空间中检测极值点,并进行精确定位和筛选创建默认大小的内存存储器
步骤三:特征点方向赋值,完成此步骤后,每个特征点有三个信息:位置、尺度、方向
opencv3.0中contrib模块的添加+实现SIFT/SURF算法
一、SIFT算法
1.算法简介
尺度不变特征转换即SIFT (Scale-invariant feature transform)是一种计算机视觉的算法。它用来侦测与描述影像中的局部性特征,它在空间尺度中寻找极值点,并提取出其位置、尺度、旋转不变量,此算法由 David Lowe在1999年所发表,2004年完善总结。
局部影像特征的描述与侦测可以帮助辨识物体,SIFT特征是基于物体上的一些局部外观的兴趣点而与影像的大小和旋转无关。对于光线、噪声、些微视角改变的容忍度也相当高。基于这些特性,它们是高度显著而且相对容易撷取,在母数庞大的特征数据库中,很容易辨识物体而且鲜有误认。使用 SIFT特征描述对于部分物体遮蔽的侦测率也相当高,甚至只需要3个以上的SIFT物体特征就足以计算出位置与方位。在现今的电脑硬件速度下和小型的特征数据库条件下,辨识速度可接近即时运算。SIFT特征的信息量大,适合在海量数据库中快速准确匹配。
SIFT算法的实质是在不同的尺度空间上查找关键点(特征点),并计算出关键点的方向。SIFT所查找到的关键点是一些十分突出,不会因光照,仿射变换和噪音等因素而变化的点,如角点、边缘点、暗区的亮点及亮区的暗点等。
1.1哪些是SIFT要查找的关键点
1.2什么是尺度空间
2.算法流程
二、SIFT算法操作步骤
1.图像金字塔
1.1高斯金字塔
图像高斯金字塔(Gaussian Pyramid)是采用高斯函数对图像进行模糊以及降采样处理得到。其形成过程可如下图所示:
其中高斯模糊系数计算公式如下:
sigma0为基准层尺度(图像的初始尺度),o为组坐标(组数的索引值),r为每组层数的索引值,s为寻找极值点的尺度空间的组数,默认值为3(Lowe推荐为3)
1.1.1高斯函数与图像卷积
根据3σ原则,使用NxN的模板在图像每一个像素点处操作,其中N=[(6σ+1)]且向上取最邻近奇数。
其操作如下图:
1.1.2分离高斯卷积
上面这样直接与图像卷积,速度比较慢,同时图像边缘信息也会损失严重。后来,后来,不知哪位学者发现,可以使用分离的高斯卷积(即先用1xN的模板沿着X方向对图像卷积一次,然后用Nx1的模板沿着Y方向对图像再卷积一次,其中N=[(6σ+1)]且向上取最邻近奇数),这样既省时也减小了直接卷积对图像边缘信息的严重损失。
1.1.3高斯金字塔源码分析
1 /*
2 从图像构建高斯尺度空间金字塔
3 @param金字塔的基础图像
4 @param octvs比例空间的八度音阶数
5 @param intvls每个八度音程的间隔数
6 每个八度音程的@param sigma高斯平滑量
7 @return返回高斯尺度空间金字塔作为octvs x(intvls + 3)
8 排列
9 */
10 static IplImage*** build_gauss_pyr(IplImage* base, int octvs,
11 int intvls, double sigma)
12 {
13 IplImage*** gauss_pyr;
14 double *sig = (double *)calloc(intvls + 3, sizeof(double)); //每组需s+3张图像,默认6张,sig存图像对应的sigma值,各组通用
15 double sig_total, sig_prev, k;
16 int i, o;
17 gauss_pyr = calloc(octvs, sizeof(IplImage**)); //octvs组图像
18 for(i = 0; i < octvs; i++)
19 gauss_pyr[i] = calloc(intvls + 3, sizeof(IplImae*)); //每组需s+3张图像,默认6张
20 /*
21 precompute Gaussian sigmas using the following formula:
22 使用以下公式预计算高斯sigma:
23 \sigma_{total}^2 = \sigma_{i}^2 + \sigma_{i-1}^2
24 */
25 sig[0] = sigma; //初始sigma,默认1.6
26 k = pow(2.0, 1.0 / intvls); //k=2^(1/s)
27 for(i = 1; i < intvls + 3; i++)
28 {
29 sig_prev = pow(k, i - 1) * sigma; //前一幅图像的sigma
30 sig_total = sig_prev * k; //当前图像的sigma
31 sig[i] = sqrt(sig_total * sig_total - sig_prev * sig_prev); //需叠加的高斯模糊参数值,应该叫sig_diff更贴切
32 }
33 for(o = 0; o < octvs; o++)
34 for(i = 0; i < intvls + 3; i++)
35 {
36 if(o == 0 && i==0) //高斯金字塔最低层
37 gauss_pyr[o][i] = cvCloneImage(base);
38 /* base of new octvave is halved image from end of previous octave */
39 else if(i == 0) //每一组最底层由上一组对应图像下采样获得。其实除了起始组外,每一组的前3幅图像都可以由上组下采样获得
40 gauss_pyr[o][i] = downsample(gauss_pyr[o-1][intvls]);
41 /* blur the current octave's last image to create the next one */
42 else //在同组上层图像基础上叠加sig_diff得到本层图像
43 {
44 gauss_pyr[o][i] = cvCreateImage(cvGetSize(gauss_pyr[o][i-1]),
45 IPL_DEPTH_32F, 1);
46 cvSmooth(gauss_pyr[o][i-1], gauss_pyr[o][i],
47 CV_GAUSSIAN, 0, 0, sig[i], sig[i]);
48 }
49 }
50 free(sig);
51 return gauss_pyr;
52 }
1.2高斯差分金字塔
2002年Mikolajczyk在详细的实验比较中发现尺度归一化的高斯拉普拉斯函数的极大值和极小值同其它的特征提取函数,例如:梯度,Hessian或Harris角特征比较,能够产生最稳定的图像特征。而Lindeberg早在1994年就发现高斯差分函数(简称DOG算子)与尺度归一化的高斯拉普拉斯函数非常近似。如下式:
其中k-1是个常数,并不影响极值点位置的求取。
证明: