SIFT
- 简介
SIFT(scale invariant feature transform)——尺度不变特征转换,用来检测和描述局部特征,运用范围包括object recognition(目标检测), robotic mapping and navigation(机器人地图感知与导航), image stitching(图像拼接), 3D modeling(3D建模), gesture recognition(手势识别), video tracking(视频追踪), individual identification of wildlife(野生物个体识别) and match moving(动作匹配)
2. 特点
(1)Sift特征是图像的局部特征,对平移、旋转、尺度缩放、亮度变化、遮挡和噪声等具有良好的不变性,对视觉变化、仿射变换也保持一定程度的稳定性。
(2)独特性好,信息量丰富,适用于在海量特征数据库中进行快速、准确的匹配。
(3)多量性,即使少数的几个物体也可以产生大量Sift特征向量。
(4)速度相对较快,经优化的Sift匹配算法甚至可以达到实时的要求。
(5)可扩展性强,可以很方便的与其他形式的特征向量进行联合。
3. 算法
3.1. 构造高斯差分空间图像。
Sift特征点的检测时在DOG(difference of gausssian)图像上进行的,DOG图像是将相邻尺度空间图像相减得到的。且金字塔的每一层都要构造一个DOG空间图像。默认参数是金字塔4层,即4个octave,每一个octave中有5张不同尺度的图片,不同octave的图片尺寸大小不同,所以每一层中就会得到4幅DOG图像。
高斯金字塔的第1层第1副原图像是将原图像放大2倍且sigma(sigma=1.6)模糊,第2幅图像是k*sigma(k等于根号2)模糊,第3幅是k*k*sigma模糊,后面类推…
高斯金字塔第2层第1幅图是选择金字塔上一层(这里是第1层)中尺度空间参数为k*k*sigma的那幅图(实际上是2倍的尺度空间)进行降采样(尺寸大小为原来的1/4倍)得到,如果k不等于根号2,那么取原图的2*sigma降采样得到。第2层第2幅图是在本层第一幅图尺度模糊系数增加k倍模糊后的图像,后面类似…
示意图如下所示:
3.2、寻找极大极小值点。
将每个像素点与其所在的那幅图像邻域的8个像素,它所在的向量尺度空间上下2幅图对应位置邻域各9个点,总共26个点进行像素值比较,如果该点是最大或者最小点,则改点就暂时列为特征点。
其邻图如下:
3.3、精确定位极值点
子像素级极值点:
由于上面找到的近似极值点落在像素点的位置上,实际上我们在像素点附近如果用空间曲面去拟合的话,很多情况下极值点都不是恰好在像素点上,而是在附近。所以sift算法提出的作者用泰勒展开找到了亚像素级的特征点。这种点更稳定,更具有代表性。
消除对比度低的特征点:
对求出亮度比较低的那些点直接过滤点,程序中的阈值为0.03.
消除边界上的点:
处理方法类似harrs角点,把平坦区域和直线边界上的点去掉,即对于是边界上的点但又不是直角上的点,sift算法是不把这些点作为特征点的。
3.4、选取特征点主方向
在特征点附近选取一个区域,该区域大小与图图像的尺度有关,尺度越大,区域越大。并对该区域统计36个bin的方向直方图,将直方图中最大bin的那个方向作为该点的主方向,另外大于最大bin80%的方向也可以同时作为主方向。这样的话,由于1个特征点有可能有多个主方向,所以一个特征点有可能有多个128维的描述子。如下图所示:
3.5、 构造特征点描述算子。
以特征点为中心,取领域内16*16大小的区域,并把这个区域分成4*4个大小为4*4的小区域,每个小区域内计算加权梯度直方图,该权值分为2部分,其一是该点的梯度大小,其二是改点离特征点的距离(二维高斯的关系),每个小区域直方图分为8个bin,所以一个特征点的维数=4*4*8=128维。示意图如下(该图取的领域为8*8个点,因此描述子向量的维数为32维):
4. 在opencv中的使用
// opencv_empty_proj.cpp : 定义控制台应用程序的入口点。
// #include <opencv2/opencv.hpp>
#include <opencv2/features2d/features2d.hpp>
#include<opencv2/nonfree/nonfree.hpp>
#include<opencv2/legacy/legacy.hpp>
#include<vector>
using namespace std;
using namespace cv;
int main()
{
const char* imagename = "SIFT.bmp"; //从文件中读入图像
Mat img = imread(imagename);
Mat img2=imread("SIFT1.bmp"); //如果读入图像失败
if(img.empty())
{
fprintf(stderr, "Can not load image %s\n", imagename);
return -1;
}
if(img2.empty())
{
fprintf(stderr, "Can not load image %s\n", imagename);
return -1;
}
//显示图像
imshow("image before", img);
imshow("image2 before",img2); //sift特征检测
SiftFeatureDetector siftdtc;
vector<KeyPoint>kp1,kp2; siftdtc.detect(img,kp1);
Mat outimg1;
drawKeypoints(img,kp1,outimg1);
imshow("image1 keypoints",outimg1);
KeyPoint kp; vector<KeyPoint>::iterator itvc;
for(itvc=kp1.begin();itvc!=kp1.end();itvc++)
{
cout<<"angle:"<<itvc->angle<<"\t"<<itvc->class_id<<"\t"<<itvc->octave<<"\t"<<itvc->pt<<"\t"<<itvc->response<<endl;
} siftdtc.detect(img2,kp2);
Mat outimg2;
drawKeypoints(img2,kp2,outimg2);
imshow("image2 keypoints",outimg2); SiftDescriptorExtractor extractor;
Mat descriptor1,descriptor2;
BruteForceMatcher<L2<float>> matcher;
vector<DMatch> matches;
Mat img_matches;
extractor.compute(img,kp1,descriptor1);
extractor.compute(img2,kp2,descriptor2); imshow("desc",descriptor1);
cout<<endl<<descriptor1<<endl;
matcher.match(descriptor1,descriptor2,matches); drawMatches(img,kp1,img2,kp2,matches,img_matches);
imshow("matches",img_matches); //此函数等待按键,按键盘任意键就返回
waitKey();
return 0;
}
SIFT的更多相关文章
- sift特征
已经有很多博客已经将sift特征提取算法解释的很清楚了,我只是记录一些我不明白的地方,并且记录几个理解sift特征比较好的博客. 1. http://aishack.in/tutorials/sift ...
- sift特征源码
先贴上我对Opencv3.1中sift源码的注释吧,虽然还有很多没看懂.先从detectAndCompute看起 void SIFT_Impl::detectAndCompute(InputArray ...
- opencv中的SIFT,SURF,ORB,FAST 特征描叙算子比较
opencv中的SIFT,SURF,ORB,FAST 特征描叙算子比较 参考: http://wenku.baidu.com/link?url=1aDYAJBCrrK-uk2w3sSNai7h52x_ ...
- 特征描述算子-sift
特征描述算子-sift http://boche.github.io/download/sift/Introduction%20to%20SIFT.pdf
- SIFT特征详解
1.SIFT概述 SIFT的全称是Scale Invariant Feature Transform,尺度不变特征变换,由加拿大教授David G.Lowe提出的.SIFT特征对旋转.尺度缩放.亮度变 ...
- SIFT中的尺度空间和传统图像金字塔
SIFT中的尺度空间和传统图像金字塔 http://www.zhizhihu.com/html/y2010/2146.html 最近自己混淆了好多概念,一边弄明白的同时,也做了一些记录,分享一下.最近 ...
- SIFT特征提取分析
SIFT特征提取分析 sift 关键点,关键点检测 读'D. G. Lowe. Distinctive Image Features from Scale-Invariant Keypoints[J] ...
- SIFT特征提取分析(转载)
转载自: http://blog.csdn.net/abcjennifer/article/details/7639681 SIFT(Scale-invariant feature transform ...
- SIFT定位算法关键步骤的说明
1. SIFT算法中一些符号的说明 $I(x,y)$表示原图像. $G(x,y,\sigma)$表示高斯滤波器,其中$G(x,y,\sigma) = \frac{1}{2\pi\sigma^2}exp ...
- SIFT 特征提取算法总结
原文链接:http://www.cnblogs.com/cfantaisie/archive/2011/06/14/2080917.html 主要步骤 1).尺度空间的生成: 2).检测尺度空间极 ...
随机推荐
- 第13章 Swing程序设计----JDialog窗体
JDialog窗体是Swing组件中的对话框 JDialog窗体的功能是从一个窗体中弹出另一个窗体,就像是在使用IE浏览器时弹出的确定对话框一样. 在应用程序中创建JDialog窗体需要实例化JDia ...
- jPaginate应用
分页结合bingojs需要注意两点 1.标签要放在bg-render外面 2.ajax请求参数包含一页显示多少条数据的字段,跟分页插件无关. 调用jPaginate插件的方法很简单: $('#page ...
- LinuxIP地址、网卡相关、克隆、VM
改IP地址(#setup) 1.输入vi /etc/sysconfig/network-scripts/ifcfg-eth0 2.里面的内容修改为 DEVICE=eth0HWADDR=FC:4D:D4 ...
- ListView控件的Insert、Edit和Delete功能(第一部分)
摘自:http://blog.ashchan.com/archive/2007/08/28/listview-control-insert-edit-amp-delete-part-1aspx/ Li ...
- 【滚动数组】 dp poj 1036
题意:一群匪徒要进入一个酒店.酒店的门有k+1个状态,每个匪徒的参数是:进入时间,符合的状态,携带的钱. 酒店的门刚开始状态0,问最多这个酒店能得到的钱数. 思路: dp数组为DP[T][K]. 转移 ...
- C++中L和_T()之区别
字符串前面加L表示该字符串是Unicode字符串._T是一个宏,如果项目使用了Unicode字符集(定义了UNICODE宏),则自动在字符串前面加上L,否则字符串不变.因此,Visual C++里边定 ...
- 轻松搭建docker应用的mesos集群
7条命令在docker中部署Mesos集群 所有使用的Docker容器构建文件是有也.您可以在本地构建每个容器或只使用位于Docker Hub预构建的容器.下面的命令会自动下载所需的预建的容器为您服务 ...
- Count on the path
Count on the path Time Limit: 5000/2500 MS (Java/Others) Memory Limit: 131072/131072 K (Java/Othe ...
- HDU5907 Find Q 数学
题目大意:求当前串中只含q的连续子串的个数 题目思路:水题,但要注意的是计算过程中可能超int范围; #include<iostream> #include<algorithm> ...
- Hadoop RPC机制
RPC(Remote Procedure Call Protocol)远程过程调用协议,它是一种通过网络从远程计算机程序上请求服务,而不需要了解底层网络技术的协议.Hadoop底层的交互都是通过 rp ...