int SIFT_ADAPTER::getOctFirst() const { if (!m_has_extracted) { if (m_oct_first == DEFAULT_OCT_FIRST_INVALID) return DEFAULT_OCT_FIRST; else return m_oct_first; } return vl_sift_get_octave_first(m_sift_model); }
/** * Gets the first octave used by the SIFT filter. May only be called if a SIFT filter has been created. * * @param first_octave Will be set to the first octave used by the SIFT filter. * * @return MAR_ERROR_NONE on success, an error code on failure. */ MAR_PUBLIC mar_error_code mar_sift_get_first_octave(int *first_octave) { if (sift_filter == NULL) { return MAR_ERROR_SIFT_FILTER_NOT_CREATED; } *first_octave = vl_sift_get_octave_first(sift_filter); return MAR_ERROR_NONE; }
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_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 */ }
/** @brief SIFT driver entry point **/ int Sift::Detect() { /* algorithm parameters */ double edge_thresh = -1 ; double peak_thresh = -1 ; double magnif = -1 ; int O = -1, S = 3, omin = -1 ; vl_bool err = VL_ERR_OK ; vl_bool force_orientations = 0 ; VlSiftFilt *filt = 0 ; vl_size q ; int i ; vl_bool first ; TimeMeasureBase& measure = *TimeMeasureBase::getInstance(); measure.startTimer("Sift::Detect()"); #define WERR(name,op) \ if (err == VL_ERR_OVERFLOW) { \ snprintf(err_msg, sizeof(err_msg), \ "Output file name too long.") ; \ goto done ; \ } else if (err) { \ snprintf(err_msg, sizeof(err_msg), \ "Could not open '%s' for " #op, name) ; \ goto done ; \ } /* ............................................................... * Make filter * ............................................................ */ filt = vl_sift_new (pim.width, pim.height, O, S, omin) ; Logger::debug(Logger::SIFT, "new filter(vl_sift_new) created:%x", filt) ; if (edge_thresh >= 0) vl_sift_set_edge_thresh (filt, edge_thresh) ; if (peak_thresh >= 0) vl_sift_set_peak_thresh (filt, peak_thresh) ; if (magnif >= 0) vl_sift_set_magnif (filt, magnif) ; if (!filt) { Logger::error(Logger::SIFT, "Detect: could not create SIFT-fiter."); throw SiftException("could not create SIFT-fiter."); } Logger::debug(Logger::SIFT, "sift: filter settings:") ; Logger::debug(Logger::SIFT, "sift: octaves (O) = %d", vl_sift_get_noctaves (filt)) ; Logger::debug(Logger::SIFT, "sift: levels (S) = %d", vl_sift_get_nlevels (filt)) ; Logger::debug(Logger::SIFT, "sift: first octave (o_min) = %d", vl_sift_get_octave_first (filt)) ; Logger::debug(Logger::SIFT, "sift: edge thresh = %g", vl_sift_get_edge_thresh (filt)) ; Logger::debug(Logger::SIFT, "sift: peak thresh = %g", vl_sift_get_peak_thresh (filt)) ; Logger::debug(Logger::SIFT, "sift: magnif = %g", vl_sift_get_magnif (filt)) ; Logger::debug(Logger::SIFT, "sift: will force orientations? %s", force_orientations ? "yes" : "no") ; /* ............................................................... * Process each octave * ............................................................ */ i = 0 ; first = 1 ; while (1) { VlSiftKeypoint const *keys = 0 ; int nkeys ; Logger::debug(Logger::SIFT, "sift: computing octave"); /* calculate the GSS for the next octave .................... */ measure.startTimer("process_octave"); if (first) { measure.startTimer("process_f_octave"); first = 0 ; err = vl_sift_process_first_octave(filt, fdata) ; measure.stopTimer("process_f_octave"); } else { measure.startTimer("process_n_octave"); err = vl_sift_process_next_octave(filt); measure.stopTimer("process_n_octave"); } measure.stopTimer("process_octave"); if (err) { err = VL_ERR_OK ; break ; } Logger::debug(Logger::SIFT, "sift: GSS octave %d computed", vl_sift_get_octave_index (filt)); /* run detector ............................................. */ measure.startTimer("sift_detect"); vl_sift_detect (filt) ; measure.stopTimer("sift_detect"); keys = vl_sift_get_keypoints(filt) ; nkeys = vl_sift_get_nkeypoints(filt) ; i = 0 ; Logger::debug(Logger::SIFT, "sift: detected %d (unoriented) keypoints", nkeys) ; /* for each keypoint ........................................ */ for (; i < nkeys ; ++i) { measure.startTimer("per_kpoint"); double angles [4] ; int nangles ; //VlSiftKeypoint ik ; VlSiftKeypoint const *k ; /* obtain keypoint orientations ........................... */ k = keys + i ; nangles = vl_sift_calc_keypoint_orientations (filt, angles, k) ; /* for each orientation ................................... */ for (q = 0 ; q < (unsigned) nangles ; ++q) { KeyPointDescriptor newKeyPoint; /* compute descriptor (if necessary) */ //if (out.active || dsc.active) { vl_sift_calc_keypoint_descriptor(filt, newKeyPoint.descr, k, angles [q]) ; //} newKeyPoint.keypoint = *k; newKeyPoint.angle = angles[q]; detected_keypoints.push_back(newKeyPoint); } measure.stopTimer("per_kpoint"); } } /* ............................................................... * Finish up * ............................................................ */ /* release filter */ if (filt) { Logger::debug(Logger::SIFT, "freeing filt: %x", filt); vl_sift_delete (filt) ; filt = 0 ; } measure.stopTimer("Sift::Detect()"); measure.printStatistic(); /* quit */ return 0; }
/** @brief SIFT driver entry point **/ int main(int argc, char **argv) { /* algorithm parameters */ double edge_thresh = -1 ; double peak_thresh = -1 ; double magnif = -1 ; int O = -1, S = 3, omin = -1 ; vl_bool err = VL_ERR_OK ; char err_msg [1024] ; int n ; int exit_code = 0 ; int verbose = 0 ; vl_bool force_output = 0 ; vl_bool force_orientations = 0 ; VlFileMeta out = {1, "%.sift", VL_PROT_ASCII, "", 0} ; VlFileMeta frm = {0, "%.frame", VL_PROT_ASCII, "", 0} ; VlFileMeta dsc = {0, "%.descr", VL_PROT_ASCII, "", 0} ; VlFileMeta met = {0, "%.meta", VL_PROT_ASCII, "", 0} ; VlFileMeta gss = {0, "%.pgm", VL_PROT_ASCII, "", 0} ; VlFileMeta ifr = {0, "%.frame", VL_PROT_ASCII, "", 0} ; #define ERRF(msg, arg) { \ err = VL_ERR_BAD_ARG ; \ snprintf(err_msg, sizeof(err_msg), msg, arg) ; \ break ; \ } #define ERR(msg) { \ err = VL_ERR_BAD_ARG ; \ snprintf(err_msg, sizeof(err_msg), msg) ; \ break ; \ } /* ----------------------------------------------------------------- * Parse options * -------------------------------------------------------------- */ while (!err) { int ch = getopt_long(argc, argv, opts, longopts, 0) ; /* If there are no files passed as input, print the help and settings */ if (ch == -1 && argc - optind == 0) ch = 'h'; /* end of option list? */ if (ch == -1) break; switch (ch) { case '?' : /* unkown option ............................................ */ ERRF("Invalid option '%s'.", argv [optind - 1]) ; break ; case ':' : /* missing argument ......................................... */ ERRF("Missing mandatory argument for option '%s'.", argv [optind - 1]) ; break ; case 'h' : /* --help ................................................... */ printf (help_message, argv [0]) ; printf ("SIFT filespec: `%s'\n", out.pattern) ; printf ("Frames filespec: `%s'\n", frm.pattern) ; printf ("Descriptors filespec: `%s'\n", dsc.pattern) ; printf ("Meta filespec: `%s'\n", met.pattern) ; printf ("GSS filespec: '%s'\n", gss.pattern) ; printf ("Read frames filespec: '%s'\n", ifr.pattern) ; printf ("Version: driver %s; libvl %s\n", VL_XSTRINGIFY(VL_SIFT_DRIVER_VERSION), vl_get_version_string()) ; exit (0) ; break ; case 'v' : /* --verbose ................................................ */ ++ verbose ; break ; case 'o' : /* --output ................................................ */ err = vl_file_meta_parse (&out, optarg) ; if (err) ERRF("The arguments of '%s' is invalid.", argv [optind - 1]) ; force_output = 1 ; break ; case opt_frames : /* --frames ................................................ */ err = vl_file_meta_parse (&frm, optarg) ; if (err) ERRF("The arguments of '%s' is invalid.", argv [optind - 1]) ; break ; case opt_descriptors : /* --descriptor ............................................. */ err = vl_file_meta_parse (&dsc, optarg) ; if (err) ERRF("The arguments of '%s' is invalid.", argv [optind - 1]) ; break; case opt_meta : /* --meta ................................................... */ err = vl_file_meta_parse (&met, optarg) ; if (err) ERRF("The arguments of '%s' is invalid.", argv [optind - 1]) ; if (met.protocol != VL_PROT_ASCII) ERR("meta file supports only ASCII protocol") ; break ; case opt_read_frames : /* --read_frames ............................................ */ err = vl_file_meta_parse (&ifr, optarg) ; if (err) ERRF("The arguments of '%s' is invalid.", argv [optind - 1]) ; break ; case opt_gss : /* --gss .................................................... */ err = vl_file_meta_parse (&gss, optarg) ; if (err) ERRF("The arguments of '%s' is invalid.", argv [optind - 1]) ; break ; case 'O' : /* --octaves ............................................... */ n = sscanf (optarg, "%d", &O) ; if (n == 0 || O < 0) ERRF("The argument of '%s' must be a non-negative integer.", argv [optind - 1]) ; break ; case 'S' : /* --levels ............................................... */ n = sscanf (optarg, "%d", &S) ; if (n == 0 || S < 0) ERRF("The argument of '%s' must be a non-negative integer.", argv [optind - 1]) ; break ; case opt_first_octave : /* --first-octave ......................................... */ n = sscanf (optarg, "%d", &omin) ; if (n == 0) ERRF("The argument of '%s' must be an integer.", argv [optind - 1]) ; break ; case opt_edge_thresh : /* --edge-thresh ........................................... */ n = sscanf (optarg, "%lf", &edge_thresh) ; if (n == 0 || edge_thresh < 1) ERRF("The argument of '%s' must be not smaller than 1.", argv [optind - 1]) ; break ; case opt_peak_thresh : /* --edge-thresh ........................................... */ n = sscanf (optarg, "%lf", &peak_thresh) ; if (n == 0 || peak_thresh < 0) ERRF("The argument of '%s' must be a non-negative float.", argv [optind - 1]) ; break ; case opt_magnif : /* --magnif .............................................. */ n = sscanf (optarg, "%lf", &magnif) ; if (n == 0 || magnif < 1) ERRF("The argument of '%s' must be a non-negative float.", argv [optind - 1]) ; break ; case opt_orientations : /* --orientations ......................................... */ force_orientations = 1 ; break ; case 0 : default : /* should not get here ...................................... */ assert (0) ; break ; } } /* check for parsing errors */ if (err) { fprintf(stderr, "%s: error: %s (%d)\n", argv [0], err_msg, err) ; exit (1) ; } /* parse other arguments (filenames) */ argc -= optind ; argv += optind ; /* if --output is not specified, specifying --frames or --descriptors prevent the aggregate outout file to be produced. */ if (! force_output && (frm.active || dsc.active)) { out.active = 0 ; } if (verbose > 1) { #define PRNFO(name,fm) \ printf("sift: " name) ; \ printf("%3s ", (fm).active ? "yes" : "no") ; \ printf("%-6s ", vl_string_protocol_name ((fm).protocol)) ; \ printf("%-10s\n", (fm).pattern) ; PRNFO("write aggregate . ", out) ; PRNFO("write frames .... ", frm) ; PRNFO("write descriptors ", dsc) ; PRNFO("write meta ...... ", met) ; PRNFO("write GSS ....... ", gss) ; PRNFO("read frames .... ", ifr) ; if (force_orientations) printf("sift: will compute orientations\n") ; } /* ------------------------------------------------------------------ * Process one image per time * --------------------------------------------------------------- */ while (argc--) { char basename [1024] ; char const *name = *argv++ ; FILE *in = 0 ; vl_uint8 *data = 0 ; vl_sift_pix *fdata = 0 ; VlPgmImage pim ; VlSiftFilt *filt = 0 ; int q, i ; vl_bool first ; double *ikeys = 0 ; int nikeys = 0, ikeys_size = 0 ; /* ............................................................... * Determine files * ............................................................ */ /* get basenmae from filename */ q = vl_string_basename (basename, sizeof(basename), name, 1) ; err = (q >= sizeof(basename)) ; if (err) { snprintf(err_msg, sizeof(err_msg), "Basename of '%s' is too long", name); err = VL_ERR_OVERFLOW ; goto done ; } if (verbose) { printf ("sift: <== '%s'\n", name) ; } if (verbose > 1) { printf ("sift: basename is '%s'\n", basename) ; } /* open input file */ in = fopen (name, "rb") ; if (!in) { err = VL_ERR_IO ; snprintf(err_msg, sizeof(err_msg), "Could not open '%s' for reading.", name) ; goto done ; } /* ............................................................... * Read data * ............................................................ */ /* read PGM header */ err = vl_pgm_extract_head (in, &pim) ; if (err) { switch (vl_err_no) { case VL_ERR_PGM_IO : snprintf(err_msg, sizeof(err_msg), "Cannot read from '%s'.", name) ; err = VL_ERR_IO ; break ; case VL_ERR_PGM_INV_HEAD : snprintf(err_msg, sizeof(err_msg), "'%s' contains a malformed PGM header.", name) ; err = VL_ERR_IO ; goto done ; } } if (verbose) printf ("sift: image is %d by %d pixels\n", pim. width, pim. height) ; /* allocate buffer */ data = malloc(vl_pgm_get_npixels (&pim) * vl_pgm_get_bpp (&pim) * sizeof (vl_uint8) ) ; fdata = malloc(vl_pgm_get_npixels (&pim) * vl_pgm_get_bpp (&pim) * sizeof (vl_sift_pix)) ; if (!data || !fdata) { err = VL_ERR_ALLOC ; snprintf(err_msg, sizeof(err_msg), "Could not allocate enough memory.") ; goto done ; } /* read PGM body */ err = vl_pgm_extract_data (in, &pim, data) ; if (err) { snprintf(err_msg, sizeof(err_msg), "PGM body malformed.") ; err = VL_ERR_IO ; goto done ; } /* convert data type */ for (q = 0 ; q < pim.width * pim.height ; ++q) fdata [q] = data [q] ; /* ............................................................... * Optionally source keypoints * ............................................................ */ #define WERR(name,op) \ if (err == VL_ERR_OVERFLOW) { \ snprintf(err_msg, sizeof(err_msg), \ "Output file name too long.") ; \ goto done ; \ } else if (err) { \ snprintf(err_msg, sizeof(err_msg), \ "Could not open '%s' for " #op, name) ; \ goto done ; \ } if (ifr.active) { /* open file */ err = vl_file_meta_open (&ifr, basename, "rb") ; WERR(ifr.name, reading) ; #define QERR \ if (err ) { \ snprintf (err_msg, sizeof(err_msg), \ "'%s' malformed", ifr.name) ; \ err = VL_ERR_IO ; \ goto done ; \ } while (1) { double x, y, s, th ; /* read next guy */ err = vl_file_meta_get_double (&ifr, &x) ; if (err == VL_ERR_EOF) break; else QERR ; err = vl_file_meta_get_double (&ifr, &y ) ; QERR ; err = vl_file_meta_get_double (&ifr, &s ) ; QERR ; err = vl_file_meta_get_double (&ifr, &th) ; if (err == VL_ERR_EOF) break; else QERR ; /* make enough space */ if (ikeys_size < nikeys + 1) { ikeys_size += 10000 ; ikeys = realloc (ikeys, 4 * sizeof(double) * ikeys_size) ; } /* add the guy to the buffer */ ikeys [4 * nikeys + 0] = x ; ikeys [4 * nikeys + 1] = y ; ikeys [4 * nikeys + 2] = s ; ikeys [4 * nikeys + 3] = th ; ++ nikeys ; } /* now order by scale */ qsort (ikeys, nikeys, 4 * sizeof(double), korder) ; if (verbose) { printf ("sift: read %d keypoints from '%s'\n", nikeys, ifr.name) ; } /* close file */ vl_file_meta_close (&ifr) ; } /* ............................................................... * Open output files * ............................................................ */ err = vl_file_meta_open (&out, basename, "wb") ; WERR(out.name, writing) ; err = vl_file_meta_open (&dsc, basename, "wb") ; WERR(dsc.name, writing) ; err = vl_file_meta_open (&frm, basename, "wb") ; WERR(frm.name, writing) ; err = vl_file_meta_open (&met, basename, "wb") ; WERR(met.name, writing) ; if (verbose > 1) { if (out.active) printf("sift: writing all ....... to . '%s'\n", out.name); if (frm.active) printf("sift: writing frames .... to . '%s'\n", frm.name); if (dsc.active) printf("sift: writing descriptors to . '%s'\n", dsc.name); if (met.active) printf("sift: writign meta ...... to . '%s'\n", met.name); } /* ............................................................... * Make filter * ............................................................ */ filt = vl_sift_new (pim.width, pim.height, O, S, omin) ; if (edge_thresh >= 0) vl_sift_set_edge_thresh (filt, edge_thresh) ; if (peak_thresh >= 0) vl_sift_set_peak_thresh (filt, peak_thresh) ; if (magnif >= 0) vl_sift_set_magnif (filt, magnif) ; if (!filt) { snprintf (err_msg, sizeof(err_msg), "Could not create SIFT filter.") ; err = VL_ERR_ALLOC ; goto done ; } if (verbose > 1) { printf ("sift: filter settings:\n") ; printf ("sift: octaves (O) = %d\n", vl_sift_get_noctaves (filt)) ; printf ("sift: levels (S) = %d\n", vl_sift_get_nlevels (filt)) ; printf ("sift: first octave (o_min) = %d\n", vl_sift_get_octave_first (filt)) ; printf ("sift: edge thresh = %g\n", vl_sift_get_edge_thresh (filt)) ; printf ("sift: peak thresh = %g\n", vl_sift_get_peak_thresh (filt)) ; printf ("sift: magnif = %g\n", vl_sift_get_magnif (filt)) ; printf ("sift: will source frames? %s\n", ikeys ? "yes" : "no") ; printf ("sift: will force orientations? %s\n", force_orientations ? "yes" : "no") ; } /* ............................................................... * Process each octave * ............................................................ */ i = 0 ; first = 1 ; while (1) { VlSiftKeypoint const *keys ; int nkeys ; /* calculate the GSS for the next octave .................... */ if (first) { first = 0 ; err = vl_sift_process_first_octave (filt, fdata) ; } else { err = vl_sift_process_next_octave (filt) ; } if (err) { err = VL_ERR_OK ; break ; } if (verbose > 1) { printf("sift: GSS octave %d computed\n", vl_sift_get_octave_index (filt)); } /* optionally save GSS */ if (gss.active) { err = save_gss (filt, &gss, basename, verbose) ; if (err) { snprintf (err_msg, sizeof(err_msg), "Could not write GSS to PGM file.") ; goto done ; } } /* run detector ............................................. */ if (ikeys == 0) { vl_sift_detect (filt) ; keys = vl_sift_get_keypoints (filt) ; nkeys = vl_sift_get_nkeypoints (filt) ; i = 0 ; if (verbose > 1) { printf ("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 (ikeys) { vl_sift_keypoint_init (filt, &ik, ikeys [4 * i + 0], ikeys [4 * i + 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] = 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 descr [128] ; /* compute descriptor (if necessary) */ if (out.active || dsc.active) { vl_sift_calc_keypoint_descriptor (filt, descr, k, angles [q]) ; } if (out.active) { int l ; vl_file_meta_put_double (&out, k -> x ) ; vl_file_meta_put_double (&out, k -> y ) ; vl_file_meta_put_double (&out, k -> sigma ) ; vl_file_meta_put_double (&out, angles [q] ) ; for (l = 0 ; l < 128 ; ++l) { vl_file_meta_put_uint8 (&out, (vl_uint8) (512.0 * descr [l])) ; } if (out.protocol == VL_PROT_ASCII) fprintf(out.file, "\n") ; } if (frm.active) { vl_file_meta_put_double (&frm, k -> x ) ; vl_file_meta_put_double (&frm, k -> y ) ; vl_file_meta_put_double (&frm, k -> sigma ) ; vl_file_meta_put_double (&frm, angles [q] ) ; if (frm.protocol == VL_PROT_ASCII) fprintf(frm.file, "\n") ; } if (dsc.active) { int l ; for (l = 0 ; l < 128 ; ++l) { double x = 512.0 * descr[l] ; x = (x < 255.0) ? x : 255.0 ; vl_file_meta_put_uint8 (&dsc, (vl_uint8) (x)) ; } if (dsc.protocol == VL_PROT_ASCII) fprintf(dsc.file, "\n") ; } } } } /* ............................................................... * Finish up * ............................................................ */ if (met.active) { fprintf(met.file, "<sift\n") ; fprintf(met.file, " input = '%s'\n", name) ; if (dsc.active) { fprintf(met.file, " descriptors = '%s'\n", dsc.name) ; } if (frm.active) { fprintf(met.file," frames = '%s'\n", frm.name) ; } fprintf(met.file, ">\n") ; } done : /* release input keys buffer */ if (ikeys) { free (ikeys) ; ikeys_size = nikeys = 0 ; ikeys = 0 ; } /* release filter */ if (filt) { vl_sift_delete (filt) ; filt = 0 ; } /* release image data */ if (fdata) { free (fdata) ; fdata = 0 ; } /* release image data */ if (data) { free (data) ; data = 0 ; } /* close files */ if (in) { fclose (in) ; in = 0 ; } vl_file_meta_close (&out) ; vl_file_meta_close (&frm) ; vl_file_meta_close (&dsc) ; vl_file_meta_close (&met) ; vl_file_meta_close (&gss) ; vl_file_meta_close (&ifr) ; /* if bad print error message */ if (err) { fprintf (stderr, "sift: err: %s (%d)\n", err_msg, err) ; exit_code = 1 ; } } /* quit */ return exit_code ; }