00001
00007
00008
00009
00010
00011
00012
00013
00014
00015 #include <mexutils.h>
00016 #include <vl/mathop.h>
00017 #include <vl/sift.h>
00018
00019 #include <math.h>
00020 #include <assert.h>
00021
00022
00023 enum {
00024 opt_magnif,
00025 opt_float_descriptors,
00026 opt_norm_thresh,
00027 opt_verbose
00028 } ;
00029
00030
00031 vlmxOption options [] = {
00032 {"Magnif", 1, opt_magnif },
00033 {"Verbose", 0, opt_verbose },
00034 {"FloatDescriptors", 0, opt_float_descriptors },
00035 {"NormThresh", 1, opt_norm_thresh },
00036 {0, 0, 0 }
00037 } ;
00038
00052 VL_INLINE void
00053 transpose_descriptor (vl_sift_pix* dst, vl_sift_pix* src)
00054 {
00055 int const BO = 8 ;
00056 int const BP = 4 ;
00057 int i, j, t ;
00058
00059 for (j = 0 ; j < BP ; ++j) {
00060 int jp = BP - 1 - j ;
00061 for (i = 0 ; i < BP ; ++i) {
00062 int o = BO * i + BP*BO * j ;
00063 int op = BO * i + BP*BO * jp ;
00064 dst [op] = src[o] ;
00065 for (t = 1 ; t < BO ; ++t)
00066 dst [BO - t + op] = src [t + o] ;
00067 }
00068 }
00069 }
00070
00075 void
00076 mexFunction(int nout, mxArray *out[],
00077 int nin, const mxArray *in[])
00078 {
00079 enum {IN_GRAD=0,IN_FRAMES,IN_END} ;
00080 enum {OUT_DESCRIPTORS} ;
00081
00082 int verbose = 0 ;
00083 int opt ;
00084 int next = IN_END ;
00085 mxArray const *optarg ;
00086
00087 mxArray *grad_array ;
00088 vl_sift_pix *grad ;
00089 int M, N ;
00090
00091 vl_bool floatDescriptors = 0 ;
00092 double magnif = -1 ;
00093 double norm_thresh = -1 ;
00094 double *ikeys = 0 ;
00095 int nikeys = 0 ;
00096
00097 int i,j ;
00098
00099 VL_USE_MATLAB_ENV ;
00100
00101
00102
00103
00104
00105 if (nin < 2) {
00106 mexErrMsgTxt("Two arguments required.") ;
00107 } else if (nout > 1) {
00108 mexErrMsgTxt("Too many output arguments.");
00109 }
00110
00111 if (mxGetNumberOfDimensions (in[IN_GRAD]) != 3 ||
00112 mxGetClassID (in[IN_GRAD]) != mxSINGLE_CLASS ||
00113 mxGetDimensions (in[IN_GRAD])[0] != 2 ) {
00114 mexErrMsgTxt("GRAD must be a 2xMxN matrix of class SINGLE.") ;
00115 }
00116
00117 if (!vlmxIsMatrix(in[IN_FRAMES], 4, -1)) {
00118 mexErrMsgTxt("FRAMES must be a 4xN matrix.") ;
00119 }
00120 nikeys = mxGetN (in[IN_FRAMES]) ;
00121 ikeys = mxGetPr(in[IN_FRAMES]) ;
00122
00123 while ((opt = vlmxNextOption (in, nin, options, &next, &optarg)) >= 0) {
00124 switch (opt) {
00125
00126 case opt_verbose :
00127 ++ verbose ;
00128 break ;
00129
00130 case opt_magnif :
00131 if (!vlmxIsPlainScalar(optarg) || (magnif = *mxGetPr(optarg)) < 0) {
00132 mexErrMsgTxt("MAGNIF must be a non-negative scalar.") ;
00133 }
00134 break ;
00135
00136 case opt_float_descriptors :
00137 floatDescriptors = 1 ;
00138 break ;
00139
00140 case opt_norm_thresh :
00141 if (!vlmxIsPlainScalar(optarg) || (norm_thresh = *mxGetPr(optarg)) < 0) {
00142 mexErrMsgTxt("NORMTHRESH must be a non-negative scalar.") ;
00143 }
00144 break ;
00145
00146 default :
00147 abort() ;
00148 }
00149 }
00150
00151 grad_array = mxDuplicateArray(in[IN_GRAD]) ;
00152 grad = (vl_sift_pix*) mxGetData (grad_array) ;
00153 M = mxGetDimensions(in[IN_GRAD])[1] ;
00154 N = mxGetDimensions(in[IN_GRAD])[2] ;
00155
00156
00157 for (i = 1 ; i < 2*M*N ; i+=2) {
00158 grad [i] = VL_PI/2 - grad [i] ;
00159 }
00160
00161
00162
00163
00164 {
00165 VlSiftFilt * filt = 0 ;
00166 void * descr = 0 ;
00167
00168
00169 filt = vl_sift_new (M, N, -1, -1, 0) ;
00170
00171 if (magnif >= 0) vl_sift_set_magnif (filt, magnif) ;
00172 if (norm_thresh >= 0) vl_sift_set_norm_thresh (filt, norm_thresh) ;
00173 if (verbose) {
00174 mexPrintf("vl_siftdescriptor: filter settings:\n") ;
00175 mexPrintf("vl_siftdescriptor: magnif = %g\n",
00176 vl_sift_get_magnif (filt)) ;
00177 mexPrintf("vl_siftdescriptor: num of frames = %d\n",
00178 nikeys) ;
00179 mexPrintf("vl_siftdescriptor: float descriptor = %d\n",
00180 floatDescriptors) ;
00181 mexPrintf("vl_siftdescriptor: norm thresh = %g\n",
00182 vl_sift_get_norm_thresh (filt));
00183 }
00184
00185 {
00186 mwSize dims [2] ;
00187 dims [0] = 128 ;
00188 dims [1] = nikeys ;
00189 out[OUT_DESCRIPTORS]= mxCreateNumericArray
00190 (2, dims,
00191 floatDescriptors ? mxSINGLE_CLASS : mxUINT8_CLASS,
00192 mxREAL) ;
00193 descr = mxGetData(out[OUT_DESCRIPTORS]) ;
00194 }
00195
00196
00197
00198
00199 for (i = 0 ; i < nikeys ; ++i) {
00200 vl_sift_pix buf [128], rbuf [128] ;
00201
00202 double y = *ikeys++ - 1 ;
00203 double x = *ikeys++ - 1 ;
00204 double s = *ikeys++ ;
00205 double th = VL_PI / 2 - *ikeys++ ;
00206
00207 vl_sift_calc_raw_descriptor (filt,
00208 grad,
00209 buf,
00210 M, N,
00211 x, y, s, th) ;
00212
00213 transpose_descriptor (rbuf, buf) ;
00214
00215 if (! floatDescriptors) {
00216 vl_uint8 * descr_ = descr ;
00217 for (j = 0 ; j < 128 ; ++j) {
00218 float x = 512.0F * rbuf [j] ;
00219 x = (x < 255.0F) ? x : 255.0F ;
00220 *descr_++ = (vl_uint8) (x) ;
00221 }
00222 descr = descr_ ;
00223 } else {
00224 float * descr_ = descr ;
00225 for (j = 0 ; j < 128 ; ++j) {
00226 *descr_++ = 512.0F * rbuf [j] ;
00227 }
00228 descr = descr_ ;
00229 }
00230 }
00231
00232 mxDestroyArray (grad_array) ;
00233 vl_sift_delete (filt) ;
00234 }
00235 }