SIFT定位算法关键步骤的说明
来源:互联网 发布:新浪通达信炒股软件 编辑:程序博客网 时间:2024/05/22 01:34
本篇文章转载自http://www.cnblogs.com/ronny/p/4028776.html请尊重版权
1. SIFT算法中一些符号的说明
上面特别值得注意的是尺度为
2. 构建高斯差分金字塔
2.1 第一组第一层图像的生成
很多初涉SIFT的都会被这个问题所困惑,这里要分两种情况:其一是把第一组的索引定为0;其二是把第一组的索引定为-1。
我们先考虑第一组索引为0的情况,我们知道第一组第一层的图像是由原图像与
其中
现在我们来考虑把第一组的索引定为-1的情况。那么首先第一个问题便是为什么要把索引定为-1。如果索引为0,如上面那种情况所示,整个尺度空间的第1组的第1层图像已经是由原图像模糊生成的了,那么也就是说已经丢失了细节信息,那么原图像我们完全没有利用上。基于这种考虑,我们先将图像放大2倍,这样原图像的细节就隐藏在了其中。由上面一种情况分析,我们已经知识了I(x,y)看成是已经被
其中
2.2 尺度空间生成了多少幅图像
我们知道S是我们最终构建出来的用来寻找特征点的高斯差分图像,而特征点的寻找需要查找的是空间局部极小值,即在某一层上查找局部极值点的时候需要用到上一层与下一层的高斯差分图像,所以如果我们需要查找S层的特征点,需要S+2层高斯差分图像,然后查找其中的第2层到第S+1层。
而每一个高斯差分图像
从上面的分析,我们知道对于尺度空间来说,我们一共需要S+3层图像来构建出来S+2层高斯差分图像。所以,如果整个尺度空间一共有O组,每组有S+3层图像。共O*(S+3)张尺度图像,如果我们查找OpenCV中的SIFT源码,则很容易找到如下代码来说明问题:
pyr.resize(nOctaves*(nOctaveLayers + 3));
上面代码中的pyr代表了整个尺度空间的图像,nOctaves为组数,nOctaveLayers即为我们定义的S。
2.3 为什么是倒数第3张
相信你在看很多SIFT算法描述里都这样写着,取上一张的倒数第3张图像隔行采样后作为下一组的第一张图像。
答案是为了保证尺度空间的连续性,我们下面来仔细分析。
我们知道对于尺度空间第o组,第s层的图像,它的尺度为
第0组:
第1组:
我们只分析2组便可以看出,第1组的第0层图像恰好与第0组的倒数第三幅图像一致,尺度都为
我们也可以继续分析,第0组尺度空间得到的高斯差分图像的尺度为:
而第1组尺度空间得到的高斯差分图像的尺度为:
如果我们把它们的中间三项取出来拼在一起,则尺度为:
2.4 用第i-1层的图像生成第i层的图像
值得注意的是,在SITF的源码里,尺度空间里的每一层的图像(除了第1层)都是由其前面一层的图像和一个相对
基于上面两点原因(个人认为原因1是最主要的,原因2只是根据实际尝试后的一个猜想,并无理论依据),所以对于每一组的第
那么相对尺度如何计算呢,我们首先考虑第0组,它们的第
sig[0] = sigma;double k = pow(2., 1. / nOctaveLayers);for (int i = 1; i < nOctaveLayers + 3; i++){ double sig_prev = pow(k, (double)(i - 1))*sigma; double sig_total = sig_prev*k; sig[i] = std::sqrt(sig_total*sig_total - sig_prev*sig_prev);}
3. 特征点的搜索
3.1 搜索策略
斑点的搜索是通过同一组内各DoG相邻层之间比较完成的。为了寻找尺度空间的极值点,每一个采样点要和它所有的相邻点进行比较,看其是否比它的图像域和尺度域的相邻点大或小。对于其中的任意一个检测点都要和它同尺度的8个相邻点和上下相邻尺度对应的
搜索过程从每组的第二层开始,以第二层为当前层,对第二层的DoG图像中的每个点取一个
3.2 子像元插值
上的的极值点的搜索是在离散空间中进行的,检测到的极值点并不是真正意义上的极值点。下图显示了一维信号离散空间得到的极值点与连续空间的极值点之间的差别。利用已知的离散空间点插值到连续空间极值点的方法叫子像元插值。
首先我们来看一个一维函数插值的例子。我们已经
如果我们只考虑离散的情况,那么只用简单比较一下,便知最大值为
利用泰勒级数,可以将
另外我们知道
所以,我们可以算出
求取函数
现在回到我们SIFT点检测中来,我们要考虑的是一个三维问题,假设我们在尺度为
可以将上式写成矢量形式如下:
令上式的一阶导数等于0,可以求得
通过多次迭代(Lowe算法里最多迭代5次),得到最终候选点的精确位置与尺度
Vec3f dD((img.at<sift_wt>(r, c + 1) - img.at<sift_wt>(r, c - 1))*deriv_scale, (img.at<sift_wt>(r + 1, c) - img.at<sift_wt>(r - 1, c))*deriv_scale, (next.at<sift_wt>(r, c) - prev.at<sift_wt>(r, c))*deriv_scale);// dD为一阶差分矢量Df/Dxfloat v2 = (float)img.at<sift_wt>(r, c) * 2;float dxx = (img.at<sift_wt>(r, c + 1) + img.at<sift_wt>(r, c - 1) - v2)*second_deriv_scale;float dyy = (img.at<sift_wt>(r + 1, c) + img.at<sift_wt>(r - 1, c) - v2)*second_deriv_scale;float dss = (next.at<sift_wt>(r, c) + prev.at<sift_wt>(r, c) - v2)*second_deriv_scale;float dxy = (img.at<sift_wt>(r + 1, c + 1) - img.at<sift_wt>(r + 1, c - 1) - img.at<sift_wt>(r - 1, c + 1) + img.at<sift_wt>(r - 1, c - 1))*cross_deriv_scale;float dxs = (next.at<sift_wt>(r, c + 1) - next.at<sift_wt>(r, c - 1) - prev.at<sift_wt>(r, c + 1) + prev.at<sift_wt>(r, c - 1))*cross_deriv_scale;float dys = (next.at<sift_wt>(r + 1, c) - next.at<sift_wt>(r - 1, c) - prev.at<sift_wt>(r + 1, c) + prev.at<sift_wt>(r - 1, c))*cross_deriv_scale;Matx33f H(dxx, dxy, dxs, dxy, dyy, dys, dxs, dys, dss);// dD + Hx = 0 --> x = H^-1 * (-dD)Vec3f X = H.solve(dD, DECOMP_LU);
3.3 删除边缘效应
为了得到稳定的特征点,只是删除DoG响应值低的点是不够的。由于DoG对图像中的边缘有比较强的响应值,而一旦特征点落在图像的边缘上,这些点就是不稳定的点。一方面图像边缘上的点是很难定位的,具有定位歧义性;另一方面这样的点很容易受到噪声的干扰而变得不稳定。
一个平坦的DoG响应峰值往往在横跨边缘的地方有较大的主曲率,而在垂直边缘的方向有较小的主曲率。而主曲率可以通过
上式中,
如果
上式的结果只与两个特征值的比例有关,而与具体特征值无关。当两个特征值相等时,
Lowe在论文中给出的
float t = dD.dot(Matx31f(xc, xr, xi));//D(\bar{x}) = D + 1/2*dD*\bar{x}contr = img.at<sift_wt>(r, c)*img_scale + t * 0.5f; // 插值得到的极值点的值if (std::abs(contr) * nOctaveLayers < contrastThreshold) return false;// principal curvatures are computed using the trace and det of Hessianfloat v2 = img.at<sift_wt>(r, c)*2.f;float dxx = (img.at<sift_wt>(r, c + 1) + img.at<sift_wt>(r, c - 1) - v2)*second_deriv_scale;float dyy = (img.at<sift_wt>(r + 1, c) + img.at<sift_wt>(r - 1, c) - v2)*second_deriv_scale;float dxy = (img.at<sift_wt>(r + 1, c + 1) - img.at<sift_wt>(r + 1, c - 1) - img.at<sift_wt>(r - 1, c + 1) + img.at<sift_wt>(r - 1, c - 1)) * cross_deriv_scale;float tr = dxx + dyy;float det = dxx * dyy - dxy * dxy;if (det <= 0 || tr*tr*edgeThreshold >= (edgeThreshold + 1)*(edgeThreshold + 1)*det)return false;
- SIFT定位算法关键步骤的说明
- SIFT定位算法关键步骤的说明
- 图像特征提取:SIFT定位算法关键步骤的说明
- 图像特征提取:SIFT定位算法关键步骤的说明
- SIFT--关键点定位
- 【特征检测】关于SIFT算法中:“精确的关键点定位”的理解
- sift算法的主要步骤
- SIFT算法关键点定位中对尺度空间DoG函数进行曲线拟合求极值点的数学过程
- SIFT算法提取关键点
- sift特征--关键点搜索与定位
- SIFT算法原理与OpenCV源码分析3:关键点搜索与定位
- SIFT算法:KeyPoint找寻、定位与优化
- SIFT实现步骤,以及算法程序
- SIFT算法的几个问题
- SIFT算法:Matlab程序代码测试例子的说明(Lowe的代码)
- kettle 合并记录步骤中的 关键字段和 比较字段的说明
- kettle 合并记录步骤中的 关键字段和 比较字段的说明
- Sift描述子形成的步骤
- spring四种依赖注入方式
- 美团打包
- angular toastr插件
- react的context更新而组件不更新的解决方案
- 小技巧
- SIFT定位算法关键步骤的说明
- spring四种依赖注入方式
- windows程序设计——图形基础
- Oracle存在修改,不存在插入记录
- Base64/32/16编码
- Java与C++编译过程比较
- POJ2739-Sum of Consecutive Prime Numbers
- 续流的理解
- BZOJ 3158: 千钧一发 最小割