/* 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 ); } }
/* 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 ); } }
/* * call-seq: * shift -> obj or nil * * Returns the first element of <i>self</i> and removes it (shifting all other elements down by one). Returns <tt>nil</tt> if the array is empty. */ VALUE rb_shift(VALUE self) { CvSeq *seq = CVSEQ(self); if(!(seq->total > 0)){ return Qnil; } VALUE object = GENERIC_OBJECT(seqblock_class(seq), malloc(seq->elem_size)); cvSeqPopFront(seq, DATA_PTR(object)); return object; }
/* 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 ); } }