结合OPENCV SIFT代码浅谈Lowe的一些SIFT算法细节
2017-12-23 19:17
260 查看
前言
最近在做毕设的过程中,看了一些网上以及书本的资料,今天主要介绍一下个人通过对OPENCV SIFT代码的分析,进一步理解SIFT算法的相关细节。SIFT(scale-invariant feature transform尺度不变特征转换):是一种广泛使用的尺度不变点特征,其基本思想是在尺度空间中寻找极值点来检测稳定的关键点(也叫特征点或兴趣点)。
SIFT可分为三大工序:1.提取关键点 2.建立描述器(对关键点附加局部特征) 3.采用欧式距离,通过两特征点(附带周围的像素点)的两两比较找出相互匹配的若干对特征点,以此建立景物间的对应关系。
在解释一些概念前,首先引入OPENCV SIFT代码:
// lowe_sift.cpp : 定义控制台应用程序的入口点。 // #include "stdafx.h" #include<iostream> #include <opencv2/highgui/highgui.hpp> #include "opencv2/core/core.hpp" #include "highgui.h" #include "opencv2/imgproc/imgproc.hpp" #include "opencv2/features2d/features2d.hpp" #include "opencv2/nonfree/nonfree.hpp" #include "opencv2/legacy/legacy.hpp" #include <boost/timer.hpp> using namespace cv; using namespace std; int main(int argc, char** argv) { //待匹配的两幅图像,其中img1包括img2,也就是要从img1中识别出img2 Mat img1 = imread("640-1.jpg"); Mat img2 = imread("800-1.jpg"); SIFT sift1, sift2; vector<KeyPoint> key_points1, key_points2; Mat descriptors1, descriptors2, mascara; boost::timer timer; sift1(img1, mascara, key_points1, descriptors1); cout<<" cost time="<<timer.elapsed()<<endl; sift2(img2, mascara, key_points2, descriptors2); //实例化暴力匹配器——BruteForceMatcher BruteForceMatcher<L2<float>> matcher; //定义匹配器算子 vector<DMatch>matches; //实现描述符之间的匹配,得到算子matches timer.restart(); matcher.match(descriptors1, descriptors2, matches); cout<<"match cost time="<<timer.elapsed()<<endl; //提取出前100个最佳匹配结果 std::nth_element(matches.begin(), //匹配器算子的初始位置 matches.begin() + 99, // 排序的数量 matches.end()); // 结束位置 //剔除掉其余的匹配结果 matches.erase(matches.begin() + 100, matches.end()); namedWindow("SIFT_matches"); Mat img_matches; //在输出图像中绘制匹配结果 drawMatches(img1, key_points1, //第一幅图像和它的特征点 img2, key_points2, //第二幅图像和它的特征点 matches, //匹配器算子 img_matches, //匹配输出图像 Scalar(255, 0, 255)); //用红色色直线连接两幅图像中的特征点 imshow("SIFT_matches", img_matches); waitKey(0); return 0; }代码涉及两幅图像的SIFT计算,建立描述器,耗费时间以及关键点的匹配,代码中可人工设定选择了最优的匹配点数。
运行结果如下
两幅建筑物因为细节比较丰富,能够提取的特征点数较多,误匹配点数也较少。在目标物较小或者细节信息量较少的图像中,误匹配率可能相对较大(后续可采用RANSAC(随机采样一致)参数估计法剔除误匹配)
由于特征点较多,可看到SIFT耗费时间在1.867秒,匹配时间在0.593秒,但这个速度会相对比较稳定。
一:相关参数概念
1)尺度空间通过对原始图像进行尺度变换,获得图像多尺度下的尺度空间表示序列,对这些序列进行尺度空间主轮廓的提取,并以该轮廓作为一种特征向量,实现边缘,角点检测和不同分辨率上的特征提取等。
通俗地说,尺度空间中个尺度图像的模糊程度逐渐变大,能够模拟人在距离目标由近到远时视网膜上的形成过程。尺度越大图像越模糊。
在减小图像尺寸的场合经常使用高斯模糊。通过构建高斯金字塔,采用像素抽取和像素插值来减少图像尺度,在第一级金字塔图像,提供尺度为原始分辨率的两倍以保留原始图像信息,增加特征点数量,进而减少局部化损失,提高精度。
2)关键点(keypoint)
在不同尺度空间的图像下检测出的具有方向信息的局部极值点。关键点具有几个特征:尺度(对应缩放不变性),方向(对应旋转不变性),大小,位置(对应平移不变性)。
以建筑物图像作为测试图像,调试过程中,通过对keypoints1监视,可看到关键点中包含了pt位置信息,
size大小信息,angle方向信息,octave尺度信息。
我们可看到,尽管两幅图像中的对象是同一建筑物,但提取出的关键点数却不一定一样,所以拿来计算的匹配总点数capacity只能为关键点较少的1787,因此若在其他关键点少的目标物图像中,我们设定最优的匹配点数超过了较少关键点数,程序就会报错。因此,切记:匹配器选取的最优匹配点数不要超过较少的关键点数。
3)关键点描述(descriptor)
一组描述子向量描述关键点(每个描述子具有128维,向量中不仅包括关键点,也包括关键点周围对其有贡献的像素点)。
描述子向量作为匹配器输入参数,
匹配器参数包括 queryIdx,trainIdx,imgIdx,distance
二:关键点精确定位和匹配方法
1)高斯金字塔构建一副图像->几组图像(octave)
一组图像->几层图像(interval),一般为3~5层
高斯金字塔构建分为两步:对图像做高斯模糊(图像预处理过程,通过局部图像增强,能对后续的描述子方法有很好的补充作用);对图像做降采样(采样之前对图像进行低通滤波处理,保证采样图像不会出现虚假的高频信息)
为保持尺度连续性,上一组图像的底层是由前一组图像的倒数第二层图像间隔点采样生成的。
2)DOG(difference of Gussian高斯差分算子)计算
DOG算子在计算上只需相邻尺度高斯模糊后图像相减,如果高斯差分图像上的像素值没有变化,也就没有特征。特征必须是变化尽可能多的点。
DOG空间的局部极值点组成了关键点。为寻找DOG函数的极值点,每一个像素点和它所有的相邻点比较,以捕捉关键点的最大值和最小值。
3)关键点精确定位
通过对尺度空间DOG函数进行曲线拟合(利用DOG函数在尺度空间的Taylor展开式),可提高关键点的稳定性,降低关键点对噪声和边缘的敏感度。在计算过程中,分别对图像的行,列及尺度三个量进行了修正,去除那些对比度较低的不稳定极值点。Lowe的实验显示,所有取值小于0.04的极值点均可抛弃。(像素灰度值范围在0~1之间)
4)采用梯度直方图统计法,确定关键点方向
梯度直方图:统计以关键点为原点,一定区域内的图像像素点对关键点方向生成所作贡献。
关键点主方向:极值点周围区域梯度脂肪图的主峰值也是关键点方向。
关键点辅方向:在梯度方向直方图中,当存在另一个相当于峰值80%能量的峰值时,则将这个方向认为是该关键点的辅方向。
这可以增强匹配的鲁棒性,Lowe的论文指出大概有15%的关键点具有多方向,但这些点对匹配的稳定性至为关键。
5)关键点描述
分别对模板图和实时图建立关键点描述子集合。目标的识别是通过两点集内关键点描述子的比对来完成的。具有128维德关键点描述子的相似性度量采用欧式距离。
通过尺度不变性求极值点,可以使关键点具有缩放不变的性质;利用关键点领域像素的梯度方向分布特性,
可为每个关键点指定方向参数,从而使描述子对图像旋转具有不变性。
三:总结
针对好的关键点描述子和特征匹配,有几大标准:具有好属性的特征 | 详细描述 |
尺度不变性 | 能在不同尺度下找到特征 |
视角不变性 | 能在视图的不同角度发现特征 |
旋转不变性 | 特征能在图像的各种旋转清醒下被识别 |
平移不变性 | 特征能在FOV(视场角)的各种位置上被识别 |
反射不变性 | 特征能在镜像图像中被识别 |
噪声不变性 | 特征能在有噪声的情况下被检测出来 |
仿射不变性 | 特征能在仿射变换下被识别 |
光照不变性 | 在不同光照下,包括在亮度和对比度变化的情况下,特征可被识别出来。 |
计算效率 | 特征描述子应被有效率的计算和匹配 |
遮挡(occlusion)鲁棒性 | 特征或特征集在被部分遮挡的情况下可悲描述和检测。 |
聚焦胡或模糊鲁棒性 | 特征或特征集在不同程度的角点下能被检测到(如图像金字塔有这种能力) |
点击打开链接
点击打开链接
相关文章推荐
- 转一些SIFT代码链接
- VS2008+OPENCV2.1配置Rob Hess的SIFT代码环境
- Opencv中sift特征提取与匹配代码
- 【OpenCV】一些短代码
- opencv2中代码在opencv3下运行时报错的修改一些方法
- 图像特征检测描述(一):SIFT、SURF、ORB、HOG、LBP特征的原理概述及OpenCV代码实现
- 转一些SIFT代码链接
- 浅谈openCV中的SIFT实现
- 转一些SIFT代码链接
- SIFT图像特征提取 python3.4 + opencv3.1.0代码
- opencv一些函数的底层代码
- 当你在VC++6.0编译上面的代码时会提示一些opencv的函数没有被定义,原因是环境没设置好
- 浅谈C\C++代码优化中的一些小技巧
- SIFT Opencv 代码
- 基于C++和OpenCv的SIFT_图像局部特征检测算法代码的实现
- linux中结合opencv编译c++代码
- SURF、SIFT、Fast角点检测的代码(opencv)
- 转一些SIFT代码链接
- 基于Opencv的SIFT代码,使用FLANN匹配
- 论文里公式P(Y|X)结合代码的一些常识