【OpenCV】SIFT原理与源码分析
SIFT简介
Scale Invariant Feature Transform,尺度不变特征变换匹配算法,是由David G. Lowe在1999年(《Object Recognition from Local Scale-Invariant Features》)提出的高效区域检测算法,在2004年(《Distinctive Image Features from Scale-Invariant Keypoints》)得以完善。
SIFT特征对旋转、尺度缩放、亮度变化等保持不变性,是非常稳定的局部特征,现在应用很广泛。而SIFT算法是将Blob检测,特征矢量生成,特征匹配搜索等步骤结合在一起优化。我会更新一系列文章,分析SIFT算法原理及OpenCV 2.4.2实现的SIFT源码:
- DoG尺度空间构造(Scale-space extrema detection)
- 关键点搜索与定位(Keypoint localization)
- 方向赋值(Orientation assignment)
- 关键点描述(Keypoint descriptor)
- OpenCV实现:特征检测器FeatureDetector
- SIFT中LoG和DoG的比较
SIFT in OpenCV
构造函数:
SIFT::SIFT(int nfeatures=, int nOctaveLayers=, double contrastThreshold=0.04, double edgeThreshold=
, double sigma=1.6)
nOctaveLayers:金字塔中每组的层数(算法中会自己计算这个值,后面会介绍)。
contrastThreshold:过滤掉较差的特征点的对阈值。contrastThreshold越大,返回的特征点越少。
edgeThreshold:过滤掉边缘效应的阈值。edgeThreshold越大,特征点越多(被多滤掉的越少)。
sigma:金字塔第0层图像高斯滤波系数,也就是σ。
重载操作符:
void SIFT::operator()(InputArray img, InputArray mask, vector<KeyPoint>& keypoints, OutputArray
descriptors, bool useProvidedKeypoints=false)
mask:图像检测区域(可选)
keypoints:特征向量矩阵
descipotors:特征点描述的输出向量(如果不需要输出,需要传cv::noArray())。
useProvidedKeypoints:是否进行特征点检测。ture,则检测特征点;false,只计算图像特征描述。
函数源码
SIFT::SIFT( int _nfeatures, int _nOctaveLayers,
double _contrastThreshold, double _edgeThreshold, double _sigma )
: nfeatures(_nfeatures), nOctaveLayers(_nOctaveLayers),
contrastThreshold(_contrastThreshold), edgeThreshold(_edgeThreshold), sigma(_sigma)
// sigma:对第0层进行高斯模糊的尺度空间因子。
// 默认为1.6(如果是软镜摄像头捕获的图像,可以适当减小此值)
{
}
void SIFT::operator()(InputArray _image, InputArray _mask,
vector<KeyPoint>& keypoints,
OutputArray _descriptors,
bool useProvidedKeypoints) const
// mask :Optional input mask that marks the regions where we should detect features.
// Boolean flag. If it is true, the keypoint detector is not run. Instead,
// the provided vector of keypoints is used and the algorithm just computes their descriptors.
// descriptors – The output matrix of descriptors.
// Pass cv::noArray() if you do not need them.
{
Mat image = _image.getMat(), mask = _mask.getMat(); if( image.empty() || image.depth() != CV_8U )
CV_Error( CV_StsBadArg, "image is empty or has incorrect depth (!=CV_8U)" ); if( !mask.empty() && mask.type() != CV_8UC1 )
CV_Error( CV_StsBadArg, "mask has incorrect type (!=CV_8UC1)" ); // 得到第1组(Octave)图像
Mat base = createInitialImage(image, false, (float)sigma);
vector<Mat> gpyr, dogpyr;
// 每层金字塔图像的组数(Octave)
int nOctaves = cvRound(log( (double)std::min( base.cols, base.rows ) ) / log(.) - ); // double t, tf = getTickFrequency();
// t = (double)getTickCount(); // 构建金字塔(金字塔层数和组数相等)
buildGaussianPyramid(base, gpyr, nOctaves);
// 构建高斯差分金字塔
buildDoGPyramid(gpyr, dogpyr); //t = (double)getTickCount() - t;
//printf("pyramid construction time: %g\n", t*1000./tf); // useProvidedKeypoints默认为false
// 使用keypoints并计算特征点的描述符
if( !useProvidedKeypoints )
{
//t = (double)getTickCount();
findScaleSpaceExtrema(gpyr, dogpyr, keypoints);
//除去重复特征点
KeyPointsFilter::removeDuplicated( keypoints ); // mask标记检测区域(可选)
if( !mask.empty() )
KeyPointsFilter::runByPixelsMask( keypoints, mask ); // retainBest:根据相应保留指定数目的特征点(features2d.hpp)
if( nfeatures > )
KeyPointsFilter::retainBest(keypoints, nfeatures);
//t = (double)getTickCount() - t;
//printf("keypoint detection time: %g\n", t*1000./tf);
}
else
{
// filter keypoints by mask
// KeyPointsFilter::runByPixelsMask( keypoints, mask );
} // 特征点输出数组
if( _descriptors.needed() )
{
//t = (double)getTickCount();
int dsize = descriptorSize();
_descriptors.create((int)keypoints.size(), dsize, CV_32F);
Mat descriptors = _descriptors.getMat(); calcDescriptors(gpyr, keypoints, descriptors, nOctaveLayers);
//t = (double)getTickCount() - t;
//printf("descriptor extraction time: %g\n", t*1000./tf);
}
}
【OpenCV】SIFT原理与源码分析的更多相关文章
- OpenCV SIFT原理与源码分析
http://blog.csdn.net/xiaowei_cqu/article/details/8069548 SIFT简介 Scale Invariant Feature Transform,尺度 ...
- 【OpenCV】SIFT原理与源码分析:DoG尺度空间构造
原文地址:http://blog.csdn.net/xiaowei_cqu/article/details/8067881 尺度空间理论 自然界中的物体随着观测尺度不同有不同的表现形态.例如我们形 ...
- 【OpenCV】SIFT原理与源码分析:关键点描述
<SIFT原理与源码分析>系列文章索引:http://www.cnblogs.com/tianyalu/p/5467813.html 由前一篇<方向赋值>,为找到的关键点即SI ...
- 【OpenCV】SIFT原理与源码分析:方向赋值
<SIFT原理与源码分析>系列文章索引:http://www.cnblogs.com/tianyalu/p/5467813.html 由前一篇<关键点搜索与定位>,我们已经找到 ...
- 【OpenCV】SIFT原理与源码分析:关键点搜索与定位
<SIFT原理与源码分析>系列文章索引:http://www.cnblogs.com/tianyalu/p/5467813.html 由前一步<DoG尺度空间构造>,我们得到了 ...
- OpenCV学习笔记(27)KAZE 算法原理与源码分析(一)非线性扩散滤波
http://blog.csdn.net/chenyusiyuan/article/details/8710462 OpenCV学习笔记(27)KAZE 算法原理与源码分析(一)非线性扩散滤波 201 ...
- ConcurrentHashMap实现原理及源码分析
ConcurrentHashMap实现原理 ConcurrentHashMap源码分析 总结 ConcurrentHashMap是Java并发包中提供的一个线程安全且高效的HashMap实现(若对Ha ...
- HashMap和ConcurrentHashMap实现原理及源码分析
HashMap实现原理及源码分析 哈希表(hash table)也叫散列表,是一种非常重要的数据结构,应用场景及其丰富,许多缓存技术(比如memcached)的核心其实就是在内存中维护一张大的哈希表, ...
- (转)ReentrantLock实现原理及源码分析
背景:ReetrantLock底层是基于AQS实现的(CAS+CHL),有公平和非公平两种区别. 这种底层机制,很有必要通过跟踪源码来进行分析. 参考 ReentrantLock实现原理及源码分析 源 ...
随机推荐
- rest_framework之版本控制
简介 API版本控制可以用来在不同的客户端使用不同的行为.REST框架提供了大量不同的版本设计. 版本控制是由传入的客户端请求决定的,并且可能基于请求URL,或者基于请求头. 有许多有效的方法达到版本 ...
- 学习调用第三方的WebService服务
互联网上面有很多的免费webService服务,我们可以调用这些免费的WebService服务,将一些其他网站的内容信息集成到我们的应用中显示,下面就以查询国内手机号码归属地为例进行说明. 首先安利一 ...
- “我爱淘”第二冲刺阶段Scrum站立会议4
完成任务: 完成了首页中的推荐功能,推荐的是最近添加的需要卖的书,注册功能实现了它,可以对数据库进行添加. 计划任务: 在客户端实现分类功能,通过学院的分类查看书籍. 遇到问题: 分类功能,根据不同学 ...
- VS2013安装及单元测试
aaarticlea/png;base64,iVBORw0KGgoAAAANSUhEUgAAAZ0AAAIlCAIAAACBzLJwAAAACXBIWXMAAA7EAAAOxAGVKw4bAAAgAE ...
- C#高级编程 (第六版) 学习 第七章:委托和事件
第七章 委托和事件 回调(callback)函数是Windows编程的一个重要方面,实际上是方法调用的指针,也称为函数指针. .Net以委托的形式实现了函数指针的概念,.Net的委托是类型安全的. 委 ...
- 关于解决乱码问题的一点探索之二(涉及Unicode(utf-16)和GBK)
在上篇日志中(链接),我们讨论了utf-8编码和GBK编码之间转化的乱码问题,这一篇我们讨论Unicode(utf-16编码方式)与GBK编码之间转换的乱码问题. 在Windows系统 ...
- Java 异常总结
Throwablede类是 Java 语言中所有错误或异常的超类. 两个子类的实例,Error 和 Exception Error 是 Throwablede 的子类,用于指示合理的应用程序不应该试图 ...
- 简易四则运算生成程序——添加GUI支持
项目成员:张金生 张政 工程地址: https://coding.net/u/jx8zjs/p/paperOne/git ssh://git@git.coding.net:jx8zjs/pap ...
- java 两个数组合并
需求:两个字符串合并(如果想去重复,参考下一篇--数组去重复及记录重复个数) //方法一 Arrays类 String[] a = {"A","B"," ...
- Linux下修改环境变量PATH
1.什么是环境变量(PATH) 在Linux中,在执行命令时,系统会按照PATH的设置,去每个PATH定义的路径下搜索执行文件,先搜索到的文件先执行. 我们知道查阅文件属性的指令ls 完整文件名为:/ ...