void mexFunction(int nout, mxArray *out[], int nin, const mxArray *in[]) { enum { X=0,Y } ; enum { U } ; int NP, NCP ; int i,j ; double *X_pt, *Y_pt, *U_pt ; const double small = 2.220446049250313e-16 ; /* ----------------------------------------------------------------- * Check the arguments * -------------------------------------------------------------- */ if(nin != 2) { mexErrMsgTxt("Two input arguments required") ; } if(!uIsRealMatrix(in[X], 2, -1)) { mexErrMsgTxt("X must be a 2xNP real matrix") ; } if(!uIsRealMatrix(in[Y], 2, -1)) { mexErrMsgTxt("Y must be a 2xNCP real matrix") ; } NP = getN(X) ; NCP = getN(Y) ; X_pt = getPr(X); Y_pt = getPr(Y) ; /* Allocate the result. */ out[U] = mxCreateDoubleMatrix(NP, NCP, mxREAL) ; U_pt = mxGetPr(out[U]) ; /* ----------------------------------------------------------------- * Check the arguments * -------------------------------------------------------------- */ for(j = 0 ; j < NCP ; ++j) { double xcp = *Y_pt++ ; double ycp = *Y_pt++ ; for(i = 0 ; i < NP ; ++i) { double dx = *X_pt++ - xcp ; double dy = *X_pt++ - ycp ; double r2 = dx*dx + dy*dy ; *U_pt++ = (r2 <= small) ? 0 : r2 * log (r2) ; } X_pt -= 2*NP ; } }
void mexFunction(int nout, mxArray *out[], int nin, const mxArray *in[]) { int k,K ; double const * om_pt ; double* R_pt ; double* dR_pt ; if(nin != 1) { mexErrMsgTxt("Exactly one argument required.") ; } if(!uIsRealMatrix(in[IN_OM],-1,-1)) { mexErrMsgTxt("OM must be a DOUBLE array") ; } K = mxGetNumberOfElements(in[IN_OM]) ; if(K % 3 || K < 3) { mexErrMsgTxt("The number of elements of OM must be a multiple of 3") ; } K /= 3 ; om_pt = mxGetPr(in[IN_OM]) ; /* space for output (R) */ if( K == 1 ) { out[OUT_R] = mxCreateDoubleMatrix(3,3,mxREAL) ; } else { mwSize dims [3] ; dims[0] = 3 ; dims[1] = 3 ; dims[2] = K ; out[OUT_R] = mxCreateNumericArray(3,dims,mxDOUBLE_CLASS,mxREAL) ; } R_pt = mxGetPr(out[OUT_R]) ; /* space for optional output (dR) */ dR_pt = NULL ; if( nout > 1 ) { if( K == 1 ) { out[OUT_DR] = mxCreateDoubleMatrix(9,3,mxREAL) ; } else { mwSize dims [3] ; dims[0] = 9 ; dims[1] = 3 ; dims[2] = K ; out[OUT_DR] = mxCreateNumericArray(3,dims,mxDOUBLE_CLASS,mxREAL) ; } dR_pt = mxGetPr(out[OUT_DR]) ; } /* ----------------------------------------------------------------- ** Process ** -------------------------------------------------------------- */ for(k = 0 ; k < K ; ++k) { vl_rodrigues(R_pt, dR_pt, om_pt) ; om_pt += 3 ; R_pt += 3*3 ; dR_pt += 9*3 ; } }
void mexFunction(int nout, mxArray *out[], int nin, const mxArray *in[]) { int k,K ; double* om_pt ; double* dom_pt ; double const * R_pt ; /* ----------------------------------------------------------------- ** Check the arguments ** -------------------------------------------------------------- */ if(nin != 1) { mexErrMsgTxt("Exactly one argument required.") ; } if(!uIsRealMatrix(in[IN_R],-1,-1)) { mexErrMsgTxt("R must be a DOUBLE array") ; } K = mxGetNumberOfElements(in[IN_R]) ; if(K % 9 || K < 9) { mexErrMsgTxt("The elements of R must be a multiple of 9.") ; } K /= 9 ; R_pt = mxGetPr(in[IN_R]) ; /* space for output (OM) */ out[OUT_OM] = mxCreateDoubleMatrix(3,1,mxREAL) ; om_pt = mxGetPr(out[OUT_OM]) ; /* space for optional output (dR) */ dom_pt = NULL ; if( nout > 1 ) { if( K == 1 ) { out[OUT_DOM] = mxCreateDoubleMatrix(3,9,mxREAL) ; } else { mwSize dims [3] ; dims[0] = 3 ; dims[1] = 9 ; dims[2] = K ; out[OUT_DOM] = mxCreateNumericArray(3,dims,mxDOUBLE_CLASS,mxREAL) ; } dom_pt = mxGetPr(out[OUT_DOM]) ; } /* ----------------------------------------------------------------- ** Process ** -------------------------------------------------------------- */ for(k = 0 ; k < K ; ++k) { vl_irodrigues(om_pt, dom_pt, R_pt) ; om_pt += 3 ; dom_pt += 3*9 ; R_pt += 3*3 ; } }
/** @brief MATLAB Driver. **/ void mexFunction(int nout, mxArray *out[], int nin, const mxArray *in[]) { int M,N,S=0,smin=0,K,num_levels=0 ; const int* dimensions ; const double* P_pt ; const double* G_pt ; float* descr_pt ; float* buffer_pt ; float sigma0 ; float magnif = 3.0f ; /* Spatial bin extension factor. */ int NBP = 4 ; /* Number of bins for one spatial direction (even). */ int NBO = 8 ; /* Number of bins for the ortientation. */ int mode = NOSCALESPACE ; int buffer_size=0; enum {IN_G=0,IN_P,IN_SIGMA0,IN_S,IN_SMIN} ; enum {OUT_L=0} ; /* ------------------------------------------------------------------ ** Check the arguments ** --------------------------------------------------------------- */ if (nin < 3) { mexErrMsgTxt("At least three arguments are required") ; } else if (nout > 1) { mexErrMsgTxt("Too many output arguments."); } if( !uIsRealScalar(in[IN_SIGMA0]) ) { mexErrMsgTxt("SIGMA0 should be a real scalar") ; } if(!mxIsDouble(in[IN_G]) || mxGetNumberOfDimensions(in[IN_G]) > 3) { mexErrMsgTxt("G should be a real matrix or 3-D array") ; } sigma0 = (float) *mxGetPr(in[IN_SIGMA0]) ; dimensions = mxGetDimensions(in[IN_G]) ; M = dimensions[0] ; N = dimensions[1] ; G_pt = mxGetPr(in[IN_G]) ; P_pt = mxGetPr(in[IN_P]) ; K = mxGetN(in[IN_P]) ; if( !uIsRealMatrix(in[IN_P],-1,-1)) { mexErrMsgTxt("P should be a real matrix") ; } if ( mxGetM(in[IN_P]) == 4) { /* Standard (scale space) mode */ mode = SCALESPACE ; num_levels = dimensions[2] ; if(nin < 5) { mexErrMsgTxt("Five arguments are required in standard mode") ; } if( !uIsRealScalar(in[IN_S]) ) { mexErrMsgTxt("S should be a real scalar") ; } if( !uIsRealScalar(in[IN_SMIN]) ) { mexErrMsgTxt("SMIN should be a real scalar") ; } if( !uIsRealMatrix(in[IN_P],4,-1)) { mexErrMsgTxt("When the e mode P should be a 4xK matrix.") ; } S = (int)(*mxGetPr(in[IN_S])) ; smin = (int)(*mxGetPr(in[IN_SMIN])) ; } else if ( mxGetM(in[IN_P]) == 3 ) { mode = NOSCALESPACE ; num_levels = 1 ; S = 1 ; smin = 0 ; } else { mexErrMsgTxt("P should be either a 3xK or a 4xK matrix.") ; } /* Parse the property-value pairs */ { char str [80] ; int arg = (mode == SCALESPACE) ? IN_SMIN + 1 : IN_SIGMA0 + 1 ; while(arg < nin) { int k ; if( !uIsString(in[arg],-1) ) { mexErrMsgTxt("The first argument in a property-value pair" " should be a string") ; } mxGetString(in[arg], str, 80) ; #ifdef WINDOWS for(k = 0 ; properties[k] && strcmpi(str, properties[k]) ; ++k) ; #else for(k = 0 ; properties[k] && strcasecmp(str, properties[k]) ; ++k) ; #endif switch (k) { case PROP_NBP: if( !uIsRealScalar(in[arg+1]) ) { mexErrMsgTxt("'NumSpatialBins' should be real scalar") ; } NBP = (int) *mxGetPr(in[arg+1]) ; if( NBP <= 0 || (NBP & 0x1) ) { mexErrMsgTxt("'NumSpatialBins' must be positive and even") ; } break ; case PROP_NBO: if( !uIsRealScalar(in[arg+1]) ) { mexErrMsgTxt("'NumOrientBins' should be a real scalar") ; } NBO = (int) *mxGetPr(in[arg+1]) ; 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) ; if (*pt > 0) *(pt + buffer_size) = atan2f(Dy, Dx) ; else *(pt + buffer_size) = 0 ; 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) ; }
void mexFunction(int nout, mxArray *out[], int nin, const mxArray *in[]) { enum {IN_GRAD=0,IN_FRAMES,IN_END} ; enum {OUT_DESCRIPTORS} ; int verbose = 0 ; int opt ; int next = IN_END ; mxArray const *optarg ; mxArray *grad_array ; vl_sift_pix *grad ; int M, N ; double magnif = -1 ; double *ikeys = 0 ; int nikeys = 0 ; int i,j ; VL_USE_MATLAB_ENV ; /* ----------------------------------------------------------------- * Check the arguments * -------------------------------------------------------------- */ if (nin < 2) { mexErrMsgTxt("Two arguments required.") ; } else if (nout > 1) { mexErrMsgTxt("Too many output arguments."); } if (mxGetNumberOfDimensions (in[IN_GRAD]) != 3 || mxGetClassID (in[IN_GRAD]) != mxSINGLE_CLASS || mxGetDimensions (in[IN_GRAD])[0] != 2 ) { mexErrMsgTxt("GRAD must be a 2xMxN matrix of class SINGLE.") ; } if (!uIsRealMatrix(in[IN_FRAMES], 4, -1)) { mexErrMsgTxt("FRAMES must be a 4xN matrix.") ; } nikeys = mxGetN (in[IN_FRAMES]) ; ikeys = mxGetPr(in[IN_FRAMES]) ; while ((opt = uNextOption(in, nin, options, &next, &optarg)) >= 0) { switch (opt) { case opt_verbose : ++ verbose ; break ; case opt_magnif : if (!uIsRealScalar(optarg) || (magnif = *mxGetPr(optarg)) < 0) { mexErrMsgTxt("MAGNIF must be a non-negative scalar.") ; } break ; default : assert(0) ; break ; } } grad_array = mxDuplicateArray(in[IN_GRAD]) ; grad = (vl_sift_pix*) mxGetData (grad_array) ; M = mxGetDimensions(in[IN_GRAD])[1] ; N = mxGetDimensions(in[IN_GRAD])[2] ; /* transpose angles */ for (i = 1 ; i < 2*M*N ; i+=2) { grad [i] = VL_PI/2 - grad [i] ; } /* ----------------------------------------------------------------- * Do job * -------------------------------------------------------------- */ { VlSiftFilt *filt = 0 ; vl_uint8 *descr = 0 ; /* create a filter to process the image */ filt = vl_sift_new (M, N, -1, -1, 0) ; if (magnif >= 0) vl_sift_set_magnif (filt, magnif) ; if (verbose) { mexPrintf("siftdescriptor: filter settings:\n") ; mexPrintf("siftdescriptor: magnif = %g\n", vl_sift_get_magnif (filt)) ; mexPrintf("siftdescriptor: num of frames = %d\n", nikeys) ; } { mwSize dims [2] ; dims [0] = 128 ; dims [1] = nikeys ; out[OUT_DESCRIPTORS]= mxCreateNumericArray (2, dims, mxUINT8_CLASS, mxREAL) ; descr = mxGetData(out[OUT_DESCRIPTORS]) ; } /* ............................................................... * Process each octave * ............................................................ */ for (i = 0 ; i < nikeys ; ++i) { vl_sift_pix buf [128], rbuf [128] ; double y = *ikeys++ - 1 ; double x = *ikeys++ - 1 ; double s = *ikeys++ ; double th = VL_PI / 2 - *ikeys++ ; vl_sift_calc_raw_descriptor (filt, grad, buf, M, N, x, y, s, th) ; transpose_descriptor (rbuf, buf) ; for (j = 0 ; j < 128 ; ++j) { double x = 512.0 * rbuf [j] ; x = (x < 255.0) ? x : 255.0 ; *descr++ = (vl_uint8) (x) ; } } /* cleanup */ mxDestroyArray (grad_array) ; vl_sift_delete (filt) ; } /* job done */ }
void mexFunction(int nout, mxArray *out[], int nin, const mxArray *in[]) { int M,N,S,smin,K ; const int* dimensions ; const double* P_pt ; const double* G_pt ; double* TH_pt ; double sigma0 ; double H_pt [ NBINS ] ; enum {IN_P=0,IN_G,IN_S,IN_SMIN,IN_SIGMA0} ; enum {OUT_Q=0} ; /* ----------------------------------------------------------------- ** Check the arguments ** -------------------------------------------------------------- */ if (nin != 5) { mexErrMsgTxt("Exactly five input arguments required."); } else if (nout > 1) { mexErrMsgTxt("Too many output arguments."); } if( !uIsRealScalar(in[IN_S]) ) { mexErrMsgTxt("S should be a real scalar") ; } if( !uIsRealScalar(in[IN_SMIN]) ) { mexErrMsgTxt("SMIN should be a real scalar") ; } if( !uIsRealScalar(in[IN_SIGMA0]) ) { mexErrMsgTxt("SIGMA0 should be a real scalar") ; } if( !uIsRealMatrix(in[IN_P],3,-1)) { mexErrMsgTxt("P should be a 3xK real matrix") ; } if(mxGetNumberOfDimensions(in[IN_G]) != 3) { mexErrMsgTxt("SSO must be a three dimensional array") ; } dimensions = mxGetDimensions(in[IN_G]) ; M = dimensions[0] ; N = dimensions[1] ; S = (int)(*mxGetPr(in[IN_S])) ; smin = (int)(*mxGetPr(in[IN_SMIN])) ; sigma0 = *mxGetPr(in[IN_SIGMA0]) ; K = mxGetN(in[IN_P]) ; P_pt = mxGetPr(in[IN_P]) ; G_pt = mxGetPr(in[IN_G]) ; /* If the input array is empty, then output an empty array as well. */ if(K == 0) { out[OUT_Q] = mxCreateDoubleMatrix(4,0,mxREAL) ; return ; } /* ------------------------------------------------------------------ * Do the job * --------------------------------------------------------------- */ { int p ; const int yo = 1 ; const int xo = M ; const int so = M*N ; int buffer_size = K*4 ; double* buffer_start = (double*) mxMalloc( buffer_size *sizeof(double)) ; double* buffer_iterator = buffer_start ; double* buffer_end = buffer_start + buffer_size ; for(p = 0 ; p < K ; ++p, TH_pt += 2) { const double x = *P_pt++ ; const double y = *P_pt++ ; const double s = *P_pt++ ; int xi = ((int) (x+0.5)) ; /* Round them off. */ int yi = ((int) (y+0.5)) ; int si = ((int) (s+0.5)) - smin ; int xs ; int ys ; double sigmaw = win_factor * sigma0 * pow(2, ((double)s) / S) ; int W = (int) ceil(3.0 * sigmaw) ; int bin ; const double* pt ; /* Make sure that the rounded off keypoint index is within bound. */ if(xi < 0 || xi > N-1 || yi < 0 || yi > M-1 || si < 0 || si > dimensions[2]-1 ) { mexPrintf("Dropping %d: W %d x %d y %d si [%d,%d,%d,%d]\n",p,W,xi,yi,si,M,N,dimensions[2]) ; continue ; } /* Clear histogram buffer. */ { int i ; for(i = 0 ; i < NBINS ; ++i) H_pt[i] = 0 ; } pt = G_pt + xi*xo + yi*yo + si*so ; #define at(dx,dy) (*(pt + (dx)*xo + (dy)*yo)) for(xs = max(-W, 1-xi) ; xs <= min(+W, N -2 -xi) ; ++xs) { for(ys = max(-W, 1-yi) ; ys <= min(+W, M -2 -yi) ; ++ys) { double Dx = 0.5 * ( at(xs+1,ys) - at(xs-1,ys) ) ; double Dy = 0.5 * ( at(xs,ys+1) - at(xs,ys-1) ) ; double dx = ((double)(xi+xs)) - x; double dy = ((double)(yi+ys)) - y; if(dx*dx + dy*dy > W*W+0.5) continue ; { double win = exp( - (dx*dx + dy*dy)/(2*sigmaw*sigmaw) ) ; double mod = sqrt(Dx*Dx + Dy*Dy) ; double theta = fmod(atan2(Dy, Dx) + 2*M_PI, 2*M_PI) ; bin = (int) floor( NBINS * theta / (2*M_PI) ) ; H_pt[bin] += mod*win ; } } } /* Smooth histogram */ { int iter, i ; for (iter = 0; iter < 6; iter++) { double prev; prev = H_pt[NBINS-1]; for (i = 0; i < NBINS; i++) { float newh = (prev + H_pt[i] + H_pt[(i+1) % NBINS]) / 3.0; prev = H_pt[i] ; H_pt[i] = newh ; } } } /* Find most strong peaks. */ { int i ; double maxh = H_pt[0] ; for(i = 1 ; i < NBINS ; ++i) maxh = max(maxh, H_pt[i]) ; for(i = 0 ; i < NBINS ; ++i) { double h0 = H_pt[i] ; double hm = H_pt[(i-1+NBINS) % NBINS] ; double hp = H_pt[(i+1+NBINS) % NBINS] ; if( h0 > 0.8*maxh && h0 > hm && h0 > hp ) { double di = -0.5 * (hp-hm) / (hp+hm-2*h0) ; /*di=0;*/ double th = 2*M_PI*(i+di+0.5)/NBINS ; if( buffer_iterator == buffer_end ) { int offset = buffer_iterator - buffer_start ; buffer_size += 4*max(1, K/16) ; buffer_start = (double*) mxRealloc(buffer_start, buffer_size*sizeof(double)) ; buffer_end = buffer_start + buffer_size ; buffer_iterator = buffer_start + offset ; } *buffer_iterator++ = x ; *buffer_iterator++ = y ; *buffer_iterator++ = s ; *buffer_iterator++ = th ; } } /* Scan histogram */ } /* Find peaks */ } /* Save back the result. */ { double* result ; int NL = (buffer_iterator - buffer_start)/4 ; out[OUT_Q] = mxCreateDoubleMatrix(4, NL, mxREAL) ; result = mxGetPr(out[OUT_Q]); memcpy(result, buffer_start, sizeof(double) * 4 * NL) ; } mxFree(buffer_start) ; } }
void mexFunction(int nout, mxArray *out[], int nin, const mxArray *in[]) { int M,N,S,smin,K ; const int* dimensions ; const double* P_pt ; const double* D_pt ; double threshold = 0.01 ; /*0.02 ;*/ double r = 10.0 ; double* result ; enum {IN_P=0,IN_D,IN_SMIN,IN_THRESHOLD,IN_R} ; enum {OUT_Q=0} ; /* ----------------------------------------------------------------- ** Check the arguments ** -------------------------------------------------------------- */ if (nin < 3) { mexErrMsgTxt("At least three input arguments required."); } else if (nout > 1) { mexErrMsgTxt("Too many output arguments."); } if( !uIsRealMatrix(in[IN_P],3,-1) ) { mexErrMsgTxt("P must be a 3xK real matrix") ; } if( !mxIsDouble(in[IN_D]) || mxGetNumberOfDimensions(in[IN_D]) != 3) { mexErrMsgTxt("G must be a three dimensional real array.") ; } if( !uIsRealScalar(in[IN_SMIN]) ) { mexErrMsgTxt("SMIN must be a real scalar.") ; } if(nin >= 4) { if(!uIsRealScalar(in[IN_THRESHOLD])) { mexErrMsgTxt("THRESHOLD must be a real scalar.") ; } threshold = *mxGetPr(in[IN_THRESHOLD]) ; } if(nin >= 5) { if(!uIsRealScalar(in[IN_R])) { mexErrMsgTxt("R must be a real scalar.") ; } r = *mxGetPr(in[IN_R]) ; } dimensions = mxGetDimensions(in[IN_D]) ; M = dimensions[0] ; N = dimensions[1] ; S = dimensions[2] ; smin = (int)(*mxGetPr(in[IN_SMIN])) ; if(S < 3 || M < 3 || N < 3) { mexErrMsgTxt("All dimensions of DOG must be not less than 3.") ; } K = mxGetN(in[IN_P]) ; P_pt = mxGetPr(in[IN_P]) ; D_pt = mxGetPr(in[IN_D]) ; /* If the input array is empty, then output an empty array as well. */ if( K == 0) { out[OUT_Q] = mxDuplicateArray(in[IN_P]) ; return ; } /* ----------------------------------------------------------------- * Do the job * -------------------------------------------------------------- */ { double* buffer = (double*) mxMalloc(K*3*sizeof(double)) ; double* buffer_iterator = buffer ; int p ; const int yo = 1 ; const int xo = M ; const int so = M*N ; for(p = 0 ; p < K ; ++p) { int x = ((int)*P_pt++) ; int y = ((int)*P_pt++) ; int s = ((int)*P_pt++) - smin ; int iter ; double b[3] ; /* Local maxima extracted from the DOG * have coorrinates 1<=x<=N-2, 1<=y<=M-2 * and 1<=s-mins<=S-2. This is also the range of the points * that we can refine. */ if(x < 1 || x > N-2 || y < 1 || y > M-2 || s < 1 || s > S-2) { continue ; } #define at(dx,dy,ds) (*(pt + (dx)*xo + (dy)*yo + (ds)*so)) { const double* pt = D_pt + y*yo + x*xo + s*so ; double Dx=0,Dy=0,Ds=0,Dxx=0,Dyy=0,Dss=0,Dxy=0,Dxs=0,Dys=0 ; int dx = 0 ; int dy = 0 ; int j, i, jj, ii ; for(iter = 0 ; iter < max_iter ; ++iter) { double A[3*3] ; #define Aat(i,j) (A[(i)+(j)*3]) x += dx ; y += dy ; pt = D_pt + y*yo + x*xo + s*so ; /* Compute the gradient. */ Dx = 0.5 * (at(+1,0,0) - at(-1,0,0)) ; Dy = 0.5 * (at(0,+1,0) - at(0,-1,0)); Ds = 0.5 * (at(0,0,+1) - at(0,0,-1)) ; /* Compute the Hessian. */ Dxx = (at(+1,0,0) + at(-1,0,0) - 2.0 * at(0,0,0)) ; Dyy = (at(0,+1,0) + at(0,-1,0) - 2.0 * at(0,0,0)) ; Dss = (at(0,0,+1) + at(0,0,-1) - 2.0 * at(0,0,0)) ; Dxy = 0.25 * ( at(+1,+1,0) + at(-1,-1,0) - at(-1,+1,0) - at(+1,-1,0) ) ; Dxs = 0.25 * ( at(+1,0,+1) + at(-1,0,-1) - at(-1,0,+1) - at(+1,0,-1) ) ; Dys = 0.25 * ( at(0,+1,+1) + at(0,-1,-1) - at(0,-1,+1) - at(0,+1,-1) ) ; /* Solve linear system. */ Aat(0,0) = Dxx ; Aat(1,1) = Dyy ; Aat(2,2) = Dss ; Aat(0,1) = Aat(1,0) = Dxy ; Aat(0,2) = Aat(2,0) = Dxs ; Aat(1,2) = Aat(2,1) = Dys ; b[0] = - Dx ; b[1] = - Dy ; b[2] = - Ds ; /* Gauss elimination */ for(j = 0 ; j < 3 ; ++j) { double maxa = 0 ; double maxabsa = 0 ; int maxi = -1 ; double tmp ; /* look for the maximally stable pivot */ for (i = j ; i < 3 ; ++i) { double a = Aat (i,j) ; double absa = abs (a) ; if (absa > maxabsa) { maxa = a ; maxabsa = absa ; maxi = i ; } } /* if singular give up */ if (maxabsa < 1e-10f) { b[0] = 0 ; b[1] = 0 ; b[2] = 0 ; break ; } i = maxi ; /* swap j-th row with i-th row and normalize j-th row */ for(jj = j ; jj < 3 ; ++jj) { tmp = Aat(i,jj) ; Aat(i,jj) = Aat(j,jj) ; Aat(j,jj) = tmp ; Aat(j,jj) /= maxa ; } tmp = b[j] ; b[j] = b[i] ; b[i] = tmp ; b[j] /= maxa ; /* elimination */ for (ii = j+1 ; ii < 3 ; ++ii) { double x = Aat(ii,j) ; for (jj = j ; jj < 3 ; ++jj) { Aat(ii,jj) -= x * Aat(j,jj) ; } b[ii] -= x * b[j] ; } } /* backward substitution */ for (i = 2 ; i > 0 ; --i) { double x = b[i] ; for (ii = i-1 ; ii >= 0 ; --ii) { b[ii] -= x * Aat(ii,i) ; } } /* If the translation of the keypoint is big, move the keypoint * and re-iterate the computation. Otherwise we are all set. */ dx= ((b[0] > 0.6 && x < N-2) ? 1 : 0 ) + ((b[0] < -0.6 && x > 1 ) ? -1 : 0 ) ; dy= ((b[1] > 0.6 && y < M-2) ? 1 : 0 ) + ((b[1] < -0.6 && y > 1 ) ? -1 : 0 ) ; if( dx == 0 && dy == 0 ) break ; } { double val = at(0,0,0) + 0.5 * (Dx * b[0] + Dy * b[1] + Ds * b[2]) ; double score = (Dxx+Dyy)*(Dxx+Dyy) / (Dxx*Dyy - Dxy*Dxy) ; double xn = x + b[0] ; double yn = y + b[1] ; double sn = s + b[2] ; if(fabs(val) > threshold && score < (r+1)*(r+1)/r && score >= 0 && fabs(b[0]) < 1.5 && fabs(b[1]) < 1.5 && fabs(b[2]) < 1.5 && xn >= 0 && xn <= N-1 && yn >= 0 && yn <= M-1 && sn >= 0 && sn <= S-1) { *buffer_iterator++ = xn ; *buffer_iterator++ = yn ; *buffer_iterator++ = sn+smin ; } } } } /* Copy the result into an array. */ { int NL = (buffer_iterator - buffer)/3 ; out[OUT_Q] = mxCreateDoubleMatrix(3, NL, mxREAL) ; result = mxGetPr(out[OUT_Q]); memcpy(result, buffer, sizeof(double) * 3 * NL) ; } mxFree(buffer) ; } }
void mexFunction(int nout, mxArray *out[], int nin, const mxArray *in[]) { enum { X=0,Y,I,iwXp,iwYp } ; enum { wI=0, wIx, wIy } ; int M, N, Mp, Np, ip, jp ; double *X_pt, *Y_pt, *I_pt, *iwXp_pt, *iwYp_pt, *wI_pt, *wIx_pt = 0, *wIy_pt = 0 ; double Xmin, Xmax, Ymin, Ymax ; const double NaN = mxGetNaN() ; /* ----------------------------------------------------------------- * Check the arguments * -------------------------------------------------------------- */ if(nin != 5) { mexErrMsgTxt("Five input argumets required.") ; } if (nout > 3) { mexErrMsgTxt("Too many output arguments") ; } if(!uIsRealMatrix(in[I], -1, -1)) { mexErrMsgTxt("I must be a real matrix of class DOUBLE") ; } if(!uIsRealMatrix(in[iwXp], -1, -1)) { mexErrMsgTxt("iwXp must be a real matrix") ; } M = getM(I) ; N = getN(I) ; Mp = getM(iwXp) ; Np = getN(iwXp) ; if(!uIsRealMatrix(in[iwYp], Mp, Np)) { mexErrMsgTxt ("iwXp and iwYp must be a real matrices of the same dimension") ; } if(!uIsRealVector(in[X],N) || !uIsRealVector(in[Y],M)) { mexErrMsgTxt ("X and Y must be vectors of the same dimensions " "of the columns/rows of I, respectivelye") ; } X_pt = getPr(X); Y_pt = getPr(Y) ; I_pt = getPr(I) ; iwXp_pt = getPr(iwXp) ; iwYp_pt = getPr(iwYp) ; /* Allocate the result. */ out[wI] = mxCreateDoubleMatrix(Mp, Np, mxREAL) ; wI_pt = mxGetPr(out[wI]) ; if (nout > 1) { out[wIx] = mxCreateDoubleMatrix(Mp, Np, mxREAL) ; out[wIy] = mxCreateDoubleMatrix(Mp, Np, mxREAL) ; wIx_pt = mxGetPr (out[wIx]) ; wIy_pt = mxGetPr (out[wIy]) ; } /* ----------------------------------------------------------------- * Do the job * -------------------------------------------------------------- */ Xmin = X_pt [0] ; Xmax = X_pt [N - 1] ; Ymin = Y_pt [0] ; Ymax = Y_pt [M - 1] ; if (nout <= 1) { /* optimized for only image output */ for(jp = 0 ; jp < Np ; ++jp) { for(ip = 0 ; ip < Mp ; ++ip) { /* Search for the four neighbors of the backprojected point. */ double x = *iwXp_pt++ ; double y = *iwYp_pt++ ; double z = NaN ; /* This messy code allows the identity transformation * to be processed as expected. */ if(x >= Xmin && x <= Xmax && y >= Ymin && y <= Ymax) { int j = findNeighbor(x, X_pt, N) ; int i = findNeighbor(y, Y_pt, M) ; double* pt = I_pt + j*M + i ; /* Weights. */ double x0 = X_pt[j] ; double x1 = X_pt[j+1] ; double y0 = Y_pt[i] ; double y1 = Y_pt[i+1] ; double wx = (x-x0)/(x1-x0) ; double wy = (y-y0)/(y1-y0) ; /* Load all possible neighbors. */ double z00 = 0.0 ; double z10 = 0.0 ; double z01 = 0.0 ; double z11 = 0.0 ; if(j > -1) { if(i > -1 ) z00 = *pt ; pt++ ; if(i < M-1) z10 = *pt ; } else { pt++ ; } pt += M - 1; if(j < N-1) { if(i > -1 ) z01 = *pt ; pt++ ; if(i < M-1) z11 = *pt ; } /* Bilinear interpolation. */ z = (1 - wy) * ((1-wx) * z00 + wx * z01) + ( wy) * ((1-wx) * z10 + wx * z11) ; } *(wI_pt + jp*Mp + ip) = z ; } } } /* do also the derivatives */ else { /* optimized for only image output */ for(jp = 0 ; jp < Np ; ++jp) { for(ip = 0 ; ip < Mp ; ++ip) { /* Search for the four neighbors of the backprojected point. */ double x = *iwXp_pt++ ; double y = *iwYp_pt++ ; double z = NaN, zx = NaN, zy = NaN ; /* This messy code allows the identity transformation * to be processed as expected. */ if(x >= Xmin && x <= Xmax && y >= Ymin && y <= Ymax) { int j = findNeighbor(x, X_pt, N) ; int i = findNeighbor(y, Y_pt, M) ; double* pt = I_pt + j*M + i ; /* Weights. */ double x0 = X_pt[j] ; double x1 = X_pt[j+1] ; double y0 = Y_pt[i] ; double y1 = Y_pt[i+1] ; double wx = (x-x0)/(x1-x0) ; double wy = (y-y0)/(y1-y0) ; /* Load all possible neighbors. */ double z00 = 0.0 ; double z10 = 0.0 ; double z01 = 0.0 ; double z11 = 0.0 ; if(j > -1) { if(i > -1 ) z00 = *pt ; pt++ ; if(i < M-1) z10 = *pt ; } else { pt++ ; } pt += M - 1; if(j < N-1) { if(i > -1 ) z01 = *pt ; pt++ ; if(i < M-1) z11 = *pt ; } /* Bilinear interpolation. */ z = (1-wy)*( (1-wx) * z00 + wx * z01) + wy*( (1-wx) * z10 + wx * z11) ; zx = (1-wy) * (z01 - z00) + wy * (z11 - z10) ; zy = (1-wx) * (z10 - z00) + wx * (z11 - z01) ; } *(wI_pt + jp*Mp + ip) = z ; *(wIx_pt + jp*Mp + ip) = zx ; *(wIy_pt + jp*Mp + ip) = zy ; } } } }
void mexFunction(int nout, mxArray *out[], int nin, const mxArray *in[]) { enum {IN_I=0,IN_END} ; enum {OUT_FRAMES=0, OUT_DESCRIPTORS} ; int verbose = 0 ; int opt ; int next = IN_END ; mxArray const *optarg ; vl_sift_pix const *data ; int M, N ; int O = - 1 ; int S = 3 ; int o_min = 0 ; double edge_thresh = -1 ; double peak_thresh = -1 ; double norm_thresh = -1 ; mxArray *ikeys_array = 0 ; double *ikeys = 0 ; int nikeys = -1 ; vl_bool force_orientations = 0 ; VL_USE_MATLAB_ENV ; /* ----------------------------------------------------------------- * Check the arguments * -------------------------------------------------------------- */ if (nin < 1) { mexErrMsgTxt("One argument required.") ; } else if (nout > 2) { mexErrMsgTxt("Too many output arguments."); } if (mxGetNumberOfDimensions (in[IN_I]) != 2 || mxGetClassID (in[IN_I]) != mxSINGLE_CLASS ) { mexErrMsgTxt("I must be a matrix of class SINGLE") ; } data = (vl_sift_pix*) mxGetData (in[IN_I]) ; M = mxGetM (in[IN_I]) ; N = mxGetN (in[IN_I]) ; while ((opt = uNextOption(in, nin, options, &next, &optarg)) >= 0) { switch (opt) { case opt_verbose : ++ verbose ; break ; case opt_octaves : if (!uIsRealScalar(optarg) || (O = (int) *mxGetPr(optarg)) < 0) { mexErrMsgTxt("'Octaves' must be a positive integer.") ; } break ; case opt_levels : if (! uIsRealScalar(optarg) || (S = (int) *mxGetPr(optarg)) < 1) { mexErrMsgTxt("'Levels' must be a positive integer.") ; } break ; case opt_first_octave : if (!uIsRealScalar(optarg)) { mexErrMsgTxt("'FirstOctave' must be an integer") ; } o_min = (int) *mxGetPr(optarg) ; break ; case opt_edge_thresh : if (!uIsRealScalar(optarg) || (edge_thresh = *mxGetPr(optarg)) < 1) { mexErrMsgTxt("'EdgeThresh' must be not smaller than 1.") ; } break ; case opt_peak_thresh : if (!uIsRealScalar(optarg) || (peak_thresh = *mxGetPr(optarg)) < 0) { mexErrMsgTxt("'PeakThresh' must be a non-negative real.") ; } break ; case opt_norm_thresh : if (!uIsRealScalar(optarg) || (norm_thresh = *mxGetPr(optarg)) < 0) { mexErrMsgTxt("'NormThresh' must be a non-negative real.") ; } break ; case opt_frames : if (!uIsRealMatrix(optarg, 4, -1)) { mexErrMsgTxt("'Frames' must be a 4 x N matrix.x") ; } ikeys_array = mxDuplicateArray (optarg) ; nikeys = mxGetN (optarg) ; ikeys = mxGetPr (ikeys_array) ; if (! check_sorted (ikeys, nikeys)) { qsort (ikeys, nikeys, 4 * sizeof(double), korder) ; } break ; case opt_orientations : force_orientations = 1 ; break ; default : assert(0) ; break ; } } /* ----------------------------------------------------------------- * Do job * -------------------------------------------------------------- */ { VlSiftFilt *filt ; vl_bool first ; double *frames = 0 ; vl_uint8 *descr = 0 ; int nframes = 0, reserved = 0, i,j,q ; /* create a filter to process the image */ filt = vl_sift_new (M, N, O, S, o_min) ; if (peak_thresh >= 0) vl_sift_set_peak_thresh (filt, peak_thresh) ; if (edge_thresh >= 0) vl_sift_set_edge_thresh (filt, edge_thresh) ; if (norm_thresh >= 0) vl_sift_set_norm_thresh (filt, norm_thresh) ; if (verbose) { mexPrintf("siftmx: filter settings:\n") ; mexPrintf("siftmx: octaves (O) = %d\n", vl_sift_get_octave_num (filt)) ; mexPrintf("siftmx: levels (S) = %d\n", vl_sift_get_level_num (filt)) ; mexPrintf("siftmx: first octave (o_min) = %d\n", vl_sift_get_octave_first (filt)) ; mexPrintf("siftmx: edge thresh = %g\n", vl_sift_get_edge_thresh (filt)) ; mexPrintf("siftmx: peak thresh = %g\n", vl_sift_get_peak_thresh (filt)) ; mexPrintf("siftmx: norm thresh = %g\n", vl_sift_get_norm_thresh (filt)) ; mexPrintf((nikeys >= 0) ? "siftmx: will source frames? yes (%d)\n" : "siftmx: will source frames? no\n", nikeys) ; mexPrintf("siftmx: will force orientations? %s\n", force_orientations ? "yes" : "no") ; } /* ............................................................... * Process each octave * ............................................................ */ i = 0 ; first = 1 ; while (true) { int err ; VlSiftKeypoint const *keys = 0 ; int nkeys = 0 ; if (verbose) { mexPrintf ("siftmx: processing octave %d\n", vl_sift_get_octave_index (filt)) ; } /* Calculate the GSS for the next octave .................... */ if (first) { err = vl_sift_process_first_octave (filt, data) ; first = 0 ; } else { err = vl_sift_process_next_octave (filt) ; } if (err) break ; if (verbose > 1) { printf("siftmx: GSS octave %d computed\n", vl_sift_get_octave_index (filt)); } /* Run detector ............................................. */ if (nikeys < 0) { vl_sift_detect (filt) ; keys = vl_sift_get_keypoints (filt) ; nkeys = vl_sift_get_keypoints_num (filt) ; i = 0 ; if (verbose > 1) { printf ("siftmx: detected %d (unoriented) keypoints\n", nkeys) ; } } else { nkeys = nikeys ; } /* For each keypoint ........................................ */ for (; i < nkeys ; ++i) { double angles [4] ; int nangles ; VlSiftKeypoint ik ; VlSiftKeypoint const *k ; /* Obtain keypoint orientations ........................... */ if (nikeys >= 0) { vl_sift_keypoint_init (filt, &ik, ikeys [4 * i + 1] - 1, ikeys [4 * i + 0] - 1, ikeys [4 * i + 2]) ; if (ik.o != vl_sift_get_octave_index (filt)) { break ; } k = &ik ; /* optionally compute orientations too */ if (force_orientations) { nangles = vl_sift_calc_keypoint_orientations (filt, angles, k) ; } else { angles [0] = VL_PI / 2 - ikeys [4 * i + 3] ; nangles = 1 ; } } else { k = keys + i ; nangles = vl_sift_calc_keypoint_orientations (filt, angles, k) ; } /* For each orientation ................................... */ for (q = 0 ; q < nangles ; ++q) { vl_sift_pix buf [128] ; vl_sift_pix rbuf [128] ; /* compute descriptor (if necessary) */ if (nout > 1) { vl_sift_calc_keypoint_descriptor (filt, buf, k, angles [q]) ; transpose_descriptor (rbuf, buf) ; } /* make enough room for all these keypoints and more */ if (reserved < nframes + 1) { reserved += 2 * nkeys ; frames = mxRealloc (frames, 4 * sizeof(double) * reserved) ; if (nout > 1) { descr = mxRealloc (descr, 128 * sizeof(double) * reserved) ; } } /* Save back with MATLAB conventions. Notice tha the input * image was the transpose of the actual image. */ frames [4 * nframes + 0] = k -> y + 1 ; frames [4 * nframes + 1] = k -> x + 1 ; frames [4 * nframes + 2] = k -> sigma ; frames [4 * nframes + 3] = VL_PI / 2 - angles [q] ; if (nout > 1) { for (j = 0 ; j < 128 ; ++j) { double x = 512.0 * rbuf [j] ; x = (x < 255.0) ? x : 255.0 ; descr [128 * nframes + j] = (vl_uint8) (x) ; } } ++ nframes ; } /* next orientation */ } /* next keypoint */ } /* next octave */ if (verbose) { mexPrintf ("siftmx: found %d keypoints\n", nframes) ; } /* ............................................................... * Save back * ............................................................ */ { int dims [2] ; /* create an empty array */ dims [0] = 0 ; dims [1] = 0 ; out[OUT_FRAMES] = mxCreateNumericArray (2, dims, mxDOUBLE_CLASS, mxREAL) ; /* set array content to be the frames buffer */ dims [0] = 4 ; dims [1] = nframes ; mxSetDimensions (out[OUT_FRAMES], dims, 2) ; mxSetPr (out[OUT_FRAMES], frames) ; if (nout > 1) { /* create an empty array */ dims [0] = 0 ; dims [1] = 0 ; out[OUT_DESCRIPTORS]= mxCreateNumericArray (2, dims, mxUINT8_CLASS, mxREAL) ; /* set array content to be the descriptors buffer */ dims [0] = 128 ; dims [1] = nframes ; mxSetDimensions (out[OUT_DESCRIPTORS], dims, 2) ; mxSetData (out[OUT_DESCRIPTORS], descr) ; } } /* cleanup */ vl_sift_delete (filt) ; if (ikeys_array) mxDestroyArray(ikeys_array) ; } /* end: do job */ }
void mexFunction (int nout, mxArray * out[], int nin, const mxArray * in[]) { enum {IN_PARENTS = 0, IN_DATA, IN_OPT} ; enum {OUT_TREE} ; vl_uint32 const *parents ; vl_uint32 *tree ; double const *data ; int nnull = 0 ; int histmode = 0 ; int i, P, N ; /* ----------------------------------------------------------------- * Check the arguments * -------------------------------------------------------------- */ if ((nin < 2) || (nin > 3)) { mexErrMsgTxt ("Two or three arguments required.") ; } if (nout > 1) { mexErrMsgTxt ("Too many output arguments.") ; } if (!uIsRealMatrix(in[IN_DATA], -1, -1)) { mexErrMsgTxt ("DATA must be a matrix of DOUBLE"); } if (!uIsVector(in[IN_PARENTS], -1)) { mexErrMsgTxt ("PARENTS must be a vector") ; } if (mxGetClassID(in[IN_PARENTS]) != mxUINT32_CLASS) { mexErrMsgTxt ("PARENTS must be UINT32") ; } N = mxGetNumberOfElements (in[IN_DATA]) ; data = mxGetPr (in[IN_DATA]) ; P = mxGetNumberOfElements (in[IN_PARENTS]) ; parents = mxGetData (in[IN_PARENTS]) ; if (nin > 2) { enum {buflen = 32} ; char buf [buflen] ; if (!uIsString(in[IN_OPT], -1)) { mexErrMsgTxt("OPT must be a string") ; } mxGetString(in[IN_OPT], buf, buflen) ; buf [buflen - 1] = 0 ; if (!uStrICmp("hist", buf)) { mexErrMsgTxt("OPT must be equal to 'hist'") ; } histmode = 1 ; } out[OUT_TREE] = mxCreateNumericMatrix(1, P,mxUINT32_CLASS, mxREAL) ; tree = mxGetData (out[OUT_TREE]) ; /* ----------------------------------------------------------------- * Do the job * -------------------------------------------------------------- */ { char buf [1024] ; vl_uint32 max_node = 0 ; vl_uint32 min_node = 0 ; vl_uint32 last_leaf = 0 ; vl_uint32 root = 0 ; /* exhamine parents for errors and informations */ for (i = 0 ; i < P ; ++i) { vl_uint32 node = parents [i] ; if ((node != 0) & (node != 1)) { max_node = VL_MAX (node, max_node) ; min_node = VL_MIN (node, min_node) ; } /* check no node points outside the tree */ if (node > P) { snprintf(buf, sizeof(buf), "Out of bounds link PARENTS[%d] = %u > %u", i, node, P) ; mexErrMsgTxt (buf) ; } /* check node points to something above him */ if ((node != 0) & (node != 1) & (node < i)) { snprintf(buf, sizeof(buf), "Backward link PARENTS[%d] = %u < %d", i, node, i) ; mexErrMsgTxt (buf) ; } if (node == 0) ++ nnull ; } /* now * * min_node = first node which is not a leaf * max_node = root node * nnull = number of leaves pointing to the null node */ last_leaf = min_node - 1 ; root = max_node ; /* process data */ for (i = 0 ; i < N ; ++i) { int w = 1 ; int x = (int) data [i] ; if (histmode) { w = x ; x = i ; } if ((x < 1) | (x > last_leaf)) { if (histmode) { snprintf(buf, sizeof(buf), "DATA length exceeds number of AIB leaves") ; } else { snprintf(buf, sizeof(buf), "DATA [%d] = %d is not a leaf", i, x) ; } mexErrMsgTxt (buf) ; } while (true) { int x_ = (int) parents [x -1] ; /* mexPrintf("%d : x_=%d, x=%d\n", i, x_, x) ; */ ++ tree [x - 1] ; if ((x_ == x) | (x_ == 0) | (x_ == 1)) break ; x = x_ ; } } } }