📄 siftdescriptor.c
字号:
if( NBO <= 0 ) { mexErrMsgTxt("'NumOrientlBins' must be positive") ; } break ; case PROP_MAGNIF: if( !uIsRealScalar(in[arg+1]) ) { mexErrMsgTxt("'Magnif' should be a real scalar") ; } magnif = (float) *mxGetPr(in[arg+1]) ; if( magnif <= 0 ) { mexErrMsgTxt("'Magnif' must be positive") ; } break ; case PROP_UNKNOWN: mexErrMsgTxt("Property unknown.") ; break ; } arg += 2 ; } } /* ----------------------------------------------------------------- * Pre-compute gradient and angles * -------------------------------------------------------------- */ /* Alloc two buffers and make sure their size is multiple of 128 for * better alignment (used also by the Altivec code below.) */ buffer_size = (M*N*num_levels + 0x7f) & (~ 0x7f) ; buffer_pt = (float*) mxMalloc( sizeof(float) * 2 * buffer_size ) ; descr_pt = (float*) mxCalloc( NBP*NBP*NBO*K, sizeof(float) ) ; { /* Offsets to move in the scale space. */ const int yo = 1 ; const int xo = M ; const int so = M*N ; int x,y,s ;#define at(x,y) (*(pt + (x)*xo + (y)*yo)) /* Compute the gradient */ for(s = 0 ; s < num_levels ; ++s) { const double* pt = G_pt + s*so ; for(x = 1 ; x < N-1 ; ++x) { for(y = 1 ; y < M-1 ; ++y) { float Dx = 0.5 * ( at(x+1,y) - at(x-1,y) ) ; float Dy = 0.5 * ( at(x,y+1) - at(x,y-1) ) ; buffer_pt[(x*xo+y*yo+s*so) + 0 ] = Dx ; buffer_pt[(x*xo+y*yo+s*so) + buffer_size] = Dy ; } } } /* Compute angles and modules */ { float* pt = buffer_pt ; int j = 0 ; while (j < N*M*num_levels) {#if defined( MACOSX ) && defined( __ALTIVEC__ ) if( ((unsigned int)pt & 0x7) == 0 && j+3 < N*M*num_levels ) { /* If aligned to 128 bit and there are at least 4 pixels left */ float4 a, b, c, d ; a.vec = vec_ld(0,(vector float*)(pt )) ; b.vec = vec_ld(0,(vector float*)(pt + buffer_size)) ; c.vec = vatan2f(b.vec,a.vec) ; a.x[0] = a.x[0]*a.x[0]+b.x[0]*b.x[0] ; a.x[1] = a.x[1]*a.x[1]+b.x[1]*b.x[1] ; a.x[2] = a.x[2]*a.x[2]+b.x[2]*b.x[2] ; a.x[3] = a.x[3]*a.x[3]+b.x[3]*b.x[3] ; d.vec = vsqrtf(a.vec) ; vec_st(c.vec,0,(vector float*)(pt + buffer_size)) ; vec_st(d.vec,0,(vector float*)(pt )) ; j += 4 ; pt += 4 ; } else {#endif float Dx = *(pt ) ; float Dy = *(pt + buffer_size) ; *(pt ) = sqrtf(Dx*Dx + Dy*Dy) ; *(pt + buffer_size) = atan2f(Dy, Dx) ; j += 1 ; pt += 1 ;#if defined( MACOSX ) && defined( __ALTIVEC__ ) }#endif } } } /* ----------------------------------------------------------------- * Do the job * -------------------------------------------------------------- */ if(K > 0) { int p ; /* Offsets to move in the buffer */ const int yo = 1 ; const int xo = M ; const int so = M*N ; /* Offsets to move in the descriptor. */ /* Use Lowe's convention. */ const int binto = 1 ; const int binyo = NBO * NBP ; const int binxo = NBO ; const int bino = NBO * NBP * NBP ; for(p = 0 ; p < K ; ++p, descr_pt += bino) { /* The SIFT descriptor is a three dimensional histogram of the position * and orientation of the gradient. There are NBP bins for each spatial * dimesions and NBO bins for the orientation dimesion, for a total of * NBP x NBP x NBO bins. * * The support of each spatial bin has an extension of SBP = 3sigma * pixels, where sigma is the scale of the keypoint. Thus all the bins * together have a support SBP x NBP pixels wide . Since weighting and * interpolation of pixel is used, another half bin is needed at both * ends of the extension. Therefore, we need a square window of SBP x * (NBP + 1) pixels. Finally, since the patch can be arbitrarly rotated, * we need to consider a window 2W += sqrt(2) x SBP x (NBP + 1) pixels * wide. */ const float x = (float) *P_pt++ ; const float y = (float) *P_pt++ ; const float s = (float) (mode == SCALESPACE) ? (*P_pt++) : 0.0 ; const float theta0 = (float) *P_pt++ ; const float st0 = sinf(theta0) ; const float ct0 = cosf(theta0) ; const int xi = (int) floor(x+0.5) ; /* Round-off */ const int yi = (int) floor(y+0.5) ; const int si = (int) floor(s+0.5) - smin ; const float sigma = sigma0 * powf(2, s / S) ; const float SBP = magnif * sigma ; const int W = (int) floor( sqrt(2.0) * SBP * (NBP + 1) / 2.0 + 0.5) ; int bin ; int dxi ; int dyi ; const float* pt ; float* dpt ; /* Check that keypoints are within bounds . */ if(xi < 0 || xi > N-1 || yi < 0 || yi > M-1 || ((mode==SCALESPACE) && (si < 0 || si > dimensions[2]-1) ) ) continue ; /* Center the scale space and the descriptor on the current keypoint. * Note that dpt is pointing to the bin of center (SBP/2,SBP/2,0). */ pt = buffer_pt + xi*xo + yi*yo + si*so ; dpt = descr_pt + (NBP/2) * binyo + (NBP/2) * binxo ; #define atd(dbinx,dbiny,dbint) (*(dpt + (dbint)*binto + (dbiny)*binyo + (dbinx)*binxo)) /* * Process each pixel in the window and in the (1,1)-(M-1,N-1) * rectangle. */ for(dxi = max(-W, 1-xi) ; dxi <= min(+W, N-2-xi) ; ++dxi) { for(dyi = max(-W, 1-yi) ; dyi <= min(+W, M-2-yi) ; ++dyi) { /* Compute the gradient. */ float mod = *(pt + dxi*xo + dyi*yo + 0 ) ; float angle = *(pt + dxi*xo + dyi*yo + buffer_size ) ;#ifdef LOWE_COMPATIBLE float theta = fast_mod(-angle + theta0) ;#else float theta = fast_mod(angle - theta0) ;#endif /* Get the fractional displacement. */ float dx = ((float)(xi+dxi)) - x; float dy = ((float)(yi+dyi)) - y; /* Get the displacement normalized w.r.t. the keypoint orientation * and extension. */ float nx = ( ct0 * dx + st0 * dy) / SBP ; float ny = (-st0 * dx + ct0 * dy) / SBP ; float nt = NBO * theta / (2*M_PI) ; /* Get the gaussian weight of the sample. The gaussian window * has a standard deviation of NBP/2. Note that dx and dy are in * the normalized frame, so that -NBP/2 <= dx <= NBP/2. */ const float wsigma = NBP/2 ; float win = expf(-(nx*nx + ny*ny)/(2.0 * wsigma * wsigma)) ; /* The sample will be distributed in 8 adijacient bins. * Now we get the ``lower-left'' bin. */ int binx = fast_floor( nx - 0.5 ) ; int biny = fast_floor( ny - 0.5 ) ; int bint = fast_floor( nt ) ; float rbinx = nx - (binx+0.5) ; float rbiny = ny - (biny+0.5) ; float rbint = nt - bint ; int dbinx ; int dbiny ; int dbint ; /* Distribute the current sample into the 8 adijacient bins. */ for(dbinx = 0 ; dbinx < 2 ; ++dbinx) { for(dbiny = 0 ; dbiny < 2 ; ++dbiny) { for(dbint = 0 ; dbint < 2 ; ++dbint) { if( binx+dbinx >= -(NBP/2) && binx+dbinx < (NBP/2) && biny+dbiny >= -(NBP/2) && biny+dbiny < (NBP/2) ) { float weight = win * mod * fabsf(1 - dbinx - rbinx) * fabsf(1 - dbiny - rbiny) * fabsf(1 - dbint - rbint) ; atd(binx+dbinx, biny+dbiny, (bint+dbint) % NBO) += weight ; } } } } } } { /* Normalize the histogram to L2 unit length. */ normalize_histogram(descr_pt, descr_pt + NBO*NBP*NBP) ; /* Truncate at 0.2. */ for(bin = 0; bin < NBO*NBP*NBP ; ++bin) { if (descr_pt[bin] > 0.2) descr_pt[bin] = 0.2; } /* Normalize again. */ normalize_histogram(descr_pt, descr_pt + NBO*NBP*NBP) ; } } } /* Restore pointer to the beginning of the descriptors. */ descr_pt -= NBO*NBP*NBP*K ; { int k ; double* L_pt ; out[OUT_L] = mxCreateDoubleMatrix(NBP*NBP*NBO, K, mxREAL) ; L_pt = mxGetPr(out[OUT_L]) ; for(k = 0 ; k < NBP*NBP*NBO*K ; ++k) { L_pt[k] = descr_pt[k] ; } } mxFree(descr_pt) ; mxFree(buffer_pt) ;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -