【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实现原理及源码分析 源 ...
随机推荐
- golang笔记2_程序结构
golang程序结构 2.1 命名 Golang中的命名遵循这样一个简单原则,名字的开头必须是字母或者下划线,后面跟字母.数字或者下划线(这里与C语言中是一致的). 在函数内部声明的实体,即局部变量, ...
- UI优秀框架(库)
1.vux 官网:https://doc.vux.li/zh-CN/ Github:https://github.com/airyland/vux 13818 Stars 3064 Forks ...
- 用了这么多年的MCU,你知道哪些MCU原厂最牛?
单片机诞生于1971年,经历了SCM.MCU.SoC三大阶段.单片机由以前的1位.4位.8位.16位,发展到现在的32位甚至64位. 90年代后随着消费电子产品大发展,单片机技术得到了巨大提高,相继诞 ...
- 作业要求20181113-4 Beta阶段第1周/共2周 Scrum立会报告+燃尽图 02
作业要求:https://edu.cnblogs.com/campus/nenu/2018fall/homework/2384 版本控制:[https://git.coding.net/lglr201 ...
- Pyhont:内建函数enumerate
1.enumerate的中文意思 2.enumerate参数为可遍历的变量,如字符串.列表等,其返回值为enumerate类. 3.enumerate多用在for循环中得到计数 . [注]:若在for ...
- PAT L1-015 跟奥巴马一起画方块
https://pintia.cn/problem-sets/994805046380707840/problems/994805124398956544 美国总统奥巴马不仅呼吁所有人都学习编程,甚至 ...
- SQL优化套路
直奔主题: (1) SELECT(2) DISTINCT <SELECT_LIST>(3) FROM <LEFT_TABLE> <JOIN_TYPE> (4) JO ...
- java 类的强制转型
- ssh-keygen的使用方法及配置authorized_keys两台linux机器相互认证
一.概述 1.就是为了让两个linux机器之间使用ssh不需要用户名和密码.采用了数字签名RSA或者DSA来完成这个操作 2.模型分析 假设 A (192.168.20.59)为客户机器,B(192. ...
- css基于文件格式使用不同的样式
a[href^="http://"]{ padding-right: 20px; background: url(external.gif) no-repeat center ri ...