📄 sift.c
字号:
Calculates the gradient magnitude and orientation at a given pixel.@param img image@param r pixel row@param c pixel col@param mag output as gradient magnitude at pixel (r,c)@param ori output as gradient orientation at pixel (r,c)@return Returns 1 if the specified pixel is a valid one and sets mag and ori accordingly; otherwise returns 0*/int calc_grad_mag_ori( IplImage* img, int r, int c, double* mag, double* ori ){ double dx, dy; if( r > 0 && r < img->height - 1 && c > 0 && c < img->width - 1 ) { dx = pixval32f( img, r, c+1 ) - pixval32f( img, r, c-1 ); dy = pixval32f( img, r-1, c ) - pixval32f( img, r+1, c ); *mag = sqrt( dx*dx + dy*dy ); *ori = atan2( dy, dx ); return 1; } else return 0;}/*Gaussian smooths an orientation histogram.@param hist an orientation histogram@param n number of bins*/void smooth_ori_hist( double* hist, int n ){ double prev, tmp, h0 = hist[0]; int i; prev = hist[n-1]; for( i = 0; i < n; i++ ) { tmp = hist[i]; hist[i] = 0.25 * prev + 0.5 * hist[i] + 0.25 * ( ( i+1 == n )? h0 : hist[i+1] ); prev = tmp; }}/*Finds the magnitude of the dominant orientation in a histogram@param hist an orientation histogram@param n number of bins@return Returns the value of the largest bin in hist*/double dominant_ori( double* hist, int n ){ double omax; int maxbin, i; omax = hist[0]; maxbin = 0; for( i = 1; i < n; i++ ) if( hist[i] > omax ) { omax = hist[i]; maxbin = i; } return omax;}/*Interpolates a histogram peak from left, center, and right values*/#define interp_hist_peak( l, c, r ) ( 0.5 * ((l)-(r)) / ((l) - 2.0*(c) + (r)) )/*Adds features to an array for every orientation in a histogram greater thana specified threshold.@param features new features are added to the end of this array@param hist orientation histogram@param n number of bins in hist@param mag_thr new features are added for entries in hist greater than this@param feat new features are clones of this with different orientations*/void add_good_ori_features( CvSeq* features, double* hist, int n, double mag_thr, struct feature* feat ){ struct feature* new_feat; double bin, PI2 = CV_PI * 2.0; int l, r, i; for( i = 0; i < n; i++ ) { l = ( i == 0 )? n - 1 : i-1; r = ( i + 1 ) % n; if( hist[i] > hist[l] && hist[i] > hist[r] && hist[i] >= mag_thr ) { bin = i + interp_hist_peak( hist[l], hist[i], hist[r] ); bin = ( bin < 0 )? n + bin : ( bin >= n )? bin - n : bin; new_feat = clone_feature( feat ); new_feat->ori = ( ( PI2 * bin ) / n ) - CV_PI; cvSeqPush( features, new_feat ); free( new_feat ); } }}/*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;}/*Computes feature descriptors for features in an array. Based on Section 6of 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 ); }}/*Computes the 2D array of orientation histograms that form the featuredescriptor. Based on Section 6.1 of Lowe's paper.@param img image used in descriptor computation@param r row coord of center of orientation histogram array@param c column coord of center of orientation histogram array@param ori canonical orientation of feature whose descr is being computed@param scl scale relative to img of feature whose descr is being computed@param d width of 2d array of orientation histograms@param n bins per orientation histogram@return Returns a d x d array of n-bin orientation histograms.*/double*** descr_hist( IplImage* img, int r, int c, double ori, double scl, int d, int n ){ double*** hist; double cos_t, sin_t, hist_width, exp_denom, r_rot, c_rot, grad_mag, grad_ori, w, rbin, cbin, obin, bins_per_rad, PI2 = 2.0 * CV_PI; int radius, i, j; hist = calloc( d, sizeof( double** ) ); for( i = 0; i < d; i++ ) { hist[i] = calloc( d, sizeof( double* ) ); for( j = 0; j < d; j++ ) hist[i][j] = calloc( n, sizeof( double ) ); } cos_t = cos( ori ); sin_t = sin( ori ); bins_per_rad = n / PI2; exp_denom = d * d * 0.5; hist_width = SIFT_DESCR_SCL_FCTR * scl; radius = hist_width * sqrt(2) * ( d + 1.0 ) * 0.5 + 0.5; for( i = -radius; i <= radius; i++ ) for( j = -radius; j <= radius; j++ ) { /* Calculate sample's histogram array coords rotated relative to ori. Subtract 0.5 so samples that fall e.g. in the center of row 1 (i.e. r_rot = 1.5) have full weight placed in row 1 after interpolation. */ c_rot = ( j * cos_t - i * sin_t ) / hist_width; r_rot = ( j * sin_t + i * cos_t ) / hist_width; rbin = r_rot + d / 2 - 0.5; cbin = c_rot + d / 2 - 0.5; if( rbin > -1.0 && rbin < d && cbin > -1.0 && cbin < d ) if( calc_grad_mag_ori( img, r + i, c + j, &grad_mag, &grad_ori )) { grad_ori -= ori; while( grad_ori < 0.0 ) grad_ori += PI2; while( grad_ori >= PI2 ) grad_ori -= PI2; obin = grad_ori * bins_per_rad; w = exp( -(c_rot * c_rot + r_rot * r_rot) / exp_denom ); interp_hist_entry( hist, rbin, cbin, obin, grad_mag * w, d, n ); } } return hist;}/*Interpolates an entry into the array of orientation histograms that formthe feature descriptor.@param hist 2D array of orientation histograms@param rbin sub-bin row coordinate of entry@param cbin sub-bin column coordinate of entry@param obin sub-bin orientation coordinate of entry@param mag size of entry@param d width of 2D array of orientation histograms@param n number of bins per orientation histogram*/void interp_hist_entry( double*** hist, double rbin, double cbin, double obin, double mag, int d, int n ){ double d_r, d_c, d_o, v_r, v_c, v_o; double** row, * h; int r0, c0, o0, rb, cb, ob, r, c, o; r0 = cvFloor( rbin ); c0 = cvFloor( cbin ); o0 = cvFloor( obin ); d_r = rbin - r0; d_c = cbin - c0; d_o = obin - o0; /* The entry is distributed into up to 8 bins. Each entry into a bin is multiplied by a weight of 1 - d for each dimension, where d is the distance from the center value of the bin measured in bin units. */ for( r = 0; r <= 1; r++ ) { rb = r0 + r; if( rb >= 0 && rb < d ) { v_r = mag * ( ( r == 0 )? 1.0 - d_r : d_r ); row = hist[rb]; for( c = 0; c <= 1; c++ ) { cb = c0 + c; if( cb >= 0 && cb < d ) { v_c = v_r * ( ( c == 0 )? 1.0 - d_c : d_c ); h = row[cb]; for( o = 0; o <= 1; o++ ) { ob = ( o0 + o ) % n; v_o = v_c * ( ( o == 0 )? 1.0 - d_o : d_o ); h[ob] += v_o; } } } } }}/*Converts the 2D array of orientation histograms into a feature's descriptorvector.@param hist 2D array of orientation histograms@param d width of hist@param n bins per histogram@param feat feature into which to store descriptor*/void hist_to_descr( double*** hist, int d, int n, struct feature* feat ){ int int_val, i, r, c, o, k = 0; for( r = 0; r < d; r++ ) for( c = 0; c < d; c++ ) for( o = 0; o < n; o++ ) feat->descr[k++] = hist[r][c][o]; feat->d = k; normalize_descr( feat ); for( i = 0; i < k; i++ ) if( feat->descr[i] > SIFT_DESCR_MAG_THR ) feat->descr[i] = SIFT_DESCR_MAG_THR; normalize_descr( feat ); /* convert floating-point descriptor to integer valued descriptor */ for( i = 0; i < k; i++ ) { int_val = SIFT_INT_DESCR_FCTR * feat->descr[i]; feat->descr[i] = MIN( 255, int_val ); }}/*Normalizes a feature's descriptor vector to unitl length@param feat feature*/void normalize_descr( struct feature* feat ){ double cur, len_inv, len_sq = 0.0; int i, d = feat->d; for( i = 0; i < d; i++ ) { cur = feat->descr[i]; len_sq += cur*cur; } len_inv = 1.0 / sqrt( len_sq ); for( i = 0; i < d; i++ ) feat->descr[i] *= len_inv;}/*Compares features for a decreasing-scale ordering. Intended for use withCvSeqSort@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*/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 descriptor histogram@param hist pointer to a 2D array of orientation histograms@param d width of hist*/void release_descr_hist( double**** hist, int d ){ int i, j; for( i = 0; i < d; i++) { for( j = 0; j < d; j++ ) free( (*hist)[i][j] ); free( (*hist)[i] ); } free( *hist ); *hist = NULL;}/*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*/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;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -