最近也一直在研究SIFT(尺度不变特征匹配算法),先理解算法的数学原理,然后再一步步分析Rob Hess的程序代码:
//初始值为3
#define SIFT_INTVLS 3
//初始值是1.6
#define SIFT_SIGMA 1.6
// 值越大,被剔除的特征点就越多
#define SIFT_CONTR_THR 0.04
//初始值是0.04
//主曲率阈值r=10,大于10即去掉边缘响应点
#define SIFT_CURV_THR 10
//初始值是10
//在建立尺度空间之前如果原图像放大一倍则取值为1,否则为0
#define SIFT_IMG_DBL 1
//descr_width:计算特征描述符时邻域子块的宽度,
#define SIFT_DESCR_WIDTH 4
//初始值为4
//计算特征描述符时将特征点邻域进行投影的方向数,默认为8,分别是0,45,90,135 180,225,270,315共8个方向。
#define SIFT_DESCR_HIST_BINS 8
#define SIFT_INIT_SIGMA 0.5
//初始值是0.5
//忽略特征点的边界宽度
#define SIFT_IMG_BORDER 5
#define SIFT_MAX_INTERP_STEPS 5
#define SIFT_ORI_HIST_BINS 36
//特征点主方向分配时高斯平滑σ为1.5倍特征点所在的尺度
#define SIFT_ORI_SIG_FCTR 1.5
//主方向分配时使用的区域半径
#define SIFT_ORI_RADIUS 3.0 * SIFT_ORI_SIG_FCTR
#define SIFT_ORI_SMOOTH_PASSES 2
//初始值0.8 阈值
#define SIFT_ORI_PEAK_RATIO 0.8
//初始值3.0
#define SIFT_DESCR_SCL_FCTR 3.0
//初始值是0.2 128维SIFT描述子中大于0.2的维度量截取为0.2
#define SIFT_DESCR_MAG_THR 0.2
//浮点数转换为无符号字符的因子值
#define SIFT_INT_DESCR_FCTR 512.0
#define feat_detection_data(f) ( (struct detection_data*)(f->feature_data) )
特征点检测函数分析
int sift_features( IplImage* img, struct feature** feat )
{
return _sift_features( img, feat, SIFT_INTVLS, SIFT_SIGMA, SIFT_CONTR_THR,
SIFT_CURV_THR, SIFT_IMG_DBL, SIFT_DESCR_WIDTH,
SIFT_DESCR_HIST_BINS );
}
int _sift_features( IplImage* img, struct feature** feat, int intvls,
double sigma, double contr_thr, int curv_thr,
int img_dbl, int descr_width, int descr_hist_bins )
{
IplImage* init_img;
IplImage*** gauss_pyr, *** dog_pyr;
CvMemStorage* storage;
CvSeq* features; //CvSeq定义非固定元素的序列
int octvs, i, n = 0;
if( ! img )
fatal_error( "NULL pointer error, %s, line %d", __FILE__, __LINE__ );
if( ! feat )
fatal_error( "NULL pointer error, %s, line %d", __FILE__, __LINE__ );
init_img = create_init_img( img, img_dbl, sigma ); //将图像转为8位灰度图像,然后再高斯平滑
octvs = log( MIN( init_img->width, init_img->height ) ) / log(2) - 2;
gauss_pyr = build_gauss_pyr( init_img, octvs, intvls, sigma ); //构建高斯尺度空间
dog_pyr = build_dog_pyr( gauss_pyr, octvs, intvls ); //构建DOG尺度空间
storage = cvCreateMemStorage( 0 );
features = scale_space_extrema( dog_pyr, octvs, intvls, contr_thr,
curv_thr, storage ); //返回特征点尺度,位置
calc_feature_scales( features, sigma, intvls ); //在每一组中计算尺度值
if( img_dbl ) //如果图像放大了一倍
adjust_for_img_dbl( features ); //在构造尺度空间之前将图像的坐标及尺度扩大一倍
calc_feature_oris( features, gauss_pyr ); //计算关键点主方向
compute_descriptors( features, gauss_pyr, descr_width, descr_hist_bins );//
cvSeqSort( features, (CvCmpFunc)feature_cmp, NULL );
n = features->total;
*feat = calloc( n, sizeof(struct feature) );
*feat = cvCvtSeqToArray( features, *feat, CV_WHOLE_SEQ );//复制序列中的元素到一个连续的内存块中
for( i = 0; i < n; i++ )
{
free( (*feat)[i].feature_data );
(*feat)[i].feature_data = NULL;
}
cvReleaseMemStorage( &storage );
cvReleaseImage( &init_img );
release_pyr( &gauss_pyr, octvs, intvls + 3 );
release_pyr( &dog_pyr, octvs, intvls + 2 );
return n;
}