Go to the documentation of this file.00001
00007
00008
00009
00010
00011
00012
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
00047
00048
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 \
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 \
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 \
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
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
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
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 }