Sift算法的框架

已经整理了sift算法四个步骤对应的基础理论和代码注释:

第一步:Sift:(第一步)建立高斯差分金字塔_zzz_zzzz_的博客-CSDN博客

第二步:Sift:(第二步)关键点位置的确定_zzz_zzzz_的博客-CSDN博客 

第三步:sift:(第三步)为关键点赋予方向_zzz_zzzz_的博客-CSDN博客 

第四步:Sift:(第四步)为关键点构造描述符_zzz_zzzz_的博客-CSDN博客 

还差一个调用这些函数的、包括Sift实现框架的函数

/**
   Finds SIFT features in an image using default parameter values.  All
   detected features are stored in the array pointed to by \a feat.

   @param img the image in which to detect features(初始图像:相当于被相机捕捉到的图像) 
   @param feat a pointer to an array in which to store detected features(储存特征点) 

   @return Returns the number of features stored in \a feat or -1 on failure
   @see _sift_features()
*/
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 );
}



/**
   Finds SIFT features in an image using user-specified parameter values.  All
   detected features are stored in the array pointed to by \a feat.

   @param img the image in which to detect features
   @param fea a pointer to an array in which to store detected features
   @param intvls the number of intervals sampled per octave of scale space
   @param sigma the amount of Gaussian smoothing applied to each image level
     before building the scale space representation for an octave
   @param cont_thr a threshold on the value of the scale space function
     \f$\left|D(\hat{x})\right|\f$, where \f$\hat{x}\f$ is a vector specifying
     feature location and scale, used to reject unstable features;  assumes
     pixel values in the range [0, 1]
   @param curv_thr threshold on a feature's ratio of principle curvatures
     used to reject features that are too edge-like
   @param img_dbl should be 1 if image doubling prior to scale space
     construction is desired or 0 if not
   @param descr_width the width, \f$n\f$, of the \f$n \times n\f$ array of
     orientation histograms used to compute a feature's descriptor
   @param descr_hist_bins the number of orientations in each of the
     histograms in the array used to compute a feature's descriptor

   @return Returns the number of keypoints stored in \a feat or -1 on failure
   @see sift_keypoints()
*/
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;
  int octvs, i, n = 0;
  
  /* check arguments */
  if( ! img )
    fatal_error( "NULL pointer error, %s, line %d",  __FILE__, __LINE__ );
  if( ! feat )
    fatal_error( "NULL pointer error, %s, line %d",  __FILE__, __LINE__ );

  /* build scale space pyramid; smallest dimension of top level is ~4 pixels */
  //构造高斯金字塔最底层的图像
  /*如果img_dbl为1,初始图像先放大再进行sqrt(1.6^2-(2*0.5)^2)的高斯模糊
    如果img_dbl为0,初始图像直接进行sqrt(1.6^2*0.5^2)的高斯模糊
    这里用的时img_dbl为0 */ 
  init_img = create_init_img( img, img_dbl, sigma );
  //第一步:建立高斯差分金字塔 
  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 );
  //第二步:精确极值点定位 
  storage = cvCreateMemStorage( 0 );
  features = scale_space_extrema( dog_pyr, octvs, intvls, contr_thr,
				  curv_thr, storage );
  //计算每个关键点的总尺度、层所在尺度等信息 
  calc_feature_scales( features, sigma, intvls );
  //img_dbl为1时(先扩大了图像的那种情况)
  if( img_dbl )
    adjust_for_img_dbl( features );//消除扩大图像的影响,回归统一 
  //第三步:为关键点分配主方向
  calc_feature_oris( features, gauss_pyr );
  //第四步:构造关键点描述符 
  compute_descriptors( features, gauss_pyr, descr_width, descr_hist_bins );

  /* sort features by decreasing scale and move from CvSeq to array */
  //按照特征点尺度大小进行排序(从大尺度到小尺度) 
  /*调用了自定义的feature_cmp函数,按照sigma排序
    feat1<feat2则返回1,feat1>feat2则返回-1,否则返回0
    只有返回值为1时,cvSeqsort()才会执行一次位置交换 */ 
  cvSeqSort( features, (CvCmpFunc)feature_cmp, NULL );
  n = features->total;//n为特征点总个数 
  *feat = calloc( n, sizeof(struct feature) );//开辟空间 
  *feat = cvCvtSeqToArray( features, *feat, CV_WHOLE_SEQ ); //将序列features中的元素拷贝到数组feat中,返回数组指针给feat
  //释放特征点数组feat中所有特征点的feature_data成员,因为此成员中的数据在检测完特征点后就没用了
  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;//返回特征点个数 
}

以上是进行sift的全部流程,除了在前几篇博客中介绍的函数(初始化图像+划分在一、二、三、四步骤中),还有:

//计算特征点的总尺度和层所在尺度的信息 
/*
  Calculates characteristic scale for each feature in an array.

  @param features array of features
  @param sigma amount of Gaussian smoothing per octave of scale space
  @param intvls intervals per octave of scale space(想从多少张图像中检测极值点) 
*/
static void calc_feature_scales( CvSeq* features, double sigma, int intvls )
{
  struct feature* feat;
  struct detection_data* ddata;
  double intvl;
  int i, n;

  n = features->total;
  for( i = 0; i < n; i++ )
    {
      feat = CV_GET_SEQ_ELEM( struct feature, features, i );
      ddata = feat_detection_data( feat );
      intvl = ddata->intvl + ddata->subintvl;//精确的尺度 
      feat->scl = sigma * pow( 2.0, ddata->octv + intvl / intvls );//sigma0*2^(o+s/S) 
      ddata->scl_octv = sigma * pow( 2.0, intvl / intvls );// sigma0*2^(s/S) 
    }
}
//img_dbl为1的情况下 
/*
  Halves feature coordinates and scale in case the input image was doubled
  prior to scale space construction.

  @param features array of features
*/
static void adjust_for_img_dbl( CvSeq* features )
{
  struct feature* feat;
  int i, n;

  n = features->total;
  for( i = 0; i < n; i++ )
    {
      feat = CV_GET_SEQ_ELEM( struct feature, features, i );
      feat->x /= 2.0;
      feat->y /= 2.0;
      feat->scl /= 2.0;
      feat->img_pt.x /= 2.0;
      feat->img_pt.y /= 2.0;
    }
}
//排序用,根据尺度比较大小返回1,-1或0 
/*
  Compares features for a decreasing-scale ordering.  Intended for use with
  CvSeqSort

  @param feat1 first feature
  @param feat2 second feature
  @param param unused

  @return Returns 1 if feat1's scale is greater than feat2's, -1 if vice versa,
    and 0 if their scales are equal
*/
static int feature_cmp( void* feat1, void* feat2, void* param )
{
  struct feature* f1 = (struct feature*) feat1;
  struct feature* f2 = (struct feature*) feat2;

  if( f1->scl < f2->scl )
    return 1;
  if( f1->scl > f2->scl )
    return -1;
  return 0;
}

 

//释放高斯金字塔空间 
/*
  De-allocates memory held by a scale space pyramid

  @param pyr scale space pyramid
  @param octvs number of octaves of scale space
  @param n number of images per octave
*/
static void release_pyr( IplImage**** pyr, int octvs, int n )
{
  int i, j;
  for( i = 0; i < octvs; i++ )
    {
      for( j = 0; j < n; j++ )
	cvReleaseImage( &(*pyr)[i][j] );
      free( (*pyr)[i] );
    }
  free( *pyr );
  *pyr = NULL;
}

到这里只是完成了Sift基本内容,关于进一步的实现,还要学习其他相关内容!

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值