SIFT特征点相对于ORB计算速度较慢,在没有GPU加速情况下,无法满足视觉里程计的实时性要求,或者无法运行在手机平台上,但是效果更好,精度更高。在应用时可以择优选取,了解其本质原理的动机是为了自己使用时,可以对其进行修改,针对自己的应用场景优化算法。

有足够的时间,可以去看D. Lowe的论文,理解起来更透彻.

1. 用高斯核构建尺度空间

对于构建的高斯金字塔,金字塔每层多张图像合称为一组(Octave),每组有多张(也叫层Interval)图像。通常高斯金字塔最底层为原始图像第0组,octave之间为降采样过程,对应OpenCV里的函数为PryDown()。注意这里降采样PryDown在直观上是金字塔向上走,要注意区分。

金字塔的第i组octave通过对第i-1组降采样获得(通常降采样的比例为2,也就是高斯模糊后去掉偶数行/列像素)。在每一组octave中还需要使用高斯核σ创建连续的尺度空间图像: σ, kσ, k2σ,..., kn-1σ,其中,k=21/s,s为每一组octave中再分的尺度层数。构建连续尺度空间的目的是为了提取特征点(角点)时,该特征点不仅在二维图像空间中是梯度极值点,还需要在第三维的尺度空间也是极值点。

当然,检测角点并不是直接在高斯卷积构建的尺度空间中,而是DoG(Difference of Gaussian)高斯差分尺度空间中,因此,为了保证DOG高斯差分尺度空间变化的连续性(是高斯卷积空间相邻尺度的差),需要在每一层octave的高斯卷积尺度首尾两边多创建一个尺度。

这里注意理解连续性,不是微积分里面的连续性,指的是尺度空间连续,(σ, kσ, k2σ,..., ks-1σ) ,(2σ, 2kσ, 2k2σ,..., 2ks-1σ) 。从这里可以看出,尺度空间主要由σ主导.

2. 在DoG尺度空间中检测极值点

  虽然在高斯拉普拉斯LoG尺度空间中检测极值点是最精确的,但是由于计算量比较大,通常使用DoG尺度空间对其进行近似,在DoG尺度空间中进行局部最值搜索。有关LoG可以参考http://fourier.eng.hmc.edu/e161/lectures/gradient/node8.html.LoG也就是将拉普拉斯算子作用于高斯核函数后形成的新的核函数,拉普拉斯算子的作用是求二阶偏导,对噪点响应较敏感,因此需要先用高斯核对图像进行平滑.

  由于DoG尺度空间是离散的,我们只能通过比较DoG空间中某个点周围26个点来获取一个点是否可以作为极值(和ORB一样,这里可以选较少的几个先比较剔除).

        

但是为了进一步获得精确的亚像素级别特征点位置,需要将DoG函数D(x,y,σ)在像素极值点附近二阶展开,对亚像素极值求偏导后=0求解.

    

    

第二式带入第一式后可以得到亚像素极值点对应的DoG函数值,也就是对比度contrast:

    

  在检测到DoG尺度空间中的极值点(extremum)后,使用两个阈值来剔除质量不高(unstable)的点,contrastThreshold以及edgeThreshold.首先在DoG尺度空间中在potential的极值点附近二阶泰勒展开,寻找更精确的极值点坐标,其中,contrastThreshold是为了剔除对比度不高的极值点,edgeThreshold是为了剔除边缘点,因为边缘点也满足极值点的条件,但是不是需要的角点.

剔除对比度不高(不稳定)的点,|D(x)| < 0.03,这里假设DoG函数取值范围[0, 1].

剔除边缘点借鉴了Harris Corner的检测方法,计算特征点邻域的Hessian矩阵。

    

一次求导物理意义是变化率/梯度,二次求导物理意义是曲率,因此Hessian矩阵更能体现一个边缘的特征程度。

该Hessian矩阵的特征值代表了边缘特征的主曲率。两个特征值之间的比例体现了邻域两个垂直方向的曲率差别,这里去掉比例较大(横跨边缘和沿着边缘方向的曲率差别较大,>10)的点。注意这里不用特征值分解,而是用矩阵迹和行列式的性质,得到两个特征值比例就行.

3. 计算特征点方向

在检测到的特征点一个圆形邻域像素集合上计算各自的梯度幅值和梯度方向:

     

将360度方向划分为方向直方图中的36个bins,获取直方图的peak,作为特征点的方向。如果存在大于80%*peak幅值的方向,则在同一个尺度特征点(x,y,σ)上新建一个方向不同的特征点,有多少个新建多少个特征点.论文中说,相同位置的不会超过15%, 但是可以显著增强匹配的稳定性.注意这里的邻域是有区分度的,距离特征点近的像素在计算直方图时权重较大,使用高斯分布加权处理。

获得关键点主方向后,每个关键点有三个信息(x,y,σ,θ):位置、尺度、方向。

4. 计算128维描述子

在对邻域像素点采样前,要旋转xy坐标系和关键点的方向对齐,使得特征点具备方向不变的特征(旋转相机后,特征点描述子不变)。

将旋转后区域划分为4×4=16个子区域(每个区域间隔为mσ像元),在每个子区域内计算8个方向的梯度直方图,绘制每个方向梯度方向的累加值,形成一个种子点。
与求主方向不同的是,此时,每个子区域梯度方向直方图将0°~360°划分为8个方向区间,每个区间为45°。即每个种子点有8个方向区间的梯度强度信息。由于存在d×d,即4×4个子区域,所以最终共有4×4×8=128个数据,形成128维SIFT特征矢量。

计算128维空间中描述子的距离,SIFT的实现中计算的是欧氏距离.

练习:

OpenCV中提供的goodFeatureToTrack()可以使用Harris和Shi-Tomasi角点检测算法对图像进行角点提取,注意没有构建尺寸空间,且没有提供描述子计算,是最简单的角点提取算法,但是通过对其参数的调整,可以了解一些实现特点:

#include "common.h"
#include <opencv2/nonfree/features2d.hpp> using namespace std;
using namespace cv; Mat origin, img;
vector<Point2f> keyPoints;
string title("FeatureDetector");
int maxCorners();
int qualityLevel();
int minDistance();
int blockSize();
int useHarrisDetector();
int k();
int method(); void detectCorner(int, void*); int main(){
origin = imread("/home/shang/dataset/opencv/building.jpg",CV_LOAD_IMAGE_COLOR);
if(!origin.data){
cerr << "No data!"<< endl;
return -;
}
cvtColor(origin, img, CV_BGR2GRAY);
namedWindow(title);
createTrackbar("maxCorners", title, &maxCorners, , detectCorner);
createTrackbar("qualityLevel (%)", title, &qualityLevel, , detectCorner);
createTrackbar("minDistance", title, &minDistance, , detectCorner);
createTrackbar("blockSize", title, &blockSize, , detectCorner);
createTrackbar("useHarrisDetector", title, &useHarrisDetector, , detectCorner);
createTrackbar("k when in HarrisDetector", title, &k, , detectCorner);
createTrackbar("Method", title, &method, , detectCorner);
detectCorner(,);
imshow(title, img); while(true){
if(waitKey()==)
break;
}
} void detectCorner(int, void*){
Mat result ;
img.copyTo(result);
switch (method){
case :
if(qualityLevel==) {
qualityLevel = ;
setTrackbarPos("qualityLevel (%)", title, );
}
if(blockSize==) {
blockSize = ;
setTrackbarPos("blockSize", title, );
}
goodFeaturesToTrack(result,
keyPoints,
maxCorners,
qualityLevel/100.0,
minDistance,
noArray(),
blockSize,
useHarrisDetector,
k/100.0
); cvtColor(result, result, CV_GRAY2RGB);
for(vector<Point2f>::const_iterator it=keyPoints.begin(); it!=keyPoints.end(); it++){
circle(result, *it, , Scalar(,,),);
}
imshow(title, result);
break;
case :
SiftFeatureDetector detector();
vector<KeyPoint> keyPoints;
detector.detect(result, keyPoints);
cvtColor(result, result, CV_GRAY2RGB);
for(vector<KeyPoint>::const_iterator it=keyPoints.begin(); it!=keyPoints.end(); it++){
rectangle(result, Rect(it->pt.x-,it->pt.y-,,), Scalar(,,),);
}
imshow(title, result);
break;
} }

参考:

SIFT特征提取分析

【OpenCV】SIFT原理与源码分析

SIFT 特征点提取算法的更多相关文章

  1. opencv学习之路(33)、SIFT特征点提取(一)

    一.简介 二.OpenCV中的SIFT算法接口 #include "opencv2/opencv.hpp" #include <opencv2/nonfree/nonfree ...

  2. 基于SIFT特征的全景图像拼接

    基于SIFT特征的全景图像拼接 分类: image Machine learning2013-07-05 13:33 2554人阅读 评论(3) 收藏 举报 基于SIFT特征的全景图像拼接 分类: 计 ...

  3. SIFT特征原理简析(HELU版)

    SIFT(Scale-Invariant Feature Transform)是一种具有尺度不变性和光照不变性的特征描述子,也同时是一套特征提取的理论,首次由D. G. Lowe于2004年以< ...

  4. Sift算子特征点提取、描述及匹配全流程解析

    Sift之前的江湖 在Sift横空出世之前,特征点检测与匹配江湖上占据霸主地位的是角点检测家族.先来探究一下角点家族不为人知的恩怨情仇. 角点家族的族长是Moravec在1977年提出的Moravec ...

  5. opencv java api提取图片sift特征

    opencv在2.4.4版本以后添加了对java的最新支持,可以利用java api了.下面就是我利用opencv的java api 提取图片的sift特征. import org.opencv.co ...

  6. OpenCV特征点提取----Fast特征

    1.FAST(featuresfrom accelerated segment test)算法 http://blog.csdn.net/yang_xian521/article/details/74 ...

  7. opencv学习之路(35)、SURF特征点提取与匹配(三)

    一.简介 二.opencv中的SURF算法接口 三.特征点匹配方法 四.代码 1.特征点提取 #include "opencv2/opencv.hpp" #include < ...

  8. FAST特征点检测算法

    一 原始方法 简介 在局部特征点检测快速发展的时候,人们对于特征的认识也越来越深入,近几年来许多学者提出了许许多多的特征检测算法及其改进算法,在众多的特征提取算法中,不乏涌现出佼佼者. 从最早期的Mo ...

  9. 特征点检测算法——FAST角点

    上面的算法如SIFT.SURF提取到的特征也是非常优秀(有较强的不变性),但是时间消耗依然很大,而在一个系统中,特征提取仅仅是一部分,还要进行诸如配准.提纯.融合等后续算法.这使得实时性不好,降系了统 ...

随机推荐

  1. nodejs+postgis实现搜周边

    利用nodejs搭建服务器,并连接PostgreSQL数据库,利用前端传过来的中心点坐标和搜索半径,进行空间查询,实现简单的搜周边,下面是实现流程和nodejs的代码: app.post('/tose ...

  2. 截取Excel字符串的部分字符

    截取Excel字符串的部分字符 我们可以使用Mid.Left.Right等函数从长字符串内获取一部分字符.  ①LEFT函数:  LEFT(text,num_chars)  Text是包含要提取字符的 ...

  3. linux常用搜索文件命令

    使用linux系统难免会忘记文件所在的位置,可以使用以下命令对系统中的文件进行搜索.搜索文件的命令为”find“:”locate“:”whereis“:”which“:”type“ 方法/步骤     ...

  4. 关闭 XXXXX 前你必须关闭所有会话框

    这个问题应该是和Microsoft管理控制台(Microsoft Management Console,MMC)有关系 我是在使用 任务计划程序 时碰到这个问题的,网上也有其他人在使用 事件查看器 的 ...

  5. jar包解压

    jar -xvf project.jar 解压到当前文件夹

  6. Hibernate之CRUD实践

    Hibernate作为一个高度封装的持久层框架,曾经是非常牛逼的,现在虽然应用不是特别广,比如我前公司主要是做OA的,应用的框架就是Spring+SpringMVC+Hibernate. Hibern ...

  7. 【转】计算Java List中的重复项出现次数

    本文演示如何使用Collections.frequency和Map来计算重复项出现的次数.(Collections.frequency在JDK 1.5版本以后支持) package com.qiyad ...

  8. Java 内部类综述

    转载自:https://blog.csdn.net/justloveyou_/article/details/53245561

  9. 高并发Web服务的演变——节约系统内存和CPU

    节约系统内存和CPU http://www.csdn.net/article/2015-02-12/2823952 Web系统大规模并发——电商秒杀与抢购 http://www.csdn.net/ar ...

  10. 算法是什么(二)手写个链表(java)

    算法是什么(二)手写个链表(java)   liuyuhang原创,未经允许禁止转载 目录 算法是什么(〇) 很多语言的API中都提供了链表实现,或者扩展库中实现了链表. 但是更多的情况下,Map(或 ...