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

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

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

posted @ 2015-03-06 09:14  sunnycs  阅读(1308)  评论(0编辑  收藏  举报