vl_ubcmatch.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 
00017 #include <vl/generic.h>
00018 
00019 #include<stdlib.h>
00020 #include<string.h>
00021 #include<math.h>
00022 
00023 #define TYPEOF_mxDOUBLE_CLASS double
00024 #define TYPEOF_mxSINGLE_CLASS float
00025 #define TYPEOF_mxINT8_CLASS   char
00026 #define TYPEOF_mxUINT8_CLASS  unsigned char
00027 
00028 #define PROMOTE_mxDOUBLE_CLASS double
00029 #define PROMOTE_mxSINGLE_CLASS float
00030 #define PROMOTE_mxINT8_CLASS   int
00031 #define PROMOTE_mxUINT8_CLASS  int
00032 
00033 #define MAXVAL_mxDOUBLE_CLASS mxGetInf()
00034 #define MAXVAL_mxSINGLE_CLASS ((float)mxGetInf())
00035 #define MAXVAL_mxINT8_CLASS   0x7fffffff
00036 #define MAXVAL_mxUINT8_CLASS  0x7fffffff
00037 
00038 typedef struct
00039 {
00040   int k1 ;
00041   int k2 ;
00042   double score ;
00043 } Pair ;
00044 
00045 /*
00046  * This macro defines the matching function for abstract type; that
00047  * is, it is a sort of C++ template.  This is also a good illustration
00048  * of why C++ is preferable for templates :-)
00049  */
00050 #define _COMPARE_TEMPLATE(MXC)                                          \
00051   Pair* compare_##MXC (Pair* pairs_iterator,                            \
00052                        const TYPEOF_##MXC * L1_pt,                      \
00053                        const TYPEOF_##MXC * L2_pt,                      \
00054                        int K1, int K2, int ND, float thresh)            \
00055   {                                                                     \
00056     int k1, k2 ;                                                        \
00057     const PROMOTE_##MXC maxval = MAXVAL_##MXC ;                         \
00058     for(k1 = 0 ; k1 < K1 ; ++k1, L1_pt += ND ) {                        \
00059                                                                         \
00060       PROMOTE_##MXC best = maxval ;                                     \
00061       PROMOTE_##MXC second_best = maxval ;                              \
00062       int bestk = -1 ;                                                  \
00063                                                                         \
00064       /* For each point P2[k2] in the second image... */                \
00065       for(k2 =  0 ; k2 < K2 ; ++k2, L2_pt += ND) {                      \
00066                                                                         \
00067         int bin ;                                                       \
00068         PROMOTE_##MXC acc = 0 ;                                         \
00069         for(bin = 0 ; bin < ND ; ++bin) {                               \
00070           PROMOTE_##MXC delta =                                         \
00071             ((PROMOTE_##MXC) L1_pt[bin]) -                              \
00072             ((PROMOTE_##MXC) L2_pt[bin]) ;                              \
00073           acc += delta*delta ;                                          \
00074           if (acc >= second_best) {                                     \
00075             break ;                                                     \
00076           }                                                             \
00077         }                                                               \
00078                                                                         \
00079         /* Filter the best and second best matching point. */           \
00080         if(acc < best) {                                                \
00081           second_best = best ;                                          \
00082           best = acc ;                                                  \
00083           bestk = k2 ;                                                  \
00084         } else if(acc < second_best) {                                  \
00085           second_best = acc ;                                           \
00086         }                                                               \
00087       }                                                                 \
00088                                                                         \
00089       L2_pt -= ND*K2 ;                                                  \
00090                                                                         \
00091       /* Lowe's method: accept the match only if unique. */             \
00092       if(thresh * (float) best < (float) second_best &&                 \
00093          bestk != -1) {                                                 \
00094         pairs_iterator->k1 = k1 ;                                       \
00095         pairs_iterator->k2 = bestk ;                                    \
00096         pairs_iterator->score = best ;                                  \
00097         pairs_iterator++ ;                                              \
00098       }                                                                 \
00099     }                                                                   \
00100                                                                         \
00101     return pairs_iterator ;                                             \
00102   }                                                                     \
00103 
00104 _COMPARE_TEMPLATE( mxDOUBLE_CLASS )
00105 _COMPARE_TEMPLATE( mxSINGLE_CLASS )
00106 _COMPARE_TEMPLATE( mxINT8_CLASS   )
00107 _COMPARE_TEMPLATE( mxUINT8_CLASS  )
00108 
00109 void
00110 mexFunction(int nout, mxArray *out[],
00111             int nin, const mxArray *in[])
00112 {
00113   int unsigned K1, K2, ND ;
00114   void* L1_pt ;
00115   void* L2_pt ;
00116   double thresh = 1.5 ;
00117   mxClassID data_class ;
00118   enum {L1=0,L2,THRESH} ;
00119   enum {MATCHES=0,D} ;
00120 
00121   /* -----------------------------------------------------------------
00122   **                                               Check the arguments
00123   ** -------------------------------------------------------------- */
00124   if (nin < 2) {
00125     mexErrMsgTxt("At least two input arguments required");
00126   } else if (nout > 2) {
00127     mexErrMsgTxt("Too many output arguments");
00128   }
00129 
00130   if(!mxIsNumeric(in[L1]) ||
00131      !mxIsNumeric(in[L2]) ||
00132      mxGetNumberOfDimensions(in[L1]) > 2 ||
00133      mxGetNumberOfDimensions(in[L2]) > 2) {
00134     mexErrMsgTxt("L1 and L2 must be two dimensional numeric arrays") ;
00135   }
00136 
00137   K1 = mxGetN(in[L1]) ;
00138   K2 = mxGetN(in[L2]) ;
00139   ND = mxGetM(in[L1]) ;
00140 
00141   if(mxGetM(in[L2]) != ND) {
00142     mexErrMsgTxt("L1 and L2 must have the same number of rows") ;
00143   }
00144 
00145   data_class = mxGetClassID(in[L1]) ;
00146   if(mxGetClassID(in[L2]) != data_class) {
00147     mexErrMsgTxt("L1 and L2 must be of the same class") ;
00148   }
00149 
00150   L1_pt = mxGetData(in[L1]) ;
00151   L2_pt = mxGetData(in[L2]) ;
00152 
00153   if(nin == 3) {
00154     if(!vlmxIsPlainScalar(in[THRESH])) {
00155       mexErrMsgTxt("THRESH should be a real scalar") ;
00156     }
00157     thresh = *mxGetPr(in[THRESH]) ;
00158   } else if(nin > 3) {
00159     mexErrMsgTxt("At most three arguments are allowed") ;
00160   }
00161 
00162   /* -----------------------------------------------------------------
00163   **                                                        Do the job
00164   ** -------------------------------------------------------------- */
00165   {
00166     Pair* pairs_begin = (Pair*) mxMalloc(sizeof(Pair) * (K1+K2)) ;
00167     Pair* pairs_iterator = pairs_begin ;
00168 
00169 
00170 #define _DISPATCH_COMPARE( MXC )                                        \
00171     case MXC :                                                          \
00172       pairs_iterator = compare_##MXC(pairs_iterator,                    \
00173                                      (const TYPEOF_##MXC*) L1_pt,       \
00174                                      (const TYPEOF_##MXC*) L2_pt,       \
00175                                      K1,K2,ND,thresh) ;                 \
00176     break ;                                                             \
00177 
00178     switch (data_class) {
00179     _DISPATCH_COMPARE( mxDOUBLE_CLASS ) ;
00180     _DISPATCH_COMPARE( mxSINGLE_CLASS ) ;
00181     _DISPATCH_COMPARE( mxINT8_CLASS   ) ;
00182     _DISPATCH_COMPARE( mxUINT8_CLASS  ) ;
00183     default :
00184       mexErrMsgTxt("Unsupported numeric class") ;
00185       break ;
00186     }
00187 
00188     /* ---------------------------------------------------------------
00189      *                                                        Finalize
00190      * ------------------------------------------------------------ */
00191     {
00192       Pair* pairs_end = pairs_iterator ;
00193       double* M_pt ;
00194       double* D_pt = NULL ;
00195 
00196       out[MATCHES] = mxCreateDoubleMatrix
00197         (2, pairs_end-pairs_begin, mxREAL) ;
00198 
00199       M_pt = mxGetPr(out[MATCHES]) ;
00200 
00201       if(nout > 1) {
00202         out[D] = mxCreateDoubleMatrix(1,
00203                                       pairs_end-pairs_begin,
00204                                       mxREAL) ;
00205         D_pt = mxGetPr(out[D]) ;
00206       }
00207 
00208       for(pairs_iterator = pairs_begin ;
00209           pairs_iterator < pairs_end  ;
00210           ++pairs_iterator) {
00211         *M_pt++ = pairs_iterator->k1 + 1 ;
00212         *M_pt++ = pairs_iterator->k2 + 1 ;
00213         if(nout > 1) {
00214           *D_pt++ = pairs_iterator->score ;
00215         }
00216       }
00217     }
00218     mxFree(pairs_begin) ;
00219   }
00220 }


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