您的位置:首页 > 其它

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

2015-12-13 14:42 288 查看
下面给出了多个参考地址,挑个能用的吧:
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
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: