static PyObject *sift(PyObject *self, PyObject *args, PyObject *kwargs) { PyObject *input, *input_frames = NULL; PyArrayObject *matin, *out_descr, *out_frames; /* Input arguments */ static char *kwlist[] = {"input", "Octave", "Levels", "FirstOctave", "Frames", "PeakThresh", "EdgeThresh", "NormThresh", "Orientations", "Verbose", NULL}; enum {IN_I=0,IN_END} ; enum {OUT_FRAMES=0, OUT_DESCRIPTORS} ; int verbose = 0 ; int opt ; int next = IN_END ; int nout = 2; 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 ; PyArrayObject *ikeys_array = 0 ; double *ikeys = 0 ; int nikeys = -1 ; vl_bool force_orientations = 0 ; // VL_USE_MATLAB_ENV ; /* Parse Python tuples into their appropriate variables */ if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|iiiOiiiii", kwlist, &matin, &O, &S, &o_min, &input_frames, &peak_thresh, &edge_thresh, &norm_thresh, &force_orientations, &verbose)) return NULL; // matin = (PyArrayObject *) PyArray_ContiguousFromObject(input, PyArray_FLOAT, 2, 2); //if (matin == NULL) // return NULL; /* ----------------------------------------------------------------- * Check the arguments * -------------------------------------------------------------- */ if (matin->nd != 2 || matin->descr->type_num != PyArray_FLOAT) { printf("I must be a 2d matrix of dtype float32\n") ; return NULL; } // Pointer to the data array in matin //data = (vl_sift_pix *) pyvector_to_Carrayptrs(matin); // vl_sift_pix is float! data = (vl_sift_pix *) matin->data; M = matin->dimensions[0]; N = matin->dimensions[1]; if (input_frames != NULL) { ikeys_array = (PyArrayObject *) PyArray_ContiguousFromObject(input_frames, PyArray_FLOAT, 2, 2); if (ikeys_array->dimensions[0] != 4) { printf("'Frames' must be a 4 x N matrix.x\n"); return NULL; } nikeys = ikeys_array->dimensions[1]; ikeys = (double *) ikeys_array->data; qsort (ikeys, nikeys, 4 * sizeof(double), korder); } /* ----------------------------------------------------------------- * 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) { printf("siftmx: filter settings:\n") ; printf("siftpy: octaves (O) = %d\n", vl_sift_get_octave_num (filt)) ; printf("siftpy: levels (S) = %d\n", vl_sift_get_level_num (filt)) ; printf("siftpy: first octave (o_min) = %d\n", vl_sift_get_octave_first (filt)) ; printf("siftpy: edge thresh = %g\n", vl_sift_get_edge_thresh (filt)) ; printf("siftpy: peak thresh = %g\n", vl_sift_get_peak_thresh (filt)) ; printf("siftpy: norm thresh = %g\n", vl_sift_get_norm_thresh (filt)) ; printf("siftpy: will force orientations? %s\n", force_orientations ? "yes" : "no") ; } Py_BEGIN_ALLOW_THREADS /* ............................................................... * Process each octave * ............................................................ */ i = 0 ; first = 1 ; while (1) { int err ; VlSiftKeypoint const *keys = 0 ; int nkeys = 0 ; if (verbose) { printf ("siftpy: 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("siftpy: 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 ("siftpy: 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 = malloc (4 * sizeof(double) * reserved) ; if (nout > 1) { descr = malloc (128 * sizeof(vl_uint8) * 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) { printf ("siftpy: found %d keypoints\n", nframes) ; } /* ............................................................... * Save back * ............................................................ */ Py_END_ALLOW_THREADS { int dims [2] ; /* create an empty array */ dims [0] = nframes ; dims [1] = 4 ; // We are allocating new memory here because its the only way to make // sure that it will get free()ed when there are no more references out_frames = (PyArrayObject*) PyArray_FromDims(2, dims, PyArray_DOUBLE); memcpy((double*) out_frames->data, frames, 4 * nframes * sizeof(double)); dims [0] = nframes ; // Numpy Array uses row format, Matlab uses column format dims [1] = 128 ; out_descr = (PyArrayObject*) PyArray_FromDims(2, dims, PyArray_UBYTE); memcpy((vl_uint8 *) out_descr->data, descr, 128 * nframes * sizeof(vl_uint8) ); } /* cleanup */ vl_sift_delete (filt) ; free(frames); free(descr); } /* end: do job */ return Py_BuildValue("(OO)",PyArray_Return(out_frames), PyArray_Return(out_descr)); }
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 ; vl_bool floatDescriptors = 0 ; 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 (!vlmxIsMatrix(in[IN_FRAMES], 4, -1)) { mexErrMsgTxt("FRAMES must be a 4xN matrix.") ; } nikeys = mxGetN (in[IN_FRAMES]) ; ikeys = mxGetPr(in[IN_FRAMES]) ; while ((opt = vlmxNextOption (in, nin, options, &next, &optarg)) >= 0) { switch (opt) { case opt_verbose : ++ verbose ; break ; case opt_magnif : if (!vlmxIsPlainScalar(optarg) || (magnif = *mxGetPr(optarg)) < 0) { mexErrMsgTxt("MAGNIF must be a non-negative scalar.") ; } break ; case opt_float_descriptors : floatDescriptors = 1 ; break ; default : abort() ; } } 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 ; void * 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("vl_siftdescriptor: filter settings:\n") ; mexPrintf("vl_siftdescriptor: magnif = %g\n", vl_sift_get_magnif (filt)) ; mexPrintf("vl_siftdescriptor: num of frames = %d\n", nikeys) ; mexPrintf("vl_siftdescriptor: float descriptor = %d\n", floatDescriptors) ; } { mwSize dims [2] ; dims [0] = 128 ; dims [1] = nikeys ; out[OUT_DESCRIPTORS]= mxCreateNumericArray (2, dims, floatDescriptors ? mxSINGLE_CLASS : 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) ; if (! floatDescriptors) { vl_uint8 * descr_ = descr ; for (j = 0 ; j < 128 ; ++j) { float x = 512.0F * rbuf [j] ; x = (x < 255.0F) ? x : 255.0F ; *descr_++ = (vl_uint8) (x) ; } descr = descr_ ; } else { float * descr_ = descr ; for (j = 0 ; j < 128 ; ++j) { *descr_++ = 512.0F * rbuf [j] ; } descr = descr_ ; } } /* cleanup */ mxDestroyArray (grad_array) ; vl_sift_delete (filt) ; } /* job done */ }
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 ; double magnif = -1 ; double window_size = -1 ; mxArray *ikeys_array = 0 ; double *ikeys = 0 ; int nikeys = -1 ; vl_bool force_orientations = 0 ; vl_bool floatDescriptors = 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 = vlmxNextOption (in, nin, options, &next, &optarg)) >= 0) { switch (opt) { case opt_verbose : ++ verbose ; break ; case opt_frames : if (!vlmxIsMatrix(optarg, 4, -1)) { mexErrMsgTxt("'Frames' must be a 4 x N matrix.") ; } ikeys_array = mxDuplicateArray (optarg) ; nikeys = mxGetN (optarg) ; ikeys = mxGetPr (ikeys_array) ; if (! check_sorted (ikeys, nikeys)) { qsort (ikeys, nikeys, 4 * sizeof(double), korder) ; } break ; default : mexPrintf("F**k you!"); abort() ; } } /* ----------------------------------------------------------------- * Do job * -------------------------------------------------------------- */ { VlSiftFilt *filt ; vl_bool first ; double *frames = 0 ; void *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) ; //mexPrintf("%f %f %f \n%f %f %f %f %f\n",(float)O,(float)S,(float)o_min,(float)peak_thresh // ,(float)edge_thresh,(float)norm_thresh,(float)magnif,(float)window_size); /* ............................................................... * Process each octave * ............................................................ */ i = 0 ; first = 1 ; while (first == 1) { int err ; VlSiftKeypoint const *keys = 0 ; int nkeys = 0 ; err = vl_sift_process_first_octave (filt, data) ; first = 0 ; if (err) break ; /* Run detector ............................................. */ nkeys = nikeys ; //mexPrintf("Zhu: entering sweeping nkeys, nkeys = %d, i = %d \n", nkeys, i); /* For each keypoint ........................................ */ for (; i < nkeys ; ++i) { int h; vl_sift_pix buf[128]; vl_sift_pix rbuf[128]; double angle; VlSiftKeypoint ik ; VlSiftKeypoint const *k ; /* Obtain keypoint orientations ........................... */ vl_sift_keypoint_init (filt, &ik, ikeys [4 * i + 1] - 1, ikeys [4 * i + 0] - 1, ikeys [4 * i + 2]) ; //mexPrintf("ikeys: [%f, %f, %f]\n", (float)(ikeys [4 * i + 1] - 1), (float)(ikeys [4 * i + 0] - 1), (float)(ikeys [4 * i + 2]) ); k = &ik ; /* optionally compute orientations too */ angle = VL_PI / 2 - ikeys [4 * i + 3] ; q = 0; /* compute descriptor (if necessary) */ //int h; //mexPrintf("M = %d, N = %d.\n",M,N); //for (h = 0; h < 300; h++) //{ // mexPrintf("%f ",data[h]); // if (h % 8 == 7) mexPrintf("\n"); //} if (nout > 1) { //mexPrintf("angles = %f, x = %f(%d), y = %f(%d), s = %f(%d), o = %d, sigma = %f.\n buf = [", //angle,k->x,k->ix,k->y,k->iy,k->s,k->is,k->o,k->sigma); vl_sift_calc_keypoint_descriptor (filt, buf, k, angle) ; //for (h = 0; h < 128; h++) //{ // mexPrintf("%f ",(float)buf[h]); // if (h % 8 == 7) mexPrintf("\n"); //} //mexPrintf("...].\nrbuf = ["); transpose_descriptor (rbuf, buf) ; //for (h = 0; h < 128; h++) //{ // mexPrintf("%f ",(float)rbuf[h]); // if (h % 8 == 7) mexPrintf("\n"); //} //mexPrintf("...].\n"); } /* 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) { if (! floatDescriptors) { descr = mxRealloc (descr, 128 * sizeof(vl_uint8) * reserved) ; } else { descr = mxRealloc (descr, 128 * sizeof(float) * 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 - angle; //mexPrintf("Zhu: %d\n", nframes); if (nout > 1) { if (! floatDescriptors) { for (j = 0 ; j < 128 ; ++j) { float x = 512.0F * rbuf [j] ; x = (x < 255.0F) ? x : 255.0F ; ((vl_uint8*)descr) [128 * nframes + j] = (vl_uint8) x ; } } else { for (j = 0 ; j < 128 ; ++j) { float x = 512.0F * rbuf [j] ; ((float*)descr) [128 * nframes + j] = x ; } } } ++ nframes ; /* next orientation */ } /* next keypoint */ //break; //mexPrintf("Zhu: skip subsequent octave\n"); } /* next octave */ //mexPrintf("nframes_tot = %d\n",nframes); /* ............................................................... * Save back * ............................................................ */ { mwSize 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 ; mxSetPr (out[OUT_FRAMES], frames) ; mxSetDimensions (out[OUT_FRAMES], dims, 2) ; if (nout > 1) { /* create an empty array */ dims [0] = 0 ; dims [1] = 0 ; out[OUT_DESCRIPTORS]= mxCreateNumericArray (2, dims, floatDescriptors ? mxSINGLE_CLASS : mxUINT8_CLASS, mxREAL) ; /* set array content to be the descriptors buffer */ dims [0] = 128 ; dims [1] = nframes ; mxSetData (out[OUT_DESCRIPTORS], descr) ; mxSetDimensions (out[OUT_DESCRIPTORS], dims, 2) ; } } /* 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_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 ; double magnif = -1 ; double window_size = -1 ; mxArray *ikeys_array = 0 ; double *ikeys = 0 ; int nikeys = -1 ; vl_bool force_orientations = 0 ; vl_bool floatDescriptors = 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 = vlmxNextOption (in, nin, options, &next, &optarg)) >= 0) { switch (opt) { case opt_verbose : ++ verbose ; break ; case opt_octaves : if (!vlmxIsPlainScalar(optarg) || (O = (int) *mxGetPr(optarg)) < 0) { mexErrMsgTxt("'Octaves' must be a positive integer.") ; } break ; case opt_levels : if (! vlmxIsPlainScalar(optarg) || (S = (int) *mxGetPr(optarg)) < 1) { mexErrMsgTxt("'Levels' must be a positive integer.") ; } break ; case opt_first_octave : if (!vlmxIsPlainScalar(optarg)) { mexErrMsgTxt("'FirstOctave' must be an integer") ; } o_min = (int) *mxGetPr(optarg) ; break ; case opt_edge_thresh : if (!vlmxIsPlainScalar(optarg) || (edge_thresh = *mxGetPr(optarg)) < 1) { mexErrMsgTxt("'EdgeThresh' must be not smaller than 1.") ; } break ; case opt_peak_thresh : if (!vlmxIsPlainScalar(optarg) || (peak_thresh = *mxGetPr(optarg)) < 0) { mexErrMsgTxt("'PeakThresh' must be a non-negative real.") ; } break ; case opt_norm_thresh : if (!vlmxIsPlainScalar(optarg) || (norm_thresh = *mxGetPr(optarg)) < 0) { mexErrMsgTxt("'NormThresh' must be a non-negative real.") ; } break ; case opt_magnif : if (!vlmxIsPlainScalar(optarg) || (magnif = *mxGetPr(optarg)) < 0) { mexErrMsgTxt("'Magnif' must be a non-negative real.") ; } break ; case opt_window_size : if (!vlmxIsPlainScalar(optarg) || (window_size = *mxGetPr(optarg)) < 0) { mexErrMsgTxt("'WindowSize' must be a non-negative real.") ; } break ; case opt_frames : if (!vlmxIsMatrix(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 ; case opt_float_descriptors : floatDescriptors = 1 ; break ; default : abort() ; } } /* ----------------------------------------------------------------- * Do job * -------------------------------------------------------------- */ { VlSiftFilt *filt ; vl_bool first ; double *frames = 0 ; void *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 (magnif >= 0) vl_sift_set_magnif (filt, magnif) ; if (window_size >= 0) vl_sift_set_window_size (filt, window_size) ; if (verbose) { mexPrintf("vl_sift: filter settings:\n") ; mexPrintf("vl_sift: octaves (O) = %d\n", vl_sift_get_noctaves (filt)) ; mexPrintf("vl_sift: levels (S) = %d\n", vl_sift_get_nlevels (filt)) ; mexPrintf("vl_sift: first octave (o_min) = %d\n", vl_sift_get_octave_first (filt)) ; mexPrintf("vl_sift: edge thresh = %g\n", vl_sift_get_edge_thresh (filt)) ; mexPrintf("vl_sift: peak thresh = %g\n", vl_sift_get_peak_thresh (filt)) ; mexPrintf("vl_sift: norm thresh = %g\n", vl_sift_get_norm_thresh (filt)) ; mexPrintf("vl_sift: window size = %g\n", vl_sift_get_window_size (filt)) ; mexPrintf("vl_sift: float descriptor = %d\n", floatDescriptors) ; mexPrintf((nikeys >= 0) ? "vl_sift: will source frames? yes (%d read)\n" : "vl_sift: will source frames? no\n", nikeys) ; mexPrintf("vl_sift: will force orientations? %s\n", force_orientations ? "yes" : "no") ; } /* ............................................................... * Process each octave * ............................................................ */ i = 0 ; first = 1 ; while (1) { int err ; VlSiftKeypoint const* keys = 0 ; int nkeys = 0 ; if (verbose) { mexPrintf ("vl_sift: 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) { mexPrintf("vl_sift: 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_nkeypoints (filt) ; i = 0 ; if (verbose > 1) { printf ("vl_sift: 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) { if (! floatDescriptors) { descr = mxRealloc (descr, 128 * sizeof(vl_uint8) * reserved) ; } else { descr = mxRealloc (descr, 128 * sizeof(float) * 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) { if (! floatDescriptors) { for (j = 0 ; j < 128 ; ++j) { float x = 512.0F * rbuf [j] ; x = (x < 255.0F) ? x : 255.0F ; ((vl_uint8*)descr) [128 * nframes + j] = (vl_uint8) x ; } } else { for (j = 0 ; j < 128 ; ++j) { float x = 512.0F * rbuf [j] ; ((float*)descr) [128 * nframes + j] = x ; } } } ++ nframes ; } /* next orientation */ } /* next keypoint */ } /* next octave */ if (verbose) { mexPrintf ("vl_sift: found %d keypoints\n", nframes) ; } /* ............................................................... * Save back * ............................................................ */ { mwSize 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 ; mxSetPr (out[OUT_FRAMES], frames) ; mxSetDimensions (out[OUT_FRAMES], dims, 2) ; if (nout > 1) { /* create an empty array */ dims [0] = 0 ; dims [1] = 0 ; out[OUT_DESCRIPTORS]= mxCreateNumericArray (2, dims, floatDescriptors ? mxSINGLE_CLASS : mxUINT8_CLASS, mxREAL) ; /* set array content to be the descriptors buffer */ dims [0] = 128 ; dims [1] = nframes ; mxSetData (out[OUT_DESCRIPTORS], descr) ; mxSetDimensions (out[OUT_DESCRIPTORS], dims, 2) ; } } /* cleanup */ vl_sift_delete (filt) ; if (ikeys_array) mxDestroyArray(ikeys_array) ; } /* end: do job */ }
PyObject * vl_siftdescriptor_python( PyArrayObject & in_grad, PyArrayObject & in_frames) { // TODO: check types and dim // "GRAD must be a 2xMxN matrix of class SINGLE." assert(in_grad.descr->type_num == PyArray_FLOAT); assert(in_frames.descr->type_num == PyArray_FLOAT64); assert(in_grad.flags & NPY_FORTRAN); assert(in_frames.flags & NPY_FORTRAN); int verbose = 0; int opt; // TODO: check if we need to do a copy of the grad array float * grad_array; vl_sift_pix *grad; int M, N; double magnif = -1; double *ikeys = 0; int nikeys = 0; int i, j; /* ----------------------------------------------------------------- * Check the arguments * -------------------------------------------------------------- */ // get frames nb and data pointer nikeys = in_frames.dimensions[1]; ikeys = (double *) in_frames.data; // TODO: deal with optional params // 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 ; // } // } // TODO: convert to Python //grad_array = mxDuplicateArray(in[IN_GRAD]); (copy?) grad = (float*) in_grad.data; //mxGetData(grad_array); M = in_grad.dimensions[1]; N = in_grad.dimensions[2]; /* transpose angles */ for (i = 1; i < 2 * M * N; i += 2) { grad[i] = VL_PI / 2 - grad[i]; } /* ----------------------------------------------------------------- * Do job * -------------------------------------------------------------- */ PyArrayObject * _descr; { 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) { printf("siftdescriptor: filter settings:\n"); printf( "siftdescriptor: magnif = %g\n", vl_sift_get_magnif(filt)); printf("siftdescriptor: num of frames = %d\n", nikeys); } { npy_intp dims[2]; dims[0] = 128; dims[1] = nikeys; _descr = (PyArrayObject*) PyArray_NewFromDescr( &PyArray_Type, PyArray_DescrFromType(PyArray_UBYTE), 2, dims, NULL, NULL, NPY_F_CONTIGUOUS, NULL); descr = (vl_uint8*) _descr->data; } /* ............................................................... * Process each octave * ............................................................ */ for (i = 0; i < nikeys; ++i) { vl_sift_pix buf[128], rbuf[128]; double y = *ikeys++; double x = *ikeys++; 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 */ return PyArray_Return(_descr); }