SIFT算法学习

来源:互联网 发布:计算机就业方向 知乎 编辑:程序博客网 时间:2024/05/21 01:53

好的博文:

《1》http://blog.csdn.net/abcjennifer/article/details/7639681    理论

《2》http://blog.csdn.net/abcjennifer/article/details/7365882  应用

《3》http://www.cnblogs.com/cql/archive/2013/05/23/3095749.html  理轮;

《4》http://blog.csdn.net/masibuaa/article/details/9207657      robhess代码解析

《5》http://blog.csdn.net/masibuaa/article/details/9191309  RobHess代码解析

《6》http://www.cnblogs.com/cql/archive/2013/05/23/3095749.html   robhess 代码编译。

《7》http://blog.csdn.net/xiaowei_cqu/article/details/8067881  尺度理论

限于本人的编码水平和理论水平,看了看lowe的论文,只能了解大意,不能深入的理解,于是借助前面几篇中文的翻译和博主们对sift算法的理解来理解sift算法。

借助于4,5博文首先编译opensift,有了代码就啥都好办了,opencv虽然有sift实现但是封装的太好了,反而不容易理解。

按照6博文编译的过程中出现了unistd.h无法找到的错误,去掉后又出现getopt无定义等错误,可以先去掉出错的*.c文件,出错的主要是main函数的命令行解析函数,对理解代码没有什么太大的帮助和障碍,然后运行match.c文件中的main函数就可以了。在vs中的命令行中写入要进行sift运算的两个图片按下f5就可以了


初步运行达到博文6的效果。


首先介绍sift使用的基础算法

1.kd树实现最近邻搜索

(1)k近邻算法1.首先查找出与训练集T中找到与实例x最近邻的k个点,2.在这k个点所属的类别,根据多数表决原则,决定x所属的类别y。

(2)kd树。参看《统计学习方法》p41。1.开始构造根节点,选择x(1)坐标轴在训练集T中所有的实例的中点作为切分点,将所有的训练集T根据根节点所对应的超平面分为两个子区域。2 重复。对已经切分出来的子区域再根据坐标轴x(j)进行继续切分,知道切分的区域中只有一个实例,这个实例就是叶节点。3.切分到叶节点kd树构造完毕。

(3)kd树实现knn算法。1.构造kd树。2.由根节点开始递归的向下访问kd树,如果x的当前维小于切分点左移节点,反之右移,直到最后为叶节点。2.将找到的叶节点作为当前最近点。3.重复。a如果“当前最近点”比当前“计算的节点”更远,那么用“当前计算节点”替代“当前最近点”。b.计算父节点对应的超平面是否与最近节点所计算出的超球面相交或者相切,如果相交或者相切,递归想上搜索,否则结束。参考资料《统计学习方法》和http://xiaofeng1982.blog.163.com/blog/static/31572458201210214406792/  http://blog.csdn.net/v_july_v/article/details/8203674  资料中有个形象的gif下面转载过来:


2.sift算法过程总结

(1)构造高斯金字塔,即论文中说的octave。
(2)构造Difference of gaussion,这步主要是模仿log金字塔,但log金字塔的计算量太大,使用dog来近似。
(3)去掉边界点。(未懂);
(4)计算特征点的方向。利用公式

计算出特征点附近每个像素的梯度方向分布hist,以直方图最大值作为特征点的角度。
(5) 局部图像描述子。a区域坐标旋转。b取得128维特征。查找出特征点所在高斯金字塔的图像的坐标,根据缩放的程度计算特征点在原始图像中的坐标位置。
 //将修正后的坐标赋值给特征点feat      //原图中特征点的x坐标,因为第octv组中的图的尺寸比原图小2^octv倍,所以坐标值要乘以2^octv      feat->img_pt.x = feat->x = ( c + xc ) * pow( 2.0, octv );      //原图中特征点的y坐标,因为第octv组中的图的尺寸比原图小2^octv倍,所以坐标值要乘以2^octv      feat->img_pt.y = feat->y = ( r + xr ) * pow( 2.0, octv );  
(代码摘自opensif,注释来自:http://blog.csdn.net/masibuaa/article/details/9207657);;;;;;;
生成后的特征图解:
(摘自:
http://www.cnblogs.com/cql/archive/2013/05/23/3095749.html);;;;;
(6)使用kd树的最近邻算法进行特征匹配。

以下代码摘自:Rachel-Zhang 的博客

#include "highgui.h"#include "cv.h"#include "vector"#include "opencv\cxcore.hpp"#include "iostream"#include "opencv.hpp"//#include "nonfree.hpp"#include<opencv2/nonfree/features2d.hpp>#include<opencv2/nonfree/nonfree.hpp>//#include "showhelper.h"using namespace cv;using namespace std;int main()//(int argc, _TCHAR* argv[]){//Load Image Mat c_src1 =  imread( "hello.jpg");Mat c_src2 = imread("hello2.jpg");Mat src1 = imread( "hello.jpg", CV_LOAD_IMAGE_GRAYSCALE);Mat src2 = imread( "hello2.jpg", CV_LOAD_IMAGE_GRAYSCALE);if( !src1.data || !src2.data ){ std::cout<< " --(!) Error reading images " << std::endl; return -1; }//sift feature detectSiftFeatureDetector detector;std::vector<KeyPoint> kp1, kp2;detector.detect( src1, kp1 );detector.detect( src2, kp2 );SiftDescriptorExtractor extractor;Mat des1,des2;//descriptorextractor.compute(src1,kp1,des1);extractor.compute(src2,kp2,des2);Mat res1,res2; int drawmode = DrawMatchesFlags::DRAW_RICH_KEYPOINTS;drawKeypoints(c_src1,kp1,res1,Scalar::all(-1),drawmode);//在内存中画出特征点drawKeypoints(c_src2,kp2,res2,Scalar::all(-1),drawmode);cout<<"size of description of Img1: "<<kp1.size()<<endl;cout<<"size of description of Img2: "<<kp2.size()<<endl;BFMatcher matcher(NORM_L2);vector<DMatch> matches;matcher.match(des1,des2,matches);Mat img_match;drawMatches(src1,kp1,src2,kp2,matches,img_match);//,Scalar::all(-1),Scalar::all(-1),vector<char>(),drawmode);cout<<"number of matched points: "<<matches.size()<<endl;imshow("matches",img_match);cvWaitKey();cvDestroyAllWindows();cv::SIFT sift ;//sift.return 0;}


0 0
原创粉丝点击