vl_dsift.c
Go to the documentation of this file.
00001 
00007 /*
00008 Copyright (C) 2007-12 Andrea Vedaldi and Brian Fulkerson.
00009 All rights reserved.
00010 
00011 This file is part of the VLFeat library and is made available under
00012 the terms of the BSD license (see the COPYING file).
00013 */
00014 
00015 #include <mexutils.h>
00016 #include <vl/mathop.h>
00017 #include <vl/dsift.h>
00018 
00019 #include <math.h>
00020 #include <assert.h>
00021 
00022 /* option codes */
00023 enum {
00024   opt_step = 0,
00025   opt_bounds,
00026   opt_size,
00027   opt_fast,
00028   opt_norm,
00029   opt_window_size,
00030   opt_float_descriptors,
00031   opt_geometry,
00032   opt_verbose
00033 } ;
00034 
00035 /* options */
00036 vlmxOption  options [] = {
00037 {"Bounds",           1,   opt_bounds           },
00038 {"Step",             1,   opt_step             },
00039 {"Size",             1,   opt_size             },
00040 {"Fast",             0,   opt_fast             },
00041 {"Norm",             0,   opt_norm             },
00042 {"WindowSize",       1,   opt_window_size      },
00043 {"FloatDescriptors", 0,   opt_float_descriptors},
00044 {"Geometry",         1,   opt_geometry         },
00045 {"Verbose",          0,   opt_verbose          },
00046 {0,                  0,   0                    }
00047 } ;
00048 
00053 void
00054 mexFunction(int nout, mxArray *out[],
00055             int nin, const mxArray *in[])
00056 {
00057   enum {IN_I=0, IN_END} ;
00058   enum {OUT_FRAMES=0, OUT_DESCRIPTORS} ;
00059 
00060   int verbose = 0 ;
00061   int opt ;
00062   int next = IN_END ;
00063   mxArray const *optarg ;
00064 
00065   float const *data ;
00066   int M, N ;
00067 
00068   int step [2] = {1,1} ;
00069   vl_bool norm = 0 ;
00070 
00071   vl_bool floatDescriptors = VL_FALSE ;
00072   vl_bool useFlatWindow = VL_FALSE ;
00073   double windowSize = -1.0 ;
00074 
00075   double *bounds = NULL ;
00076   double boundBuffer [4] ;
00077   VlDsiftDescriptorGeometry geom ;
00078 
00079   VL_USE_MATLAB_ENV ;
00080 
00081   geom.numBinX = 4 ;
00082   geom.numBinY = 4 ;
00083   geom.numBinT = 8 ;
00084   geom.binSizeX = 3 ;
00085   geom.binSizeY = 3 ;
00086 
00087   /* -----------------------------------------------------------------
00088    *                                               Check the arguments
00089    * -------------------------------------------------------------- */
00090 
00091   if (nin < 1) {
00092     vlmxError(vlmxErrNotEnoughInputArguments, NULL) ;
00093   } else if (nout > 2) {
00094     vlmxError(vlmxErrTooManyOutputArguments, NULL) ;
00095   }
00096 
00097   if (mxGetNumberOfDimensions (in[IN_I]) != 2              ||
00098       mxGetClassID            (in[IN_I]) != mxSINGLE_CLASS ) {
00099     vlmxError(vlmxErrInvalidArgument,
00100               "I must be a matrix of class SINGLE.") ;
00101   }
00102 
00103   data = (float*) mxGetData (in[IN_I]) ;
00104   M    = mxGetM (in[IN_I]) ;
00105   N    = mxGetN (in[IN_I]) ;
00106 
00107   while ((opt = vlmxNextOption (in, nin, options, &next, &optarg)) >= 0) {
00108     switch (opt) {
00109 
00110       case opt_verbose :
00111         ++ verbose ;
00112         break ;
00113 
00114       case opt_fast :
00115         useFlatWindow = 1 ;
00116         break ;
00117 
00118       case opt_norm :
00119         norm = 1 ;
00120         break ;
00121 
00122       case opt_bounds :
00123         if (!vlmxIsPlainVector(optarg, 4)) {
00124           mexErrMsgTxt("BOUNDS must be a 4-dimensional vector.") ;
00125         }
00126         bounds = boundBuffer ;
00127         bounds [0] = mxGetPr(optarg)[0] - 1 ;
00128         bounds [1] = mxGetPr(optarg)[1] - 1 ;
00129         bounds [2] = mxGetPr(optarg)[2] - 1 ;
00130         bounds [3] = mxGetPr(optarg)[3] - 1 ;
00131         break ;
00132 
00133       case opt_size :
00134         if (!vlmxIsPlainVector(optarg,-1)) {
00135           vlmxError(vlmxErrInvalidArgument,"SIZE is not a plain vector.") ;
00136         }
00137         if (mxGetNumberOfElements(optarg) == 1) {
00138           geom.binSizeX = (int) mxGetPr(optarg)[0] ;
00139           geom.binSizeY = (int) mxGetPr(optarg)[0] ;
00140         } else if (mxGetNumberOfElements(optarg) == 2) {
00141           geom.binSizeX = (int) mxGetPr(optarg)[1] ;
00142           geom.binSizeY = (int) mxGetPr(optarg)[0] ;
00143         } else {
00144           vlmxError(vlmxErrInvalidArgument,"SIZE is neither a scalar or a 2D vector.") ;
00145         }
00146         if (geom.binSizeX < 1 || geom.binSizeY < 1) {
00147           vlmxError(vlmxErrInvalidArgument,"SIZE value is invalid.") ;
00148         }
00149         break ;
00150 
00151       case opt_step :
00152         if (!vlmxIsPlainVector(optarg,-1)) {
00153           vlmxError(vlmxErrInvalidArgument,"STEP is not a plain vector.") ;
00154         }
00155         if (mxGetNumberOfElements(optarg) == 1) {
00156           step[0] = (int) mxGetPr(optarg)[0] ;
00157           step[1] = (int) mxGetPr(optarg)[0] ;
00158         } else if (mxGetNumberOfElements(optarg) == 2) {
00159           step[0] = (int) mxGetPr(optarg)[1] ;
00160           step[1] = (int) mxGetPr(optarg)[0] ;
00161         } else {
00162           vlmxError(vlmxErrInvalidArgument,"STEP is neither a scalar or a 2D vector.") ;
00163         }
00164         if (step[0] < 1 || step[1] < 1) {
00165           vlmxError(vlmxErrInvalidArgument,"STEP value is invalid.") ;
00166         }
00167         break ;
00168 
00169       case opt_window_size :
00170         if (!vlmxIsPlainScalar(optarg) || (windowSize = *mxGetPr(optarg)) < 0) {
00171           vlmxError(vlmxErrInvalidArgument,"WINDOWSIZE is not a scalar or it is negative.") ;
00172         }
00173         break ;
00174 
00175       case opt_float_descriptors :
00176         floatDescriptors = VL_TRUE ;
00177         break ;
00178 
00179       case opt_geometry :
00180         if (!vlmxIsPlainVector(optarg,3)) {
00181           vlmxError(vlmxErrInvalidArgument, "GEOMETRY is not a 3D vector.") ;
00182         }
00183         geom.numBinY = (int)mxGetPr(optarg)[0] ;
00184         geom.numBinX = (int)mxGetPr(optarg)[1] ;
00185         geom.numBinT = (int)mxGetPr(optarg)[2] ;
00186         if (geom.numBinX < 1 ||
00187             geom.numBinY < 1 ||
00188             geom.numBinT < 1) {
00189           vlmxError(vlmxErrInvalidArgument, "GEOMETRY value is invalid.") ;
00190         }
00191         break ;
00192 
00193       default :
00194         abort() ;
00195     }
00196   }
00197 
00198   /* -----------------------------------------------------------------
00199    *                                                            Do job
00200    * -------------------------------------------------------------- */
00201   {
00202     int numFrames ;
00203     int descrSize ;
00204     VlDsiftKeypoint const *frames ;
00205     float const *descrs ;
00206     int k, i ;
00207 
00208     VlDsiftFilter *dsift ;
00209 
00210     /* note that the image received from MATLAB is transposed */
00211     dsift = vl_dsift_new (M, N) ;
00212     vl_dsift_set_geometry(dsift, &geom) ;
00213     vl_dsift_set_steps(dsift, step[0], step[1]) ;
00214 
00215     if (bounds) {
00216       vl_dsift_set_bounds(dsift,
00217                           VL_MAX(bounds[1], 0),
00218                           VL_MAX(bounds[0], 0),
00219                           VL_MIN(bounds[3], M - 1),
00220                           VL_MIN(bounds[2], N - 1));
00221     }
00222     vl_dsift_set_flat_window(dsift, useFlatWindow) ;
00223 
00224     if (windowSize >= 0) {
00225       vl_dsift_set_window_size(dsift, windowSize) ;
00226     }
00227 
00228     numFrames = vl_dsift_get_keypoint_num (dsift) ;
00229     descrSize = vl_dsift_get_descriptor_size (dsift) ;
00230     geom = *vl_dsift_get_geometry (dsift) ;
00231 
00232     if (verbose) {
00233       int stepX ;
00234       int stepY ;
00235       int minX ;
00236       int minY ;
00237       int maxX ;
00238       int maxY ;
00239       vl_bool useFlatWindow ;
00240 
00241       vl_dsift_get_steps (dsift, &stepY, &stepX) ;
00242       vl_dsift_get_bounds (dsift, &minY, &minX, &maxY, &maxX) ;
00243       useFlatWindow = vl_dsift_get_flat_window(dsift) ;
00244 
00245       mexPrintf("vl_dsift: image size         [W, H] = [%d, %d]\n", N, M) ;
00246       mexPrintf("vl_dsift: bounds:            [minX,minY,maxX,maxY] = [%d, %d, %d, %d]\n",
00247                 minX+1, minY+1, maxX+1, maxY+1) ;
00248       mexPrintf("vl_dsift: subsampling steps: stepX=%d, stepY=%d\n", stepX, stepY) ;
00249       mexPrintf("vl_dsift: num bins:          [numBinT, numBinX, numBinY] = [%d, %d, %d]\n",
00250                 geom.numBinT,
00251                 geom.numBinX,
00252                 geom.numBinY) ;
00253       mexPrintf("vl_dsift: descriptor size:   %d\n", descrSize) ;
00254       mexPrintf("vl_dsift: bin sizes:         [binSizeX, binSizeY] = [%d, %d]\n",
00255                 geom.binSizeX,
00256                 geom.binSizeY) ;
00257       mexPrintf("vl_dsift: flat window:       %s\n", VL_YESNO(useFlatWindow)) ;
00258       mexPrintf("vl_dsift: window size:       %g\n", vl_dsift_get_window_size(dsift)) ;
00259       mexPrintf("vl_dsift: num of features:   %d\n", numFrames) ;
00260     }
00261 
00262     vl_dsift_process (dsift, data) ;
00263 
00264     frames = vl_dsift_get_keypoints (dsift) ;
00265     descrs = vl_dsift_get_descriptors (dsift) ;
00266 
00267     /* ---------------------------------------------------------------
00268      *                                            Create output arrays
00269      * ------------------------------------------------------------ */
00270     {
00271       mwSize dims [2] ;
00272 
00273       dims [0] = descrSize ;
00274       dims [1] = numFrames ;
00275 
00276       if (floatDescriptors) {
00277         out[OUT_DESCRIPTORS] = mxCreateNumericArray
00278         (2, dims, mxSINGLE_CLASS, mxREAL) ;
00279       } else {
00280         out[OUT_DESCRIPTORS] = mxCreateNumericArray
00281         (2, dims, mxUINT8_CLASS, mxREAL) ;
00282       }
00283 
00284       dims [0] = norm ? 3 : 2 ;
00285 
00286       out[OUT_FRAMES] = mxCreateNumericArray
00287       (2, dims, mxDOUBLE_CLASS, mxREAL) ;
00288     }
00289 
00290     /* ---------------------------------------------------------------
00291      *                                                       Copy back
00292      * ------------------------------------------------------------ */
00293     {
00294       float *tmpDescr = mxMalloc(sizeof(float) * descrSize) ;
00295       double *outFrameIter = mxGetPr(out[OUT_FRAMES]) ;
00296       void *outDescrIter = mxGetData(out[OUT_DESCRIPTORS]) ;
00297       for (k = 0 ; k < numFrames ; ++k) {
00298         *outFrameIter++ = frames[k].y + 1 ;
00299         *outFrameIter++ = frames[k].x + 1 ;
00300 
00301         /* We have an implied / 2 in the norm, because of the clipping
00302            below */
00303         if (norm)
00304           *outFrameIter++ = frames [k].norm ;
00305 
00306         vl_dsift_transpose_descriptor (tmpDescr,
00307                                        descrs + descrSize * k,
00308                                        geom.numBinT,
00309                                        geom.numBinX,
00310                                        geom.numBinY) ;
00311 
00312         if (floatDescriptors) {
00313           for (i = 0 ; i < descrSize ; ++i) {
00314             float * pt = (float*) outDescrIter ;
00315             *pt++ = VL_MIN(512.0F * tmpDescr[i], 255.0F) ;
00316             outDescrIter = pt ;
00317           }
00318         } else {
00319           for (i = 0 ; i < descrSize ; ++i) {
00320             vl_uint8 * pt = (vl_uint8*) outDescrIter ;
00321             *pt++ = (vl_uint8) (VL_MIN(512.0F * tmpDescr[i], 255.0F)) ;
00322             outDescrIter = pt ;
00323 
00324           }
00325         }
00326       }
00327       mxFree(tmpDescr) ;
00328     }
00329     vl_dsift_delete (dsift) ;
00330   }
00331 }


libvlfeat
Author(s): Andrea Vedaldi
autogenerated on Thu Jun 6 2019 20:25:51