00001
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017 #include<mexutils.h>
00018
00019 #include<stdio.h>
00020 #include<stdlib.h>
00021 #include<math.h>
00022 #include<string.h>
00023 #include<assert.h>
00024
00025 #include <vl/hikmeans.h>
00026 #include <vl/generic.h>
00027
00028 enum {
00029 opt_method,
00030 opt_verbose
00031 } ;
00032
00033 vlmxOption options [] = {
00034 {"Method", 1, opt_method },
00035 {"Verbose", 0, opt_verbose },
00036 {0, 0, 0 }
00037 } ;
00038
00039 #define NFIELDS(field_names) (sizeof(field_names)/sizeof(*field_names))
00040
00041
00047 static VlHIKMNode *
00048 xcreate (VlHIKMTree *tree, mxArray const *mnode, int i)
00049 {
00050 mxArray const *mcenters, *msub ;
00051 VlHIKMNode *node ;
00052 mwSize M ;
00053 mwSize node_K ;
00054 vl_uindex k ;
00055
00056
00057 mcenters = mxGetField(mnode, i, "centers") ;
00058 msub = mxGetField(mnode, i, "sub") ;
00059
00060 if (!mcenters ||
00061 mxGetClassID (mcenters) != mxINT32_CLASS ||
00062 !vlmxIsMatrix (mcenters, -1, -1)) {
00063 mexErrMsgTxt("A NODE.CENTERS is not a INT32 matrix.") ;
00064 }
00065
00066 M = mxGetM (mcenters) ;
00067 node_K = mxGetN (mcenters) ;
00068
00069 if (M == 0) {
00070 mexErrMsgTxt("A NODE.CENTERS has zero rows.") ;
00071 }
00072 if ((vl_size)node_K > tree->K) {
00073 mexErrMsgTxt("A NODE.CENTERS has more columns than overall clusters TREE.K.") ;
00074 }
00075 if (tree->M == 0) {
00076 tree->M = M ;
00077 } else if (M != tree->M) {
00078 mexErrMsgTxt("A NODE.CENTERS field has inconsistent dimensionality.") ;
00079 }
00080
00081 node = mxMalloc (sizeof(VlHIKMNode)) ;
00082 node->filter = vl_ikm_new (tree->method) ;
00083 node->children = 0 ;
00084
00085 vl_ikm_init (node->filter, mxGetData(mcenters), M, node_K) ;
00086
00087
00088 if (msub) {
00089
00090
00091 if (mxGetClassID (msub) != mxSTRUCT_CLASS) {
00092 mexErrMsgTxt("A NODE.SUB is not a MATLAB structure array.") ;
00093 }
00094 if (mxGetNumberOfElements (msub) != node_K) {
00095 mexErrMsgTxt("A NODE.SUB does not correspond to NODE.CENTERS.") ;
00096 }
00097
00098 node->children = mxMalloc (sizeof(VlHIKMNode *) * node_K) ;
00099 for(k = 0 ; k < node_K ; ++ k) {
00100 node->children[k] = xcreate (tree, msub, k) ;
00101 }
00102 }
00103 return node ;
00104 }
00105
00111 static VlHIKMTree*
00112 matlab_to_hikm (mxArray const *mtree, int method_type)
00113 {
00114 VlHIKMTree *tree ;
00115 mxArray *mK ;
00116 mxArray *mdepth ;
00117 vl_index K = 0 ;
00118 vl_index depth = 0 ;
00119
00120 VL_USE_MATLAB_ENV ;
00121
00122 if (mxGetClassID (mtree) != mxSTRUCT_CLASS) {
00123 mexErrMsgTxt("TREE must be a MATLAB structure.") ;
00124 }
00125
00126 mK = mxGetField(mtree, 0, "K") ;
00127 mdepth = mxGetField(mtree, 0, "depth") ;
00128
00129 if (!mK ||
00130 !vlmxIsPlainScalar(mK) ||
00131 (K = (int) *mxGetPr(mK)) < 1) {
00132 mexErrMsgTxt("TREE.K must be a DOUBLE not smaller than one.") ;
00133 }
00134
00135 if (!mdepth ||
00136 !vlmxIsPlainScalar (mdepth) ||
00137 (depth = (int) *mxGetPr (mdepth)) < 1) {
00138 mexErrMsgTxt("TREE.DEPTH must be a DOUBLE not smaller than one.") ;
00139 }
00140
00141 tree = mxMalloc (sizeof(VlHIKMTree)) ;
00142 tree->depth = (vl_size)depth ;
00143 tree->K = (vl_size)K ;
00144 tree->M = 0 ;
00145 tree->method = method_type ;
00146 tree->root = xcreate (tree, mtree, 0) ;
00147 return tree ;
00148 }
00149
00150
00153 void mexFunction (int nout, mxArray * out[],
00154 int nin, const mxArray * in[])
00155 {
00156 enum {IN_TREE = 0, IN_DATA, IN_END} ;
00157 enum {OUT_ASGN = 0} ;
00158 vl_uint8 const *data;
00159
00160 int opt ;
00161 int next = IN_END ;
00162 mxArray const *optarg ;
00163
00164 mwSize N = 0 ;
00165 int method_type = VL_IKM_LLOYD ;
00166 int verb = 0 ;
00167
00168
00169
00170
00171 if (nin < 2)
00172 mexErrMsgTxt ("At least two arguments required.");
00173 else if (nout > 1)
00174 mexErrMsgTxt ("Too many output arguments.");
00175
00176 if (mxGetClassID (in[IN_DATA]) != mxUINT8_CLASS) {
00177 mexErrMsgTxt ("DATA must be of class UINT8");
00178 }
00179
00180 N = mxGetN(in[IN_DATA]) ;
00181 data = (vl_uint8 *) mxGetPr (in[IN_DATA]);
00182
00183 while ((opt = vlmxNextOption (in, nin, options, &next, &optarg)) >= 0) {
00184 char buf [1024] ;
00185
00186 switch (opt) {
00187
00188 case opt_verbose :
00189 ++ verb ;
00190 break ;
00191
00192 case opt_method :
00193 if (!vlmxIsString (optarg, -1)) {
00194 mexErrMsgTxt("'Method' must be a string.") ;
00195 }
00196 if (mxGetString (optarg, buf, sizeof(buf))) {
00197 mexErrMsgTxt("Option argument too long.") ;
00198 }
00199 if (strcmp("lloyd", buf) == 0) {
00200 method_type = VL_IKM_LLOYD ;
00201 } else if (strcmp("elkan", buf) == 0) {
00202 method_type = VL_IKM_ELKAN ;
00203 } else {
00204 mexErrMsgTxt("Unknown 'Method' type.") ;
00205 }
00206 break ;
00207
00208 default :
00209 abort() ;
00210 }
00211 }
00212
00213
00214
00215
00216
00217 {
00218 VlHIKMTree *tree ;
00219 vl_uint32 *ids ;
00220 vl_uindex j;
00221 vl_size depth ;
00222
00223 tree = matlab_to_hikm (in[IN_TREE], method_type) ;
00224 depth = vl_hikm_get_depth (tree) ;
00225
00226 if (verb) {
00227 mexPrintf("vl_hikmeanspush: ndims: %d K: %d depth: %d\n",
00228 vl_hikm_get_ndims (tree),
00229 vl_hikm_get_K (tree),
00230 depth) ;
00231 }
00232
00233 out[OUT_ASGN] = mxCreateNumericMatrix (depth, N, mxUINT32_CLASS, mxREAL) ;
00234 ids = mxGetData (out[OUT_ASGN]) ;
00235
00236 vl_hikm_push (tree, ids, data, N) ;
00237 vl_hikm_delete (tree) ;
00238
00239 for (j = 0 ; j < N * depth ; j++) ids[j] ++ ;
00240 }
00241 }