00001
00007
00008
00009
00010
00011
00012
00013
00014
00015 #include <mexutils.h>
00016 #include <vl/kdtree.h>
00017
00018 #include <assert.h>
00019 #include <string.h>
00020
00021 #include "kdtree.h"
00022
00023
00024 enum {
00025 opt_verbose, opt_num_neighs, opt_max_num_comparisons, opt_multithreading
00026 } ;
00027
00028
00029 vlmxOption options [] = {
00030 {"Verbose", 0, opt_verbose },
00031 {"NumNeighbors", 1, opt_num_neighs },
00032 {"MaxComparisons", 1, opt_max_num_comparisons },
00033 {"MaxNumComparisons", 1, opt_max_num_comparisons },
00034 {0, 0, 0 }
00035 } ;
00036
00041 void
00042 mexFunction(int nout, mxArray *out[],
00043 int nin, const mxArray *in[])
00044 {
00045 enum {IN_FOREST = 0, IN_DATA, IN_QUERY, IN_END} ;
00046 enum {OUT_INDEX = 0, OUT_DISTANCE} ;
00047
00048 int verbose = 0 ;
00049 int opt ;
00050 int next = IN_END ;
00051 mxArray const *optarg ;
00052
00053 VlKDForest * forest ;
00054 mxArray const * forest_array = in[IN_FOREST] ;
00055 mxArray const * data_array = in[IN_DATA] ;
00056 mxArray const * query_array = in[IN_QUERY] ;
00057 void * query ;
00058 vl_uint32 * index ;
00059 void * distance ;
00060 vl_size numNeighbors = 1 ;
00061 vl_size numQueries ;
00062 unsigned int numComparisons = 0 ;
00063 unsigned int maxNumComparisons = 0 ;
00064 mxClassID dataClass ;
00065 vl_index i ;
00066
00067 VL_USE_MATLAB_ENV ;
00068
00069
00070
00071
00072
00073 if (nin < 3) {
00074 vlmxError(vlmxErrNotEnoughInputArguments, NULL) ;
00075 }
00076 if (nout > 2) {
00077 vlmxError(vlmxErrTooManyOutputArguments, NULL) ;
00078 }
00079
00080 forest = new_kdforest_from_array (forest_array, data_array) ;
00081
00082 dataClass = mxGetClassID (data_array) ;
00083 if (mxGetClassID (query_array) != dataClass) {
00084 vlmxError(vlmxErrInvalidArgument,
00085 "QUERY must have the same storage class as DATA.") ;
00086 }
00087 if (! vlmxIsReal (query_array)) {
00088 vlmxError(vlmxErrInvalidArgument,
00089 "QUERY must be real.") ;
00090 }
00091 if (! vlmxIsMatrix (query_array, forest->dimension, -1)) {
00092 vlmxError(vlmxErrInvalidArgument,
00093 "QUERY must be a matrix with TREE.NUMDIMENSIONS rows.") ;
00094 }
00095
00096 while ((opt = vlmxNextOption (in, nin, options, &next, &optarg)) >= 0) {
00097 switch (opt) {
00098 case opt_num_neighs :
00099 if (! vlmxIsScalar(optarg) ||
00100 (numNeighbors = mxGetScalar(optarg)) < 1) {
00101 vlmxError(vlmxErrInvalidArgument,
00102 "NUMNEIGHBORS must be a scalar not smaller than one.") ;
00103 }
00104 break;
00105
00106 case opt_max_num_comparisons :
00107 if (! vlmxIsScalar(optarg)) {
00108 vlmxError(vlmxErrInvalidArgument,
00109 "MAXNUMCOMPARISONS must be a scalar.") ;
00110 }
00111 maxNumComparisons = mxGetScalar(optarg) ;
00112 break;
00113
00114 case opt_verbose :
00115 ++ verbose ;
00116 break ;
00117 }
00118 }
00119
00120 vl_kdforest_set_max_num_comparisons (forest, maxNumComparisons) ;
00121
00122 query = mxGetData (query_array) ;
00123 numQueries = mxGetN (query_array) ;
00124
00125 out[OUT_INDEX] = mxCreateNumericMatrix (numNeighbors, numQueries, mxUINT32_CLASS, mxREAL) ;
00126 out[OUT_DISTANCE] = mxCreateNumericMatrix (numNeighbors, numQueries, dataClass, mxREAL) ;
00127
00128 index = mxGetData (out[OUT_INDEX]) ;
00129 distance = mxGetData (out[OUT_DISTANCE]) ;
00130
00131 if (verbose) {
00132 VL_PRINTF ("vl_kdforestquery: number of queries: %d\n", numQueries) ;
00133 VL_PRINTF ("vl_kdforestquery: number of neighbors per query: %d\n", numNeighbors) ;
00134 VL_PRINTF ("vl_kdforestquery: max num of comparisons per query: %d\n",
00135 vl_kdforest_get_max_num_comparisons (forest)) ;
00136 }
00137
00138 numComparisons = vl_kdforest_query_with_array (forest, index, numNeighbors, numQueries, distance, query) ;
00139
00140 vl_kdforest_delete(forest) ;
00141
00142
00143 for (i = 0 ; i < (signed) (numNeighbors * numQueries) ; ++i) { index[i] ++ ; }
00144
00145 if (verbose) {
00146 VL_PRINTF ("vl_kdforestquery: number of comparisons per query: %.3f\n",
00147 ((double) numComparisons) / numQueries) ;
00148 VL_PRINTF ("vl_kdforestquery: number of comparisons per neighbor: %.3f\n",
00149 ((double) numComparisons) / (numQueries * numNeighbors)) ;
00150 }
00151 }