Ejemplo n.º 1
0
/*
Makes a deep copy of a feature

@param feat feature to be cloned

@return Returns a deep copy of feat
*/
struct feature* clone_feature( struct feature* feat )
{
	struct feature* new_feat;
	struct detection_data* ddata;

	new_feat = new_feature();
	ddata = feat_detection_data( new_feat );
	memcpy( new_feat, feat, sizeof( struct feature ) );
	memcpy( ddata, feat_detection_data(feat), sizeof( struct detection_data ) );
	new_feat->feature_data = ddata;

	return new_feat;
}
Ejemplo n.º 2
0
/*
Computes a canonical orientation for each image feature in an array.  Based
on Section 5 of Lowe's paper.  This function adds features to the array when
there is more than one dominant orientation at a given feature location.

@param features an array of image features
@param gauss_pyr Gaussian scale space pyramid
*/
void calc_feature_oris( CvSeq* features, IplImage*** gauss_pyr )
{
	struct feature* feat;
	struct detection_data* ddata;
	double* hist;
	double omax;
	int i, j, n = features->total;

	for( i = 0; i < n; i++ )
	{
		feat = (feature* )malloc( sizeof( struct feature ) );
		cvSeqPopFront( features, feat );
		ddata = feat_detection_data( feat );
		hist = ori_hist( gauss_pyr[ddata->octv][ddata->intvl],
						ddata->r, ddata->c, SIFT_ORI_HIST_BINS,
						cvRound( SIFT_ORI_RADIUS * ddata->scl_octv ),
						SIFT_ORI_SIG_FCTR * ddata->scl_octv );
		for( j = 0; j < SIFT_ORI_SMOOTH_PASSES; j++ )
			smooth_ori_hist( hist, SIFT_ORI_HIST_BINS );
		omax = dominant_ori( hist, SIFT_ORI_HIST_BINS );
		add_good_ori_features( features, hist, SIFT_ORI_HIST_BINS,
								omax * SIFT_ORI_PEAK_RATIO, feat );
		free( ddata );
		free( feat );
		free( hist );
	}
}
Ejemplo n.º 3
0
/*
Computes a canonical orientation for each image feature in an array.  Based
on Section 5 of Lowe's paper.  This function adds features to the array when
there is more than one dominant orientation at a given feature location.

@param features an array of image features
@param gauss_pyr Gaussian scale space pyramid
*/
static void calc_feature_oris( CvSeq* features, IplImage*** gauss_pyr )
{
	struct feature* feat;
	struct detection_data* ddata;
	double* hist;
	double omax;
	int i, j, n = features->total;

	for( i = 0; i < n; i++ )
	{
		feat = malloc( sizeof( struct feature ) );
		cvSeqPopFront( features, feat );
		ddata = feat_detection_data( feat );
		/*Each sample added to the hstogram is weighted by its gradient magnitude and by a gausian-weighted circular 
		window with a sigma that is 1.5 times that of the scale of the keypoint*/
		hist = ori_hist( gauss_pyr[ddata->octv][ddata->intvl],
						ddata->r, ddata->c, SIFT_ORI_HIST_BINS,
						cvRound( SIFT_ORI_RADIUS * ddata->scl_octv ),//主方向分配时使用的区域半径
						SIFT_ORI_SIG_FCTR * ddata->scl_octv );//特征点主方向分配时高斯平滑σ为1.5倍特征点所在的尺度
		for( j = 0; j < SIFT_ORI_SMOOTH_PASSES; j++ )
			smooth_ori_hist( hist, SIFT_ORI_HIST_BINS );//使用高斯函数对直方图进行平滑,减少突变的影响
		omax = dominant_ori( hist, SIFT_ORI_HIST_BINS );//在直方图中找到主方向的梯度
		add_good_ori_features( features, hist, SIFT_ORI_HIST_BINS,//将大于某一个梯度大小阈值的特征向量加入到直方图中去
								omax * SIFT_ORI_PEAK_RATIO, feat );
		free( ddata );
		free( feat );
		free( hist );
	}
}
Ejemplo n.º 4
0
/*
Makes a deep copy of a feature
@param feat feature to be cloned
@return Returns a deep copy of feat
*/
static struct feature* clone_feature( struct feature* feat )
{
	struct feature* new_feat;
	struct detection_data* ddata;

    //为一个feature结构分配空间并初始化
    new_feat = new_feature();
    //调用宏feat_detection_data来提取参数feat中的feature_data成员并转换为detection_data类型的指针
	ddata = feat_detection_data( new_feat );
    //对内存空间进行赋值
	memcpy( new_feat, feat, sizeof( struct feature ) );
	memcpy( ddata, feat_detection_data(feat), sizeof( struct detection_data ) );
	new_feat->feature_data = ddata;

    return new_feat;//返回克隆生成的特征点的指针
}
Ejemplo n.º 5
0
/*
Detects features at extrema in DoG scale space.  Bad features are discarded
based on contrast and ratio of principal curvatures.

@param dog_pyr DoG scale space pyramid
@param octvs octaves of scale space represented by dog_pyr
@param intvls intervals per octave
@param contr_thr low threshold on feature contrast
@param curv_thr high threshold on feature ratio of principal curvatures
@param storage memory storage in which to store detected features

@return Returns an array of detected features whose scales, orientations,
	and descriptors are yet to be determined.
*/
CvSeq* scale_space_extrema( IplImage*** dog_pyr, int octvs, int intvls,
			   double contr_thr, int curv_thr, CvMemStorage* storage ) {
	CvSeq* features;
	double prelim_contr_thr = 0.5 * contr_thr / intvls;
	struct feature* feat;
	struct detection_data* ddata;
	int o, i, r, c;

	features = cvCreateSeq( 0, sizeof(CvSeq), sizeof(struct feature), storage );
	for( o = 0; o < octvs; o++ )
		for( i = 1; i <= intvls; i++ )
			for(r = SIFT_IMG_BORDER; r < dog_pyr[o][0]->height-SIFT_IMG_BORDER; r++)
				for(c = SIFT_IMG_BORDER; c < dog_pyr[o][0]->width-SIFT_IMG_BORDER; c++)
					/* perform preliminary check on contrast */
					if( ABS( pixval32f( dog_pyr[o][i], r, c ) ) > prelim_contr_thr )
						if( is_extremum( dog_pyr, o, i, r, c ) ) {
							feat = interp_extremum(dog_pyr, o, i, r, c, intvls, contr_thr);
							if( feat ) {
								ddata = feat_detection_data( feat );
								if( ! is_too_edge_like( dog_pyr[ddata->octv][ddata->intvl],
									ddata->r, ddata->c, curv_thr ) ) {
									cvSeqPush( features, feat );
								}
								else
									free( ddata );
								free( feat );
							}
						}

	return features;
}
Ejemplo n.º 6
0
Archivo: sift.c Proyecto: vabc3/KarCv
/*
   Interpolates a scale-space extremum's location and scale to subpixel
   accuracy to form an image feature.  Rejects features with low contrast.
   Based on Section 4 of Lowe's paper.  

   @param dog_pyr DoG scale space pyramid
   @param octv feature's octave of scale space
   @param intvl feature's within-octave interval
   @param r feature's image row
   @param c feature's image column
   @param intvls total intervals per octave
   @param contr_thr threshold on feature contrast

   @return Returns the feature resulting from interpolation of the given
   parameters or NULL if the given location could not be interpolated or
   if contrast at the interpolated loation was too low.  If a feature is
   returned, its scale, orientation, and descriptor are yet to be determined.
   */
static struct feature* interp_extremum( IplImage*** dog_pyr, int octv,
		int intvl, int r, int c, int intvls,
		double contr_thr )
{
	struct feature* feat;
	struct detection_data* ddata;
	double xi, xr, xc, contr;
	int i = 0;

	while( i < SIFT_MAX_INTERP_STEPS )
	{
		interp_step( dog_pyr, octv, intvl, r, c, &xi, &xr, &xc );
		if( ABS( xi ) < 0.5  &&  ABS( xr ) < 0.5  &&  ABS( xc ) < 0.5 )
			break;

		c += cvRound( xc );
		r += cvRound( xr );
		intvl += cvRound( xi );

		if( intvl < 1  ||
				intvl > intvls  ||
				c < SIFT_IMG_BORDER  ||
				r < SIFT_IMG_BORDER  ||
				c >= dog_pyr[octv][0]->width - SIFT_IMG_BORDER  ||
				r >= dog_pyr[octv][0]->height - SIFT_IMG_BORDER )
		{
			return NULL;
		}

		i++;
	}

	/* ensure convergence of interpolation */
	if( i >= SIFT_MAX_INTERP_STEPS )
		return NULL;

	contr = interp_contr( dog_pyr, octv, intvl, r, c, xi, xr, xc );
	if( ABS( contr ) < contr_thr / intvls )
		return NULL;

	feat = new_feature();
	ddata = feat_detection_data( feat );
	feat->img_pt.x = feat->x = ( c + xc ) * pow( 2.0, octv );
	feat->img_pt.y = feat->y = ( r + xr ) * pow( 2.0, octv );
	ddata->r = r;
	ddata->c = c;
	ddata->octv = octv;
	ddata->intvl = intvl;
	ddata->subintvl = xi;

	return feat;
}
Ejemplo n.º 7
0
/*
Computes feature descriptors for features in an array.  Based on Section 6
of Lowe's paper.

@param features array of features
@param gauss_pyr Gaussian scale space pyramid
@param d width of 2D array of orientation histograms
@param n number of bins per orientation histogram
*/
void compute_descriptors( CvSeq* features, IplImage*** gauss_pyr, int d, int n)
{
	struct feature* feat;
	struct detection_data* ddata;
	double*** hist;
	int i, k = features->total;

	for( i = 0; i < k; i++ )
	{
		feat = CV_GET_SEQ_ELEM( struct feature, features, i );
		ddata = feat_detection_data( feat );
		hist = descr_hist( gauss_pyr[ddata->octv][ddata->intvl], ddata->r,
			ddata->c, feat->ori, ddata->scl_octv, d, n );
		hist_to_descr( hist, d, n, feat );
		release_descr_hist( &hist, d );
	}
}
Ejemplo n.º 8
0
/*
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
*/
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 );
		ddata->scl_octv = sigma * pow( 2.0, intvl / intvls );
	}
}
Ejemplo n.º 9
0
/*
Detects features at extrema in DoG scale space.  Bad features are discarded
based on contrast and ratio of principal curvatures.
@param dog_pyr DoG scale space pyramid
@param octvs octaves of scale space represented by dog_pyr
@param intvls intervals per octave
@param contr_thr low threshold on feature contrast
@param curv_thr high threshold on feature ratio of principal curvatures
@param storage memory storage in which to store detected features
@return Returns an array of detected features whose scales, orientations,
	and descriptors are yet to be determined.
*/
static CvSeq* scale_space_extrema( IplImage*** dog_pyr, int octvs, int intvls,
								   double contr_thr, int curv_thr, CvMemStorage* storage )
{
    CvSeq* features;//特征点序列
    double prelim_contr_thr = 0.5 * contr_thr / intvls;//像素的对比度阈值
	struct feature* feat;
	struct detection_data* ddata;
	int o, i, r, c;

    //在存储器storage上创建存储极值点的序列,其中存储feature结构类型的数据
	features = cvCreateSeq( 0, sizeof(CvSeq), sizeof(struct feature), storage );

    /*遍历高斯差分金字塔,检测极值点*/
    //SIFT_IMG_BORDER指明边界宽度,只检测边界线以内的极值点
    for( o = 0; o < octvs; o++ )//第o组
        for( i = 1; i <= intvls; i++ )//遍i层
            for(r = SIFT_IMG_BORDER; r < dog_pyr[o][0]->height-SIFT_IMG_BORDER; r++)//第r行
                for(c = SIFT_IMG_BORDER; c < dog_pyr[o][0]->width-SIFT_IMG_BORDER; c++)//第c列
                    //进行初步的对比度检查,只有当归一化后的像素值大于对比度阈值prelim_contr_thr时才继续检测此像素点是否可能是极值
                    //调用函数pixval32f获取图像dog_pyr[o][i]的第r行第c列的点的坐标值,然后调用ABS宏求其绝对值
					if( ABS( pixval32f( dog_pyr[o][i], r, c ) ) > prelim_contr_thr )
                        //通过在尺度空间中将一个像素点的值与其周围3*3*3邻域内的点比较来决定此点是否极值点(极大值或极小都行)
                        if( is_extremum( dog_pyr, o, i, r, c ) )//若是极值点
						{
                            //由于极值点的检测是在离散空间中进行的,所以检测到的极值点并不一定是真正意义上的极值点
                            //因为真正的极值点可能位于两个像素之间,而在离散空间中只能精确到坐标点精度上
                            //通过亚像素级插值进行极值点精确定位(修正极值点坐标),并去除低对比度的极值点,将修正后的特征点组成feature结构返回
							feat = interp_extremum(dog_pyr, o, i, r, c, intvls, contr_thr);
                            //返回值非空,表明此点已被成功修正
                            if( feat )
							{
                                //调用宏feat_detection_data来提取参数feat中的feature_data成员并转换为detection_data类型的指针
								ddata = feat_detection_data( feat );
                                //去除边缘响应,即通过计算主曲率比值判断某点是否边缘点,返回值为0表示不是边缘点,可做特征点
                                if( ! is_too_edge_like( dog_pyr[ddata->octv][ddata->intvl], ddata->r, ddata->c, curv_thr ) )
								{
                                    cvSeqPush( features, feat );//向特征点序列features末尾插入新检测到的特征点feat
								}
								else
									free( ddata );
								free( feat );
							}
						}

    return features;//返回特征点序列
}
Ejemplo n.º 10
0
/*
Computes a canonical orientation for each image feature in an array.  Based
on Section 5 of Lowe's paper.  This function adds features to the array when
there is more than one dominant orientation at a given feature location.
@param features an array of image features
@param gauss_pyr Gaussian scale space pyramid
*/
static void calc_feature_oris( CvSeq* features, IplImage*** gauss_pyr )
{
	struct feature* feat;
	struct detection_data* ddata;
    double* hist;//存放梯度直方图的数组
	double omax;
    int i, j, n = features->total;//特征点个数

    //遍历特征点序列
	for( i = 0; i < n; i++ )
	{
        //给每个特征点分配feature结构大小的内存
		feat = malloc( sizeof( struct feature ) );
        //移除列首元素,放到feat中
		cvSeqPopFront( features, feat );
        //调用宏feat_detection_data来提取参数feat中的feature_data成员并转换为detection_data类型的指针
        //detection_data数据中存放有此特征点的行列坐标和尺度,以及所在的层和组
		ddata = feat_detection_data( feat );

        //计算指定像素点的梯度方向直方图,返回存放直方图的数组给hist
        hist = ori_hist( gauss_pyr[ddata->octv][ddata->intvl],       //特征点所在的图像
                        ddata->r, ddata->c,                          //特征点的行列坐标
                        SIFT_ORI_HIST_BINS,                          //默认的梯度直方图的bin(柱子)个数
                        cvRound( SIFT_ORI_RADIUS * ddata->scl_octv ),//特征点方向赋值过程中,搜索邻域的半径为:3 * 1.5 * σ
                        SIFT_ORI_SIG_FCTR * ddata->scl_octv );       //计算直翻图时梯度幅值的高斯权重的初始值

        //对梯度直方图进行高斯平滑,弥补因没有仿射不变性而产生的特征点不稳定的问题,SIFT_ORI_SMOOTH_PASSES指定了平滑次数
		for( j = 0; j < SIFT_ORI_SMOOTH_PASSES; j++ )
			smooth_ori_hist( hist, SIFT_ORI_HIST_BINS );

        //查找梯度直方图中主方向的梯度幅值,即查找直方图中最大bin的值,返回给omax
		omax = dominant_ori( hist, SIFT_ORI_HIST_BINS );
        /*若当前特征点的直方图中某个bin的值大于给定的阈值,则新生成一个特征点并添加到特征点序列末尾
          传入的特征点指针feat是已经从特征点序列features中移除的,所以即使此特征点没有辅方向(第二个大于幅值阈值的方向)
          在函数add_good_ori_features中也会执行一次克隆feat,对其方向进行插值修正,并插入特征点序列的操作
          幅值阈值一般设置为当前特征点的梯度直方图的最大bin值的80%                   */
		add_good_ori_features( features, hist, SIFT_ORI_HIST_BINS,
								omax * SIFT_ORI_PEAK_RATIO, feat );
        //释放内存
		free( ddata );
		free( feat );
		free( hist );
	}
}
Ejemplo n.º 11
0
/*
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;
		//计算参考博客   http://underthehood.blog.51cto.com/2531780/658350  2.5
        //http://www.cnblogs.com/cfantaisie/archive/2011/06/14/2080917.html
		feat->scl = sigma * pow( 2.0, ddata->octv + intvl / intvls );
		ddata->scl_octv = sigma * pow( 2.0, intvl / intvls );
	}
}
Ejemplo n.º 12
0
/*
Computes feature descriptors for features in an array.  Based on Section 6 of Lowe's paper.
@param features array of features
@param gauss_pyr Gaussian scale space pyramid
@param d width of 2D array of orientation histograms
@param n number of bins per orientation histogram
*/
static void compute_descriptors( CvSeq* features, IplImage*** gauss_pyr, int d, int n)
{
	struct feature* feat;
	struct detection_data* ddata;
    double*** hist;//d*d*n的三维直方图数组
    int i, k = features->total;//特征点的个数

    //遍历特征点序列中的特征点
	for( i = 0; i < k; i++ )
	{
        //调用宏,获取序列features中的第i个元素,并强制转换为struct feature类型
		feat = CV_GET_SEQ_ELEM( struct feature, features, i );
        //调用宏feat_detection_data来提取参数feat中的feature_data成员并转换为detection_data类型的指针
		ddata = feat_detection_data( feat );
        //计算特征点附近区域的方向直方图,此直方图在计算特征描述子中要用到,返回值是一个d*d*n的三维数组
		hist = descr_hist( gauss_pyr[ddata->octv][ddata->intvl], ddata->r,
			ddata->c, feat->ori, ddata->scl_octv, d, n );
        //将某特征点的方向直方图转换为特征描述子向量,对特征描述子归一化并将所有元素转化为整型,存入特征点feat中
		hist_to_descr( hist, d, n, feat );
        //释放特征点的方向直方图
		release_descr_hist( &hist, d );
	}
}
Ejemplo n.º 13
0
/*
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++ )
	{
        //调用宏,获取序列features中的第i个元素,并强制转换为struct feature类型
        feat = CV_GET_SEQ_ELEM( struct feature, features, i );
        //调用宏feat_detection_data来提取参数feat中的feature_data成员并转换为detection_data类型的指针
		ddata = feat_detection_data( feat );
        //特征点所在的层数ddata->intvl加上特征点在层方向上的亚像素偏移量,得到特征点的较为精确的层数
        intvl = ddata->intvl + ddata->subintvl;
        //计算特征点的尺度(公式见SIFT算法说明),并赋值给scl成员
		feat->scl = sigma * pow( 2.0, ddata->octv + intvl / intvls );
        //计算特征点所在的组的尺度,给detection_data的scl_octv成员赋值
		ddata->scl_octv = sigma * pow( 2.0, intvl / intvls );
	}
}
Ejemplo n.º 14
0
/*
Interpolates a scale-space extremum's location and scale to subpixel
accuracy to form an image feature.  Rejects features with low contrast.
Based on Section 4 of Lowe's paper.  
@param dog_pyr DoG scale space pyramid
@param octv feature's octave of scale space
@param intvl feature's within-octave interval
@param r feature's image row
@param c feature's image column
@param intvls total intervals per octave
@param contr_thr threshold on feature contrast
@return Returns the feature resulting from interpolation of the given
	parameters or NULL if the given location could not be interpolated or
	if contrast at the interpolated loation was too low.  If a feature is
	returned, its scale, orientation, and descriptor are yet to be determined.
*/
static struct feature* interp_extremum( IplImage*** dog_pyr, int octv, int intvl,
										int r, int c, int intvls, double contr_thr )
{
    struct feature* feat;//修正后的特征点
    struct detection_data* ddata;//与特征检测有关的结构,存在feature结构的feature_data成员中
    double xi, xr, xc, contr;//xi,xr,xc分别为亚像素的intvl(层),row(y),col(x)方向上的增量(偏移量)
    int i = 0;//插值次数

    //SIFT_MAX_INTERP_STEPS指定了关键点的最大插值次数,即最多修正多少次,默认是5
	while( i < SIFT_MAX_INTERP_STEPS )
	{
        //进行一次极值点差值,计算σ(层方向,intvl方向),y,x方向上的子像素偏移量(增量)
		interp_step( dog_pyr, octv, intvl, r, c, &xi, &xr, &xc );
        //若在任意方向上的偏移量大于0.5时,意味着差值中心已经偏移到它的临近点上,所以必须改变当前关键点的位置坐标
        if( ABS( xi ) < 0.5  &&  ABS( xr ) < 0.5  &&  ABS( xc ) < 0.5 )//若三方向上偏移量都小于0.5,表示已经够精确,则不用继续插值
			break;

        //修正关键点的坐标,x,y,σ三方向上的原坐标加上偏移量取整(四舍五入)
        c += cvRound( xc );//x坐标修正
        r += cvRound( xr );//y坐标修正
        intvl += cvRound( xi );//σ方向,即层方向

        //若坐标修正后超出范围,则结束插值,返回NULL
        if( intvl < 1  ||           //层坐标插之后越界
			intvl > intvls  ||
            c < SIFT_IMG_BORDER  ||   //行列坐标插之后到边界线内
			r < SIFT_IMG_BORDER  ||
			c >= dog_pyr[octv][0]->width - SIFT_IMG_BORDER  ||
			r >= dog_pyr[octv][0]->height - SIFT_IMG_BORDER )
		{
			return NULL;
		}

		i++;
	}

    //若经过SIFT_MAX_INTERP_STEPS次插值后还没有修正到理想的精确位置,则返回NULL,即舍弃此极值点
	if( i >= SIFT_MAX_INTERP_STEPS )
		return NULL;

    //计算被插值点的对比度:D + 0.5 * dD^T * X
	contr = interp_contr( dog_pyr, octv, intvl, r, c, xi, xr, xc );
    if( ABS( contr ) < contr_thr / intvls )//若该点对比度过小,舍弃,返回NULL
		return NULL;

    //为一个特征点feature结构分配空间并初始化,返回特征点指针
	feat = new_feature();
    //调用宏feat_detection_data来提取参数feat中的feature_data成员并转换为detection_data类型的指针
	ddata = feat_detection_data( feat );

    //将修正后的坐标赋值给特征点feat
    //原图中特征点的x坐标,因为第octv组中的图的尺寸比原图小2^octv倍,所以坐标值要乘以2^octv
    feat->img_pt.x = feat->x = ( c + xc ) * pow( 2.0, octv );
    //原图中特征点的y坐标,因为第octv组中的图的尺寸比原图小2^octv倍,所以坐标值要乘以2^octv
	feat->img_pt.y = feat->y = ( r + xr ) * pow( 2.0, octv );

    ddata->r = r;//特征点所在的行
    ddata->c = c;//特征点所在的列
    ddata->octv = octv;//高斯差分金字塔中,特征点所在的组
    ddata->intvl = intvl;//高斯差分金字塔中,特征点所在的组中的层
    ddata->subintvl = xi;//特征点在层方向(σ方向,intvl方向)上的亚像素偏移量

    return feat;//返回特征点指针
}