static VlHIKMNode * xcreate (VlHIKMTree *tree, mxArray const *mnode, int i) { mxArray const *mcenters, *msub ; VlHIKMNode *node ; vl_size M, node_K ; vl_uindex k ; /* sanity checks */ mcenters = mxGetField(mnode, i, "centers") ; msub = mxGetField(mnode, i, "sub") ; if (!mcenters || mxGetClassID (mcenters) != mxINT32_CLASS || !vlmxIsMatrix (mcenters, -1, -1) ) { mexErrMsgTxt("NODE.CENTERS must be a INT32 matrix.") ; } M = mxGetM (mcenters) ; node_K = mxGetN (mcenters) ; if (node_K > (vl_size)tree->K) { mexErrMsgTxt("A node has more clusters than TREE.K.") ; } if (tree->M < 0) { tree->M = M ; } else if (M != (vl_size)tree->M) { mexErrMsgTxt("A node CENTERS field has inconsistent dimensionality.") ; } node = mxMalloc (sizeof(VlHIKMNode)) ; node->filter = vl_ikm_new (tree->method) ; node->children = 0 ; vl_ikm_init (node->filter, mxGetData(mcenters), M, node_K) ; /* has any childer? */ if (msub) { /* sanity checks */ if (mxGetClassID (msub) != mxSTRUCT_CLASS) { mexErrMsgTxt("NODE.SUB must be a MATLAB structure array.") ; } if (mxGetNumberOfElements (msub) != node_K) { mexErrMsgTxt("NODE.SUB size must correspond to NODE.CENTERS.") ; } node-> children = mxMalloc (sizeof(VlHIKMNode *) * node_K) ; for(k = 0 ; k < node_K ; ++ k) { node-> children [k] = xcreate (tree, msub, k) ; } } return node ; }
static VlHIKMNode * xcreate(VlHIKMTree *tree, VlHIKMTree_python & inTree) { VlHIKMNode *node; int M, node_K, k; PyArrayObject * centers = (PyArrayObject *) inTree.centers; M = centers->dimensions[0]; node_K = centers->dimensions[1]; if (node_K > tree->K) { printf("%d / %d\n", node_K, tree->K); printf("A node has more clusters than TREE.K.\n"); } if (tree->M < 0) { tree->M = M; } else if (M != tree->M) { printf("%d / %d\n", M, tree->M); printf("A node CENTERS field has inconsistent dimensionality.\n"); } node = new VlHIKMNode; node->filter = vl_ikm_new(tree->method); node->children = 0; vl_ikm_init(node->filter, (vl_ikm_acc*) centers->data, M, node_K); /* has any childer? */ if (inTree.sub.size() > 0) { /* sanity checks */ if (inTree.sub.size() != node_K) { printf("%d, %d\n", (int)inTree.sub.size(), node_K); printf("NODE.SUB size must correspond to NODE.CENTERS.\n"); } node-> children = new VlHIKMNode*[node_K]; for (k = 0; k < node_K; ++k) { PyArrayObject * centers = (PyArrayObject *) inTree.sub[k].centers; node-> children[k] = xcreate(tree, inTree.sub[k]); } } return node; }
/* driver */ void mexFunction(int nout, mxArray *out[], int nin, const mxArray *in[]) { enum {IN_X=0,IN_C,IN_END} ; enum {OUT_ASGN=0} ; vl_uint* asgn ; vl_ikm_acc* centers ; vl_uint8* data ; int M,N,j,K=0 ; int opt ; int next = IN_END ; mxArray const *optarg ; int method_type = VL_IKM_LLOYD ; int verb = 0 ; VlIKMFilt *ikmf ; VL_USE_MATLAB_ENV ; /** ----------------------------------------------------------------- ** Check the arguments ** -------------------------------------------------------------- */ if (nin < 2) { mexErrMsgTxt("At least two arguments required.") ; } else if (nout > 2) { mexErrMsgTxt("Too many output arguments.") ; } if(mxGetClassID(in[IN_X]) != mxUINT8_CLASS) { mexErrMsgTxt("X must be of class UINT8") ; } if(mxGetClassID(in[IN_C]) != mxINT32_CLASS) { mexErrMsgTxt("C must be of class INT32") ; } M = mxGetM(in[IN_X]) ; /* n of components */ N = mxGetN(in[IN_X]) ; /* n of elements */ K = mxGetN(in[IN_C]) ; /* n of centers */ if( (int) mxGetM(in[IN_C]) != M ) { mexErrMsgTxt("DATA and CENTERS must have the same number of columns.") ; } while ((opt = vlmxNextOption (in, nin, options, &next, &optarg)) >= 0) { char buf [1024] ; switch (opt) { case opt_verbose : ++ verb ; break ; case opt_method : if (!vlmxIsString (optarg, -1)) { mexErrMsgTxt("'Method' must be a string.") ; } if (mxGetString (optarg, buf, sizeof(buf))) { mexErrMsgTxt("Option argument too long.") ; } if (strcmp("lloyd", buf) == 0) { method_type = VL_IKM_LLOYD ; } else if (strcmp("elkan", buf) == 0) { method_type = VL_IKM_ELKAN ; } else { mexErrMsgTxt("Unknown cost type.") ; } break ; default : abort() ; } } /** ----------------------------------------------------------------- ** Check the arguments ** -------------------------------------------------------------- */ if (verb) { char const * method_name = 0 ; switch (method_type) { case VL_IKM_LLOYD: method_name = "Lloyd" ; break ; case VL_IKM_ELKAN: method_name = "Elkan" ; break ; default : abort() ; } mexPrintf("ikmeanspush: Method = %s\n", method_name) ; mexPrintf("ikmeanspush: ndata = %d\n", N) ; } out[OUT_ASGN] = mxCreateNumericMatrix (1, N, mxUINT32_CLASS, mxREAL) ; data = (vl_uint8*) mxGetData (in[IN_X]) ; centers = (vl_ikm_acc*) mxGetData (in[IN_C]) ; asgn = (vl_uint*) mxGetData (out[OUT_ASGN]) ; ikmf = vl_ikm_new (method_type) ; vl_ikm_set_verbosity (ikmf, verb) ; vl_ikm_init (ikmf, centers, M, K) ; vl_ikm_push (ikmf, asgn, data, N) ; /* adjust for MATLAB indexing */ for(j = 0 ; j < N ; ++j) ++ asgn[j] ; vl_ikm_delete (ikmf) ; }
void ikm() { const vl_size data_dim = 2; const vl_size num_data = 1000; vl_uint8 data[data_dim * num_data] = { 0, }; for (vl_size i = 0; i < data_dim * num_data; ++i) data[i] = (vl_uint8)std::floor((((float)std::rand() / RAND_MAX) * 255) + 0.5f); // std::cout << "start processing ..." << std::endl; const vl_size num_clusters = 3; const VlIKMAlgorithms algorithm = VL_IKM_LLOYD; // VL_IKM_LLOYD, VL_IKM_ELKAN. const vl_size num_max_iterations = 100; VlIKMFilt *ikm = vl_ikm_new(algorithm); vl_ikm_set_max_niters(ikm, num_max_iterations); // initialization. #if 1 vl_ikm_init_rand(ikm, data_dim, num_clusters); #elif 0 vl_ikm_init_rand_data(ikm, data, data_dim, num_data, num_clusters); #else vl_ikm_acc init_centers[data_dim * num_clusters] = { 0, }; for (vl_size i = 0; i < data_dim * num_clusters; ++i) init_centers[i] = (vl_ikm_acc)std::floor((((float)std::rand() / RAND_MAX) * 255) + 0.5f); vl_ikm_init(ikm, init_centers, data_dim, num_clusters); #endif // training. if (-1 != vl_ikm_train(ikm, data, num_data)) { const vl_ikmacc_t *centers = vl_ikm_get_centers(ikm); for (int i = 0; i < num_clusters; ++i) { std::cout << '('; for (int j = 0; j < data_dim; ++j) { if (j) std::cout << ','; std::cout << (int)centers[i * data_dim + j]; } std::cout << ')' << std::endl; } // { vl_uint assignments[num_data] = { 0, }; vl_ikm_push(ikm, assignments, data, num_data); for (int i = 0; i < num_data; ++i) { std::cout << '('; for (int j = 0; j < data_dim; ++j) { if (j) std::cout << ','; std::cout << (int)data[i * data_dim + j]; // TODO [check] >> is it correct? } std::cout << ") => " << assignments[i] << std::endl; } } // testing. { vl_uint8 test_sample[data_dim] = { 0, }; for (vl_size i = 0; i < data_dim; ++i) test_sample[i] = (vl_uint8)std::floor((((float)std::rand() / RAND_MAX) * 255) + 0.5f); const vl_uint assignment = vl_ikm_push_one(centers, test_sample, data_dim, num_clusters); } } else { std::cerr << "an overflow may have occurred." << std::endl; } std::cout << "end processing ..." << std::endl; // if (ikm) { vl_ikm_delete(ikm); ikm = NULL; } }
PyObject * vl_ikmeanspush_python( PyArrayObject & inputData, PyArrayObject & centers, char * method, int verb) { // check types assert(inputData.descr->type_num == PyArray_UBYTE); assert(inputData.flags & NPY_FORTRAN); assert(centers.descr->type_num == PyArray_INT32); assert(centers.flags & NPY_FORTRAN); vl_ikm_acc* centers_data = (vl_ikm_acc *) centers.data; vl_uint8 * data = (vl_uint8 *) inputData.data; int j; npy_intp M, N, K = 0; VlIKMFilt *ikmf; /** ----------------------------------------------------------------- ** Check the arguments ** -------------------------------------------------------------- */ M = inputData.dimensions[0]; //mxGetM(in[IN_X]) ; /* n of components */ N = inputData.dimensions[1]; //mxGetN(in[IN_X]) ; /* n of elements */ K = centers.dimensions[1]; //mxGetN(in[IN_C]) ; /* n of centers */ if (centers.dimensions[0] != M) { printf("DATA and CENTERS must have the same number of columns."); } int method_type = VL_IKM_LLOYD; if (strcmp("lloyd", method) == 0) { method_type = VL_IKM_LLOYD; } else if (strcmp("elkan", method) == 0) { method_type = VL_IKM_ELKAN; } else { assert(0); } /** ----------------------------------------------------------------- ** Check the arguments ** -------------------------------------------------------------- */ if (verb) { char const * method_name = 0; switch (method_type) { case VL_IKM_LLOYD: method_name = "Lloyd"; break; case VL_IKM_ELKAN: method_name = "Elkan"; break; default: assert (0); } printf("ikmeanspush: Method = %s\n", method_name); printf("ikmeanspush: ndata = %d\n", (int)N); } PyArrayObject * asgn = (PyArrayObject *) PyArray_SimpleNew( 1, (npy_intp*) &N, PyArray_UINT32); unsigned int * asgn_data = (unsigned int*) asgn->data; ikmf = vl_ikm_new(method_type); vl_ikm_set_verbosity(ikmf, verb); vl_ikm_init(ikmf, centers_data, M, K); vl_ikm_push(ikmf, asgn_data, data, N); vl_ikm_delete(ikmf); return PyArray_Return(asgn); }