SIFT学习笔记之一 下载和调用

来源:互联网 发布:网络电玩数据修改 编辑:程序博客网 时间:2024/06/06 12:52

下面给出了多个参考地址,挑个能用的吧:

vs2010+Rob Hess SIFT: http://blog.csdn.net/lanbing510/article/details/8507341

 Rob Hess主页:http://blogs.oregonstate.edu/hess/

 SIFT的实现有好几个版本,Rob Hess的这个也是基于opencv的。

 下载地址:http://robwhess.github.io/opensift/

(有windows平台下的和linux平台下的... ...)

sift-latest-win.zip: http://download.csdn.net/detail/rxy429/5812261#

sift-1.1.2_20101207_win:https://code.google.com/p/hlibrary/source/browse/#svn%2Fbranches%2Fsift-1.1.2_20101207_win

shioyng:http://blog.csdn.net/chen825919148/article/details/7685952

一 OpenCV内部的SIFT API:

Opencv中调用SIFT进行特征提取和匹配:

复制代码
#include <iostream>#include <opencv2/opencv.hpp>#include <opencv2/nonfree/nonfree.hpp>using namespace std;using namespace cv;int main(){    initModule_nonfree();//if use SIFT or SURF      Ptr<FeatureDetector> detector = FeatureDetector::create("SIFT");    Ptr<DescriptorExtractor> descriptor_extractor = DescriptorExtractor::create("SIFT");    Ptr<DescriptorMatcher> descriptor_matcher = DescriptorMatcher::create("BruteForce");    if (detector.empty() || descriptor_extractor.empty())        throw runtime_error("fail to create detector!");    Mat img1 = imread("d:/src/tc0.bmp");//image in clutter    Mat img2 = imread("d:/src/tc1.bmp");    //detect keypoints;      vector<KeyPoint> keypoints1, keypoints2;    detector->detect(img1, keypoints1);    detector->detect(img2, keypoints2);    cout << "img1:" << keypoints1.size() << " points  img2:" << keypoints2.size()        << " points" << endl << ">" << endl;    //compute descriptors for keypoints;      cout << "< Computing descriptors for keypoints from images..." << endl;    Mat descriptors1, descriptors2;    descriptor_extractor->compute(img1, keypoints1, descriptors1);    descriptor_extractor->compute(img2, keypoints2, descriptors2);    cout << endl << "Descriptors Size: " << descriptors2.size() << " >" << endl;    cout << endl << "Descriptor's Column: " << descriptors2.cols << endl        << "Descriptor's Row: " << descriptors2.rows << endl;    cout << ">" << endl;    //Draw And Match img1,img2 keypoints      Mat img_keypoints1, img_keypoints2;    drawKeypoints(img1, keypoints1, img_keypoints1, Scalar::all(-1), 0);    drawKeypoints(img2, keypoints2, img_keypoints2, Scalar::all(-1), 0);    imshow("Box_in_scene keyPoints", img_keypoints1);    imshow("Box keyPoints", img_keypoints2);    descriptor_extractor->compute(img1, keypoints1, descriptors1);    vector<DMatch> matches;    descriptor_matcher->match(descriptors1, descriptors2, matches);    Mat img_matches;    drawMatches(img1, keypoints1, img2, keypoints2, matches, img_matches, Scalar::all(-1), CV_RGB(255, 255, 255), Mat(), 4);    imshow("Mathc", img_matches);    //waitKey(10000);    waitKey(0);    return 0;}
复制代码

 

二.  Rob Hess 的SIFT代码

(widows平台下,c语言版本)代码本站下载

下载下源码后,配置好opencv环境(包括vs中opencv相关的路径和库配置),本文使用的环境是vs2010+opencv244

导入工程后提示升级,升级完成进行编译,如果出现下面的错误:

在utils.c里加上#include <stdarg.h>即可。

 代码中已经写好了sift的库函数和相关的调用程序,这里先看调用程序是怎样调用sift函数库的:

 1.特征提取程序:

siftFeat工程文件

复制代码
#include "sift.h"#include "imgfeatures.h"#include "utils.h"#include <highgui.h>#include <stdio.h>/******************************** Globals ************************************/char* img_file_name = "..\\beaver.png";char* out_file_name  = "..\\beaver.sift";;char* out_img_name = NULL;int display = 1;int intvls = SIFT_INTVLS;           //每层图像中不同模糊度的图像个数double sigma = SIFT_SIGMA;          //模糊参数double contr_thr = SIFT_CONTR_THR;  //扫描极值点时,对比度阈值int curv_thr = SIFT_CURV_THR;       //去除边界点时的阈值int img_dbl = SIFT_IMG_DBL;         //初始化图片的时候是否先double一下原始图片int descr_width = SIFT_DESCR_WIDTH; //对应于特征点的窗口图像的边长int descr_hist_bins = SIFT_DESCR_HIST_BINS;//对应于梯度方向直方图的下标个数(将360度划分成几个区间)   //最后两个参数就决定了特征点的sift特征的int个数width*width*bins/********************************** Main *************************************/int main( int argc, char** argv ){    IplImage* img;    struct feature* features;    //仅仅需要定义特征指针,在特征提取函数内部会进行内存的malloc    int n = 0;    fprintf( stderr, "Finding SIFT features...\n" );    img = cvLoadImage( img_file_name, 1 );    if( ! img )    {        fprintf( stderr, "unable to load image from %s", img_file_name );        exit( 1 );    }    n = _sift_features( img, &features, intvls, sigma, contr_thr, curv_thr,                        img_dbl, descr_width, descr_hist_bins );    fprintf( stderr, "Found %d features.\n", n );    if( display )    {        draw_features( img, features, n );        cvNamedWindow( img_file_name, 1 );        cvShowImage( img_file_name, img );        cvWaitKey( 0 );    }    if( out_file_name != NULL )        export_features( out_file_name, features, n );    if( out_img_name != NULL )        cvSaveImage( out_img_name, img, NULL );    return 0;}
复制代码

主要为: 加载图像、提取特征、将特征绘制到图像中、显示图像、保存特征到文件中。

其中最关键的就是特征提取函数:

_sift_features( img, &features, intvls, sigma, contr_thr, curv_thr, img_dbl, descr_width, descr_hist_bins );

输入参数:

img为输入图像;

feat为所要提取的特征指针;

intvl指的是高斯金字塔和差分金字塔的层数;

sigma指的是图像初始化过程中高斯模糊所使用的参数;

contr_thr是归一化之后的去除不稳定特征的阈值;

curv_thr指的是去除边缘的特征的主曲率阈值;

img_dbl是是否将图像放大为之前的两倍;

descr_with用来计算特征描述子的方向直方图的宽度;

descr_hist_bins是直方图中的条数

siftFeat.exe运行结果:

将生成的特征保存到文件beaver.sift中:

 

2.match程序:

match工程文件

复制代码
int main( int argc, char** argv ){    IplImage* img1, * img2, * stacked;    struct feature* feat1, * feat2, * feat;    struct feature** nbrs;    struct kd_node* kd_root;    CvPoint pt1, pt2;    double d0, d1;    int n1, n2, k, i, m = 0;    img1 = cvLoadImage( img1_file, 1 );    if( ! img1 )        fatal_error( "unable to load image from %s", img1_file );    img2 = cvLoadImage( img2_file, 1 );    if( ! img2 )        fatal_error( "unable to load image from %s", img2_file );    stacked = stack_imgs( img1, img2 );    fprintf( stderr, "Finding features in %s...\n", img1_file );    n1 = sift_features( img1, &feat1 );    fprintf( stderr, "Finding features in %s...\n", img2_file );    n2 = sift_features( img2, &feat2 );    kd_root = kdtree_build( feat2, n2 );    for( i = 0; i < n1; i++ )    {        feat = feat1 + i;        k = kdtree_bbf_knn( kd_root, feat, 2, &nbrs, KDTREE_BBF_MAX_NN_CHKS );        if( k == 2 )        {            d0 = descr_dist_sq( feat, nbrs[0] );            d1 = descr_dist_sq( feat, nbrs[1] );            if( d0 < d1 * NN_SQ_DIST_RATIO_THR )            {                pt1 = cvPoint( cvRound( feat->x ), cvRound( feat->y ) );                pt2 = cvPoint( cvRound( nbrs[0]->x ), cvRound( nbrs[0]->y ) );                pt2.y += img1->height;                cvLine( stacked, pt1, pt2, CV_RGB(255,0,255), 1, 8, 0 );                m++;                feat1[i].fwd_match = nbrs[0];            }        }        free( nbrs );    }    fprintf( stderr, "Found %d total matches\n", m );    cvNamedWindow( "Matches", 1 );    cvShowImage( "Matches", stacked );    cvWaitKey( 0 );
复制代码

 

主要为:导入两幅图像、堆叠到一幅图像中、使用默认参数分别提取sift特征、对特征进行比较、显示图像

首先导入两幅待匹配的图像,然后通过函数stack_imgs将两幅图像堆叠到一幅图像中使图像1位于图像2的顶部。

其中sift_features函数是对_sift_features函数的简单封装,使用默认的参数:(这些默认的参数都在sift.h头文件中)

 

 

3. dispFeat

dispFeat工程:

复制代码
int main( int argc, char** argv ){    IplImage* img;    struct feature* feat;    char* name;    int n;    img = cvLoadImage( img_file, 1 );    if( ! img )        fatal_error( "unable to load image from %s", img_file );    n = import_features( feat_file, feat_type, &feat );    if( n == -1 )        fatal_error( "unable to import features from %s", feat_file );    name = feat_file;    draw_features( img, feat, n );    cvNamedWindow( name, 1 );    cvShowImage( name, img );    cvWaitKey( 0 );    return 0;}
复制代码

功能很简单就是从特征文件中import入特征,然后通过draw_features函数将特征绘制到图像中显示。

 

 

-------

综上,整个sift库中关键的就是 特征提取  +  相似性比较

 

 

 

 

 

很好的参考网址(这位作者对函数分析的已经很全面了):http://blog.csdn.net/xizero00/article/details/7328060

Trouble is a Friend
0 0
原创粉丝点击