main函数
#include<opencv2/opencv.hpp>
#include"PC_SIFT.h"
using namespace std;
using namespace cv;
int main(int argc,char*argv[])
{
struct feature *feat;
int n;
Mat img1=cv::imread("E://corner.jpg",-1);
if(!img1.data)
{cout<<"Error!No such file!"<<endl;
return -1;
}
cv::namedWindow("test1",CV_WINDOW_AUTOSIZE);
imshow("test1",img1);
n=pc_sift_features(img1, &feat);
cv::waitKey(0);
return 0;
}
CPP文件
#include<opencv2/opencv.hpp>
#include<math.h>
#include "PC_SIFT.h"
using namespace std;
using namespace cv;
Size Wsize(5,5); // the size of gaussain smooth kernel
/*************************Static Function Feclaration**************************/
static int _sift_features( Mat, struct feature**, int ,double , double , int ,int , int );
static Mat create_init_img( Mat, double );
static void build_gauss_pyr( Mat,vector<Mat>&, int,int, double );
static Mat downsample( Mat);
static void build_dog_pyr(vector<Mat>&dog_pyr,vector<Mat>&gauss_pyr, int octvs, int intvls );
/************************Main function pc_sift_features************************/
/*we skipped the first ocatve */
int pc_sift_features(Mat img,struct feature ** feat)
{
return _sift_features( img, feat, SIFT_INTVLS, SIFT_SIGMA, SIFT_CONTR_THR,
SIFT_CURV_THR, SIFT_DESCR_WIDTH,
SIFT_DESCR_HIST_BINS );
}
int _sift_features( Mat img, struct feature** feat, int intvls,
double sigma, double contr_thr, int curv_thr,
int descr_width, int descr_hist_bins )
{
Mat init_img;
vector<Mat> gauss_pyr,dog_pyr;
int n=0;
int octvs;
/*create the init img via original gaussian smooth and converting to type 32 float*/
init_img=create_init_img( img, sigma );
/* build scale space pyramid; */
octvs=(int)log( static_cast<double>MIN( init_img.rows, init_img.cols ) ) / log(2.0) - 2;
build_gauss_pyr( init_img,gauss_pyr, octvs, intvls, sigma );
build_dog_pyr(dog_pyr,gauss_pyr,octvs,intvls);
/*find scale extrama candidate keypoints and discard the bad points */
/*display*/
Mat display;
string winName="1";
char cnt='1';
for(int i=0;i<=12;i++)
{
winName+=cnt;
dog_pyr[i].convertTo(display,CV_8UC1);
imshow(winName,display);
}
/*release the img and pyramid*/
return n;
}
static Mat create_init_img( Mat img, double sigma )
{
Mat gray;
double sig_diff;
img.convertTo(gray,CV_32FC1);
sig_diff = sqrt( sigma * sigma - SIFT_INIT_SIGMA * SIFT_INIT_SIGMA );
cv::GaussianBlur(gray,gray,Wsize,sig_diff);
return gray;
}
static void build_gauss_pyr( Mat base, vector<Mat> &gauss_pyr,int octvs,
int intvls, double sigma )
{
double* sig = (double*)calloc( intvls + 3, sizeof(double));
gauss_pyr.resize(octvs*(intvls+3));
double sig_total, sig_prev, k;
int i, o;
/*
precompute Gaussian sigmas using the following formula:
\sigma_{total}^2 = \sigma_{i}^2 + \sigma_{i-1}^2
*/
sig[0] = sigma;
k = pow( 2.0, 1.0 / intvls );
for( i = 1; i < intvls + 3; i++ )
{
sig_prev = pow( k, i - 1 ) * sigma;
sig_total = sig_prev * k;
sig[i] = sqrt( sig_total * sig_total - sig_prev * sig_prev );
}
/*****build gauss pyramid *************/
for( o = 0; o < octvs; o++ )
for( i = 0; i < intvls + 3; i++ )
{
if( o == 0 && i == 0 )
gauss_pyr[o*(intvls+3)+i]=base.clone();
/* base of new octvave is halved image from end of previous octave */
else if( i == 0 )
gauss_pyr[o*(intvls+3)+i]=downsample(gauss_pyr[(o-1)*(intvls+3)+intvls]);
/* blur the current octave's last image to create the next one */
else
cv::GaussianBlur(gauss_pyr[o*(intvls+3)+i-1],gauss_pyr[o*(intvls+3)+i],Wsize,sig[i]);
}
free( sig );
}
static Mat downsample( Mat img )
{
Mat smaller;
smaller.create(img.rows/2,img.cols/2,CV_32FC1);
cv::resize(img,smaller,cv::Size(img.rows/2,img.cols/2));
return smaller;
}
static void build_dog_pyr(vector<Mat>&dog_pyr,vector<Mat>&gauss_pyr, int octvs, int intvls )
{
dog_pyr.resize(octvs*(intvls+2));
for(int o=0;o<octvs;o++)
for(int i=0;i<intvls+2;i++)
{
Mat& src1=gauss_pyr[o*(intvls+3)+i+1];
Mat& src2=gauss_pyr[o*(intvls+3)+i];
Mat& dst=dog_pyr[o*(intvls+2)+i];
cv::subtract(src1,src2,dst);
}
}
//#ifndef PC_SIFT_H
//#define PC_SIFT_H
#include<opencv2\opencv.hpp>
/** max feature descriptor length */
#define FEATURE_MAX_D 128
/**
Structure to represent an affine invariant image feature.
*/
struct feature
{
double x; /**< x coord */
double y; /**< y coord */
/*********/
int octv; // Octave
int intvl; // inteval
/*********/
double scl; /**< scale of a Lowe-style feature */
double ori; /**< orientation of a Lowe-style feature */
int d; /**< descriptor length */
double descr[FEATURE_MAX_D]; /**< descriptor */
int category; /**< all-purpose feature category */
struct feature* fwd_match; /**< matching feature from forward image */
CvPoint2D64f img_pt; /**< location in image */
CvPoint2D64f mdl_pt; /**< location in model */
void* feature_data; /**< user-definable data */
};
/******************************* Defs and macros *****************************/
/** default number of sampled intervals per octave */
#define SIFT_INTVLS 3
/** default sigma for initial gaussian smoothing */
#define SIFT_SIGMA 1.6
/** default threshold on keypoint contrast |D(x)| */
#define SIFT_CONTR_THR 0.04
/** default threshold on keypoint ratio of principle curvatures */
#define SIFT_CURV_THR 10
/** double image size before pyramid construction? */
#define SIFT_IMG_DBL 0 //no, for sar img ,we abandon the first ovtave
/** default width of descriptor histogram array */
#define SIFT_DESCR_WIDTH 4
/** default number of bins per histogram in descriptor array */
#define SIFT_DESCR_HIST_BINS 8
/* assumed gaussian blur for input image */
#define SIFT_INIT_SIGMA 0.5
/* width of border in which to ignore keypoints */
#define SIFT_IMG_BORDER 5
/*********** Function Proto types ********/
//int pc_sift_features(Mat img,struct feature ** feat);
extern "C" {
extern int pc_sift_features(cv::Mat img,struct feature ** feat);
}
//#endif
gaussian pyramid
DOG Pyramid