void mexFunction(int nout, mxArray *out[], int nin, const mxArray *in[]) { enum {IN_I = 0, IN_S, IN_END} ; enum {OUT_J = 0} ; int opt ; int next = IN_END ; mxArray const *optarg ; int padding = VL_PAD_BY_CONTINUITY ; int kernel = GAUSSIAN ; int flags ; vl_size step = 1 ; int verb = 0 ; double sigma ; mxClassID classid ; mwSize M, N, K, M_, N_, ndims ; mwSize dims_ [3] ; mwSize const * dims ; /* ----------------------------------------------------------------- * Check the arguments * -------------------------------------------------------------- */ if (nin < 2) { mexErrMsgTxt("At least two input arguments required."); } else if (nout > 1) { mexErrMsgTxt("Too many output arguments."); } while ((opt = vlmxNextOption (in, nin, options, &next, &optarg)) >= 0) { switch (opt) { case opt_padding : { enum {buflen = 32} ; char buf [buflen] ; if (!vlmxIsString(optarg, -1)) { vlmxError(vlmxErrInvalidArgument, "PADDING argument must be a string.") ; } mxGetString(optarg, buf, buflen) ; buf [buflen - 1] = 0 ; if (vlmxCompareStringsI("zero", buf) == 0) { padding = VL_PAD_BY_ZERO ; } else if (vlmxCompareStringsI("continuity", buf) == 0) { padding = VL_PAD_BY_CONTINUITY ; } else { vlmxError(vlmxErrInvalidArgument, "PADDING must be either ZERO or CONTINUITY, was '%s'.", buf) ; } break ; } case opt_subsample : if (!vlmxIsPlainScalar(optarg)) { vlmxError(vlmxErrInvalidArgument, "SUBSAMPLE must be a scalar.") ; } step = *mxGetPr(optarg) ; if (step < 1) { vlmxError(vlmxErrInvalidArgument, "SUBSAMPLE must be not less than one.") ; } break ; case opt_kernel : { enum {buflen = 32} ; char buf [buflen] ; if (!vlmxIsString(optarg, -1)) { vlmxError(vlmxErrInvalidArgument, "KERNEL argument must be a string.") ; } mxGetString(optarg, buf, buflen) ; buf [buflen - 1] = 0 ; if (vlmxCompareStringsI("gaussian", buf) == 0) { kernel = GAUSSIAN ; } else if (vlmxCompareStringsI("triangular", buf) == 0) { kernel = TRIANGULAR ; } else { vlmxError(vlmxErrInvalidArgument, "Unknown kernel type '%s'.", buf) ; } break ; } case opt_verbose : ++ verb ; break ; default: abort() ; } } if (! vlmxIsPlainScalar(IN(S))) { vlmxError(vlmxErrInvalidArgument, "S must be a real scalar.") ; } classid = mxGetClassID(IN(I)) ; if (classid != mxDOUBLE_CLASS && classid != mxSINGLE_CLASS) { vlmxError(vlmxErrInvalidArgument, "I must be either DOUBLE or SINGLE.") ; } if (mxGetNumberOfDimensions(IN(I)) > 3) { vlmxError(vlmxErrInvalidArgument, "I must be either a two or three dimensional array.") ; } ndims = mxGetNumberOfDimensions(IN(I)) ; dims = mxGetDimensions(IN(I)) ; M = dims[0] ; N = dims[1] ; K = (ndims > 2) ? dims[2] : 1 ; sigma = * mxGetPr(IN(S)) ; if ((sigma < 0.01) && (step == 1)) { OUT(J) = mxDuplicateArray(IN(I)) ; return ; } M_ = (M - 1) / step + 1 ; N_ = (N - 1) / step + 1 ; dims_ [0] = M_ ; dims_ [1] = N_ ; if (ndims > 2) dims_ [2] = K ; OUT(J) = mxCreateNumericArray(ndims, dims_, classid, mxREAL) ; if (verb) { char const *classid_str = 0, *kernel_str = 0, *padding_str = 0 ; switch (padding) { case VL_PAD_BY_ZERO : padding_str = "with zeroes" ; break ; case VL_PAD_BY_CONTINUITY : padding_str = "by continuity" ; break ; default: abort() ; } switch (classid) { case mxDOUBLE_CLASS: classid_str = "DOUBLE" ; break ; case mxSINGLE_CLASS: classid_str = "SINGLE" ; break ; default: abort() ; } switch (kernel) { case GAUSSIAN: kernel_str = "Gaussian" ; break ; case TRIANGULAR: kernel_str = "triangular" ; break ; default: abort() ; } mexPrintf("vl_imsmooth: [%dx%dx%d] -> [%dx%dx%d] (%s, subsampling step %d)\n", N, M, K, N_, M_, K, classid_str, step) ; mexPrintf("vl_imsmooth: padding: %s\n", padding_str) ; mexPrintf("vl_imsmooth: kernel: %s\n", kernel_str) ; mexPrintf("vl_imsmooth: sigma: %g\n", sigma) ; mexPrintf("vl_imsmooth: SIMD enabled: %s\n", vl_get_simd_enabled() ? "yes" : "no") ; } /* ----------------------------------------------------------------- * Do the job * -------------------------------------------------------------- */ flags = padding ; flags |= VL_TRANSPOSE ; switch (classid) { case mxSINGLE_CLASS: _vl_imsmooth_smooth_f ((float*) mxGetPr(OUT(J)), M_, N_, (float const*) mxGetPr(IN(I)), M, N, K, kernel, sigma, step, flags) ; break ; case mxDOUBLE_CLASS: _vl_imsmooth_smooth_d ((double*) mxGetPr(OUT(J)), M_, N_, (double const*) mxGetPr(IN(I)), M, N, K, kernel, sigma, step, flags) ; break ; default: abort() ; } }
/** ------------------------------------------------------------------ ** @internal ** @brief MEX driver **/ void mexFunction (int nout, mxArray * out[], int nin, const mxArray * in[]) { vl_uint8 *data ; enum {IN_DATA = 0, IN_K, IN_NLEAVES, IN_END} ; enum {OUT_TREE = 0, OUT_ASGN} ; int M, N, K = 2, depth = 0 ; int opt ; int next = IN_END ; mxArray const *optarg ; int nleaves = 1 ; int method_type = VL_IKM_LLOYD ; int max_niters = 200 ; int verb = 0 ; VlHIKMTree* tree ; VL_USE_MATLAB_ENV ; /* ------------------------------------------------------------------ * Check the arguments * --------------------------------------------------------------- */ if (nin < 3) { mexErrMsgTxt ("At least three arguments required."); } else if (nout > 2) { mexErrMsgTxt ("Too many output arguments."); } if (mxGetClassID (in[IN_DATA]) != mxUINT8_CLASS) { mexErrMsgTxt ("DATA must be of class UINT8."); } if (! vlmxIsPlainScalar (in[IN_NLEAVES]) || (nleaves = (int) *mxGetPr (in[IN_NLEAVES])) < 1) { mexErrMsgTxt ("NLEAVES must be a scalar not smaller than 2.") ; } M = mxGetM (in[IN_DATA]); /* n of components */ N = mxGetN (in[IN_DATA]); /* n of elements */ if (! vlmxIsPlainScalar (in[IN_K]) || (K = (int) *mxGetPr (in[IN_K])) > N ) { mexErrMsgTxt ("Cannot have more clusters than data.") ; } data = (vl_uint8 *) mxGetPr (in[IN_DATA]) ; while ((opt = vlmxNextOption (in, nin, options, &next, &optarg)) >= 0) { char buf [1024] ; switch (opt) { case opt_verbose : ++ verb ; break ; case opt_max_niters : if (!vlmxIsPlainScalar(optarg) || (max_niters = (int) *mxGetPr(optarg)) < 1) { mexErrMsgTxt("MaxNiters must be not smaller than 1.") ; } 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() ; break ; } } /* --------------------------------------------------------------- * Do the job * ------------------------------------------------------------ */ depth = VL_MAX(1, ceil (log (nleaves) / log(K))) ; tree = vl_hikm_new (method_type) ; if (verb) { mexPrintf("hikmeans: # dims: %d\n", M) ; mexPrintf("hikmeans: # data: %d\n", N) ; mexPrintf("hikmeans: K: %d\n", K) ; mexPrintf("hikmeans: depth: %d\n", depth) ; } vl_hikm_set_verbosity (tree, verb) ; vl_hikm_init (tree, M, K, depth) ; vl_hikm_train (tree, data, N) ; out[OUT_TREE] = hikm_to_matlab (tree) ; if (nout > 1) { vl_uint *asgn ; int j ; out [OUT_ASGN] = mxCreateNumericMatrix (vl_hikm_get_depth (tree), N, mxUINT32_CLASS, mxREAL) ; asgn = mxGetData(out[OUT_ASGN]) ; vl_hikm_push (tree, asgn, data, N) ; for (j = 0 ; j < N*depth ; ++ j) asgn [j] ++ ; } if (verb) { mexPrintf("hikmeans: done.\n") ; } /* vl_hikm_delete (tree) ; */ }
/* driver */ void mexFunction(int nout, mxArray *out[], int nin, const mxArray *in[]) { enum { MANIP_STATE, RUN_GENERATOR } mode ; VlRand * rand ; VL_USE_MATLAB_ENV ; rand = vl_get_rand() ; /** ----------------------------------------------------------------- ** Check the arguments ** -------------------------------------------------------------- */ if (nout > 1) { vlmxError(vlmxErrTooManyInputArguments, NULL) ; } if (nin > 0 && ! mxIsNumeric(in[0])) { mode = MANIP_STATE ; } else { mode = RUN_GENERATOR ; } switch (mode) { case RUN_GENERATOR: { enum { maxNumDimensions = 30 } ; vl_size numDimensions = 2, n ; vl_uindex k ; mwSize dimensions [maxNumDimensions] = {1, 1} ; double * x ; if (nin > 1) { /* TWISTER(N1 N2 ...) style */ if (nin >= maxNumDimensions) { vlmxError(vlmxErrTooManyInputArguments, "Too many dimensions specified.") ; } for (k = 0 ; k < (unsigned)nin ; ++k) { if (! vlmxIsPlainScalar(in[k])) { vlmxError(vlmxErrInvalidArgument, "The %d-th argument is not a plain scalar.", k + 1) ; } if (mxGetScalar(in[k]) < 0) { vlmxError(vlmxErrInvalidArgument, "The %d-th argument is negative.", k + 1) ; } dimensions[k] = mxGetScalar(in[k]) ; } numDimensions = k ; } else if (nin == 1) { /* TWISTER([N1 N2 ...]) style */ if (! vlmxIsPlainVector(in[0], -1)) { vlmxError(vlmxErrInvalidArgument, "The argument is not a plain vector.") ; } x = mxGetPr(in[0]) ; n = mxGetNumberOfElements(in[0]) ; numDimensions = VL_MAX(2, n) ; if (numDimensions > maxNumDimensions) { vlmxError(vlmxErrInvalidArgument, "Too many dimensions specified.") ; } if (n == 1) { if (*x < 0) { vlmxError(vlmxErrInvalidArgument, "The specified dimension is negative.") ; } dimensions[0] = dimensions[1] = *x ; } else { for (k = 0 ; k < n ; ++k) { if (x[k] < 0) { vlmxError(vlmxErrInvalidArgument, "One of the specified dimensions is negative.") ; } dimensions[k] = x[k] ; } } } out[0] = mxCreateNumericArray (numDimensions, dimensions, mxDOUBLE_CLASS, mxREAL) ; n = mxGetNumberOfElements (out[0]) ; x = mxGetPr (out[0]) ; for (k = 0 ; k < n ; ++k) { x[k] = vl_rand_res53(rand) ; } } break ; case MANIP_STATE: { enum { buff_size = 32 } ; char buff [buff_size] ; /* check for 'state' string */ if (! vlmxIsString(in[0], -1) || mxGetString(in[0], buff, buff_size) || vl_string_casei_cmp ("state", buff) != 0 ) { vlmxError(vlmxErrInvalidArgument, NULL) ; } /* TWISTER('state') */ if (nin == 1) { vl_uindex i ; vl_uint32 * data ; out[0] = mxCreateNumericMatrix (625, 1, mxUINT32_CLASS, mxREAL) ; data = mxGetData(out[0]) ; for (i = 0 ; i < 624 ; ++i) data[i] = rand->mt[i] ; data[624] = (vl_uint32) rand->mti ; } else { if (vlmxIsPlainScalar(in[1])) { /* TWISTER('state', X) */ vl_uint32 x = (vl_uint32) mxGetScalar(in[1]) ; vl_rand_seed (rand, x) ; } else if (mxIsNumeric(in[1]) && mxGetClassID(in[1]) == mxUINT32_CLASS && mxGetNumberOfElements(in[1]) == 624+1 && ((vl_uint32 const*)mxGetData(in[1]))[624] <= 624 ) { /* TWISTER('state', STATE) */ vl_uindex i ; vl_uint32 * data = mxGetData(in[1]) ; for (i = 0 ; i < 624 ; ++i) rand->mt[i] = data[i] ; rand->mti = data [624] ; } else if (mxIsNumeric(in[1]) && mxGetClassID(in[1]) == mxDOUBLE_CLASS && mxGetNumberOfElements(in[1]) <= 624) { /* TWISTER('state', KEY) */ vl_uint32 key [624] ; double const * x = mxGetPr(in[1]) ; vl_size n = mxGetNumberOfElements(in[1]) ; vl_uindex k ; for (k = 0 ; k < n ; ++k) { key [k] = x [k] ; } vl_rand_seed_by_array (rand, key, n) ; } } } break ; default: abort() ; } }
void mexFunction(int nout, mxArray *out[], int nin, const mxArray *in[]) { enum {IN_DATA = 0, IN_END} ; enum {OUT_TREE = 0} ; int verbose = 0 ; int opt ; int next = IN_END ; mxArray const *optarg ; VlKDForest * forest ; void * data ; vl_size numData ; vl_size dimension ; mxClassID dataClass ; vl_type dataType ; int thresholdingMethod = VL_KDTREE_MEDIAN ; vl_size numTrees = 1 ; VL_USE_MATLAB_ENV ; /* ----------------------------------------------------------------- * Check the arguments * -------------------------------------------------------------- */ if (nin < 1) { vlmxError(vlmxErrInvalidArgument, "At least one argument required") ; } else if (nout > 2) { vlmxError(vlmxErrInvalidArgument, "Too many output arguments"); } dataClass = mxGetClassID(IN(DATA)) ; if (! vlmxIsMatrix (IN(DATA), -1, -1) || ! vlmxIsReal (IN(DATA))) { vlmxError(vlmxErrInvalidArgument, "DATA must be a real matrix ") ; } switch (dataClass) { case mxSINGLE_CLASS : dataType = VL_TYPE_FLOAT ; break ; case mxDOUBLE_CLASS : dataType = VL_TYPE_DOUBLE ; break ; default: vlmxError(vlmxErrInvalidArgument, "DATA must be either SINGLE or DOUBLE") ; } while ((opt = vlmxNextOption (in, nin, options, &next, &optarg)) >= 0) { char buffer [1024] ; switch (opt) { case opt_threshold_method : mxGetString (optarg, buffer, sizeof(buffer)/sizeof(buffer[0])) ; if (! vlmxIsString(optarg, -1)) { vlmxError(vlmxErrInvalidOption, "THRESHOLDMETHOD must be a string") ; } if (vl_string_casei_cmp(buffer, "median") == 0) { thresholdingMethod = VL_KDTREE_MEDIAN ; } else if (vl_string_casei_cmp(buffer, "mean") == 0) { thresholdingMethod = VL_KDTREE_MEAN ; } else { vlmxError(vlmxErrInvalidOption, "Unknown thresholding method %s", buffer) ; } break ; case opt_num_trees : if (! vlmxIsScalar(optarg) || (numTrees = mxGetScalar(optarg)) < 1) { vlmxError(vlmxErrInvalidOption, "NUMTREES must be not smaller than one") ; } break ; case opt_verbose : ++ verbose ; break ; } } data = mxGetData (IN(DATA)) ; numData = mxGetN (IN(DATA)) ; dimension = mxGetM (IN(DATA)) ; forest = vl_kdforest_new (dataType, dimension, numTrees) ; vl_kdforest_set_thresholding_method (forest, thresholdingMethod) ; if (verbose) { char const * str = 0 ; mexPrintf("vl_kdforestbuild: data %s [%d x %d]\n", vl_get_type_name (dataType), dimension, numData) ; switch (vl_kdforest_get_thresholding_method(forest)) { case VL_KDTREE_MEAN : str = "mean" ; break ; case VL_KDTREE_MEDIAN : str = "median" ; break ; default: abort() ; } mexPrintf("vl_kdforestbuild: threshold selection method: %s\n", str) ; mexPrintf("vl_kdforestbuild: number of trees: %d\n", vl_kdforest_get_num_trees(forest)) ; } /* ----------------------------------------------------------------- * Do job * -------------------------------------------------------------- */ vl_kdforest_build (forest, numData, data) ; if (verbose) { vl_uindex ti ; for (ti = 0 ; ti < vl_kdforest_get_num_trees(forest) ; ++ ti) { mexPrintf("vl_kdforestbuild: tree %d: depth %d, num nodes %d\n", ti, vl_kdforest_get_depth_of_tree(forest, ti), vl_kdforest_get_num_nodes_of_tree(forest, ti)) ; } } out[OUT_TREE] = new_array_from_kdforest (forest) ; vl_kdforest_delete (forest) ; }
/* 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) ; }
/* driver */ void mexFunction (int nout, mxArray * out[], int nin, const mxArray * in[]) { enum {IN_X = 0, IN_K, IN_END} ; enum {OUT_C = 0, OUT_I} ; int opt ; int next = IN_END ; mxArray const *optarg ; int M, N, K = 0 ; int err = 0 ; vl_uint *asgn = 0 ; vl_ikm_acc *centers = 0 ; vl_uint8 *data ; int method_type = VL_IKM_LLOYD ; int max_niters = 200 ; 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"); } M = mxGetM (in[IN_X]); /* n of components */ N = mxGetN (in[IN_X]); /* n of elements */ if (!vlmxIsPlainScalar (in[IN_K]) || (K = (int) *mxGetPr(in[IN_K])) < 1 || K > N ) { mexErrMsgTxt ("K must be a positive integer not greater than the number of data."); } while ((opt = vlmxNextOption (in, nin, options, &next, &optarg)) >= 0) { char buf [1024] ; switch (opt) { case opt_verbose : ++ verb ; break ; case opt_max_niters : if (!vlmxIsPlainScalar(optarg) || (max_niters = (int) *mxGetPr(optarg)) < 1) { mexErrMsgTxt("MaxNiters must be not smaller than 1.") ; } 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 method type.") ; } break ; default : abort() ; } } /* ------------------------------------------------------------------ * Do the job * --------------------------------------------------------------- */ 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("ikmeans: MaxInters = %d\n", max_niters) ; mexPrintf("ikmeans: Method = %s\n", method_name) ; } data = (vl_uint8*) mxGetPr(in[IN_X]) ; ikmf = vl_ikm_new (method_type) ; vl_ikm_set_verbosity (ikmf, verb) ; vl_ikm_set_max_niters (ikmf, max_niters) ; vl_ikm_init_rand_data (ikmf, data, M, N, K) ; err = vl_ikm_train (ikmf, data, N) ; if (err) mexWarnMsgTxt("ikmeans: possible overflow!") ; /* ------------------------------------------------------------------ * Return results * --------------------------------------------------------------- */ { out[OUT_C] = mxCreateNumericMatrix (M, K, mxINT32_CLASS, mxREAL) ; centers = mxGetData (out[OUT_C]) ; memcpy (centers, vl_ikm_get_centers (ikmf), sizeof(vl_ikm_acc) * M * K) ; } if (nout > 1) { int j ; out[OUT_I] = mxCreateNumericMatrix (1, N, mxUINT32_CLASS, mxREAL) ; asgn = mxGetData (out[OUT_I]) ; vl_ikm_push (ikmf, asgn, data, N) ; for (j = 0 ; j < N ; ++j) ++ asgn [j] ; } vl_ikm_delete (ikmf) ; if (verb) { mexPrintf("ikmeans: done\n") ; } }
void mexFunction(int nout, mxArray *out[], int nin, const mxArray *in[]) { enum {IN_DATA, IN_LABELS, IN_LAMBDA, IN_END} ; enum {OUT_MODEL = 0, OUT_BIAS, OUT_INFO} ; int verbose = 0 ; int opt ; int next = IN_END ; mxArray const *optarg ; mxArray *inputModel = NULL; VlSvmPegasos* svm = NULL ; vl_bool freeModel = VL_TRUE ; vl_size dataDimension ; vl_uint32* matlabPermutation ; void * data ; mxClassID dataClass ; vl_type dataType ; vl_size numSamples ; vl_uint32 * permutation = NULL ; vl_size permutationSize = 0 ; DiagnosticsDispatcher* disp ; VlSvmDatasetInnerProduct innerProduct = NULL ; VlSvmDatasetAccumulator accumulator = NULL ; /* maps */ VlSvmDatasetFeatureMap mapFunc = NULL ; /* Homkermap */ VlHomogeneousKernelType kernelType = VlHomogeneousKernelChi2 ; VlHomogeneousKernelMapWindowType windowType = VlHomogeneousKernelMapWindowRectangular ; double gamma = 1.0 ; int n = 0 ; double period = -1 ; VlSvmDataset* dataset ; vl_bool homkermap = VL_FALSE ; void * map = NULL ; VL_USE_MATLAB_ENV ; disp = (DiagnosticsDispatcher*) vl_malloc(sizeof(DiagnosticsDispatcher)) ; disp->diagnosticsHandle = NULL ; disp->callerRef = NULL ; disp->verbose = 0 ; /* ----------------------------------------------------------------- * Check the arguments * -------------------------------------------------------------- */ if (nin < 3) { vlmxError(vlmxErrInvalidArgument, "At least three arguments are required.") ; } else if (nout > 3) { vlmxError(vlmxErrInvalidArgument, "Too many output arguments."); } dataClass = mxGetClassID(IN(DATA)) ; if (! vlmxIsMatrix (IN(DATA), -1, -1) || ! vlmxIsReal (IN(DATA))) { vlmxError(vlmxErrInvalidArgument, "DATA must be a real matrix.") ; } data = mxGetData (IN(DATA)) ; dataDimension = mxGetM(IN(DATA)) ; numSamples = mxGetN(IN(DATA)) ; /* Get order of the HOMKERMAP, if used. */ while ((opt = vlmxNextOption (in, nin, options, &next, &optarg)) >= 0) { if (opt == opt_homkermap) { homkermap = VL_TRUE ; if (! vlmxIsPlainScalar(optarg)) { vlmxError(vlmxErrInvalidArgument, "N is not a scalar.") ; } n = *mxGetPr(optarg) ; if (n < 0) { vlmxError(vlmxErrInvalidArgument, "N is negative.") ; } } } next = IN_END ; if (! vlmxIsVector(IN(LABELS), numSamples)) { vlmxError(vlmxErrInvalidArgument, "LABELS is not a vector of dimension compatible with DATA.") ; } switch (dataClass) { case mxSINGLE_CLASS : dataType = VL_TYPE_FLOAT ; break ; case mxDOUBLE_CLASS : dataType = VL_TYPE_DOUBLE ; break ; default: vlmxError(vlmxErrInvalidArgument, "DATA must be either SINGLE or DOUBLE.") ; } if (mxGetClassID(IN(LABELS)) != mxINT8_CLASS) { vlmxError(vlmxErrInvalidArgument, "LABELS must be INT8.") ; } if (! vlmxIsPlainScalar(IN(LAMBDA))) { vlmxError(vlmxErrInvalidArgument, "LAMBDA is not a plain scalar.") ; } svm = vl_svmpegasos_new ((2*n + 1)*dataDimension,*mxGetPr(IN(LAMBDA))) ; while ((opt = vlmxNextOption (in, nin, options, &next, &optarg)) >= 0) { switch (opt) { case opt_bias_multiplier : if (!vlmxIsPlainScalar(optarg)) { vlmxError(vlmxErrInvalidArgument, "BIASMULTIPLIER is not a plain scalar.") ; } vl_svmpegasos_set_bias_multiplier(svm, *mxGetPr(optarg)) ; break ; case opt_max_iterations : if (!vlmxIsPlainScalar(optarg)) { vlmxError(vlmxErrInvalidArgument, "MAXITERATIONS is not a plain scalar.") ; } if (*mxGetPr(optarg) < 0) { vlmxError(vlmxErrInvalidArgument, "MAXITERATIONS is negative.") ; } vl_svmpegasos_set_maxiterations(svm, (vl_size) *mxGetPr(optarg)) ; break ; case opt_epsilon : if (!vlmxIsPlainScalar(optarg)) { vlmxError(vlmxErrInvalidArgument, "EPSILON is not a plain scalar.") ; } if (*mxGetPr(optarg) < 0) { vlmxError(vlmxErrInvalidArgument, "EPSILON is negative.") ; } vl_svmpegasos_set_epsilon(svm, (double) *mxGetPr(optarg)) ; break ; case opt_starting_iteration : if (!vlmxIsPlainScalar(optarg)) { vlmxError(vlmxErrInvalidArgument, "STARTINGITERATION is not a plain scalar.") ; } if (*mxGetPr(optarg) < 1) { vlmxError(vlmxErrInvalidArgument, "STARTINGITERATION is smaller than 1.") ; } vl_svmpegasos_set_iterations(svm, (vl_size) *mxGetPr(optarg) - 1) ; break ; case opt_starting_model : if (!vlmxIsVector(optarg, -1) || mxIsComplex(optarg) || mxGetClassID(optarg) != mxDOUBLE_CLASS) { vlmxError(vlmxErrInvalidArgument, "STARTINGMODEL is not a real vector.") ; } inputModel = mxDuplicateArray(optarg) ; vl_svmpegasos_set_model(svm,(double*) mxGetData(inputModel)) ; freeModel = VL_FALSE ; break ; case opt_starting_bias : if (!vlmxIsPlainScalar(optarg)) { vlmxError(vlmxErrInvalidArgument, "STARTINGBIAS is not a plain scalar.") ; } vl_svmpegasos_set_bias(svm, (double) *mxGetPr(optarg)) ; break ; case opt_permutation : if (!vlmxIsVector(optarg, -1) || mxIsComplex(optarg) || mxGetClassID(optarg) != mxUINT32_CLASS) { vlmxError(vlmxErrInvalidArgument, "PERMUTATION is not a UINT32 vector.") ; } permutationSize = mxGetNumberOfElements(optarg) ; permutation = mxMalloc(sizeof(vl_uint32) * permutationSize) ; matlabPermutation = mxGetData(optarg) ; { /* adjust indexing */ vl_uindex k ; for (k = 0 ; k < permutationSize ; ++k) { permutation[k] = matlabPermutation[k] - 1 ; if (permutation[k] >= numSamples) { vlmxError(vlmxErrInconsistentData, "Permutation indexes out of bounds: PERMUTATION(%d) = %d > %d = number of data samples.", k + 1, permutation[k] + 1, numSamples) ; } } } vl_svmpegasos_set_permutation(svm,permutation,permutationSize) ; break ; case opt_bias_learningrate : if (!vlmxIsPlainScalar(optarg)) { vlmxError(vlmxErrInvalidArgument, "BIASLEARNINGRATE is not a plain scalar.") ; } if (mxGetClassID(optarg) != mxDOUBLE_CLASS) { vlmxError(vlmxErrInvalidArgument, "BIASLEARNINGRATE must be double.") ; } vl_svmpegasos_set_bias_learningrate(svm, (double)*mxGetPr(optarg)) ; break ; case opt_diagnostic : if( !mxIsClass( optarg , "function_handle")) { mexErrMsgTxt("DIAGNOSTICSFUNCTION must be a function handle."); } disp->diagnosticsHandle = (mxArray*)(optarg) ; break ; case opt_diagnostic_caller_ref : disp->callerRef = (mxArray*)(optarg) ; break ; case opt_energy_freq : if (!vlmxIsPlainScalar(optarg)) { vlmxError(vlmxErrInvalidArgument, "ENERGYFREQ is not a plain scalar.") ; } vl_svmpegasos_set_energy_frequency (svm, (vl_size)*mxGetPr(optarg)) ; break ; case opt_verbose : ++ verbose ; disp->verbose = 1 ; break ; case opt_KINTERS: case opt_KL1: kernelType = VlHomogeneousKernelIntersection ; break ; case opt_KCHI2: kernelType = VlHomogeneousKernelChi2 ; break ; case opt_KJS: kernelType = VlHomogeneousKernelJS ; break ; case opt_period: if (! vlmxIsPlainScalar(optarg)){ vlmxError(vlmxErrInvalidArgument, "PERIOD is not a scalar.") ; } period = *mxGetPr(optarg) ; if (period <= 0) { vlmxError(vlmxErrInvalidArgument, "PERIOD is not positive.") ; } break ; case opt_gamma: if (! vlmxIsPlainScalar(optarg)){ vlmxError(vlmxErrInvalidArgument, "GAMMA is not a scalar.") ; } gamma = *mxGetPr(optarg) ; if (gamma <= 0) { vlmxError(vlmxErrInvalidArgument, "GAMMA is not positive.") ; } break ; case opt_window: if (! vlmxIsString(optarg,-1)){ vlmxError(vlmxErrInvalidArgument, "WINDOW is not a string.") ; } else { char buffer [1024] ; mxGetString(optarg, buffer, sizeof(buffer) / sizeof(char)) ; if (vl_string_casei_cmp("uniform", buffer) == 0) { windowType = VlHomogeneousKernelMapWindowUniform ; } else if (vl_string_casei_cmp("rectangular", buffer) == 0) { windowType = VlHomogeneousKernelMapWindowRectangular ; } else { vlmxError(vlmxErrInvalidArgument, "WINDOW=%s is not recognized.", buffer) ; } } break ; } } if (verbose) { mexPrintf("vl_pegasos: Lambda = %g\n", svm->lambda) ; mexPrintf("vl_pegasos: BiasMultiplier = %g\n", svm->biasMultiplier) ; mexPrintf("vl_pegasos: MaxIterations = %d\n", svm->maxIterations) ; mexPrintf("vl_pegasos: permutation size = %d\n", permutationSize) ; } switch (dataType) { case VL_TYPE_FLOAT : innerProduct = (VlSvmDatasetInnerProduct)&vl_svmdataset_innerproduct_f ; accumulator = (VlSvmDatasetAccumulator)&vl_svmdataset_accumulator_f ; break ; case VL_TYPE_DOUBLE: innerProduct = (VlSvmDatasetInnerProduct)&vl_svmdataset_innerproduct_d ; accumulator = (VlSvmDatasetAccumulator)&vl_svmdataset_accumulator_d ; break ; } dataset = vl_svmdataset_new(data,dataDimension) ; if (homkermap) { map = vl_homogeneouskernelmap_new (kernelType, gamma, n, period, windowType) ; mapFunc = (VlSvmDatasetFeatureMap)&vl_homogeneouskernelmap_evaluate_d ; vl_svmdataset_set_map(dataset,map,mapFunc,2*n + 1) ; } /* ----------------------------------------------------------------- * Do job * -------------------------------------------------------------- */ if (disp->diagnosticsHandle) { vl_svmpegasos_set_diagnostic (svm, (VlSvmDiagnostics)&diagnosticDispatcher, disp) ; } vl_svmpegasos_train (svm,dataset, numSamples,innerProduct, accumulator, (vl_int8 const *)mxGetData(IN(LABELS))) ; /* ----------------------------------------------------------------- * Output * -------------------------------------------------------------- */ if (nout >= 1) { double * tempBuffer ; mwSize dims[2] ; dims[0] = svm->dimension ; dims[1] = 1 ; out[OUT_MODEL] = mxCreateNumericArray(2, dims, mxDOUBLE_CLASS, mxREAL) ; tempBuffer = (double*) mxGetData(out[OUT_MODEL]) ; memcpy(tempBuffer,svm->model,svm->dimension * sizeof(double)) ; } if (nout >= 2) { double * tempBuffer ; mwSize dims[2] ; dims[0] = 1 ; dims[1] = 1 ; out[OUT_BIAS] = mxCreateNumericArray(2, dims, mxDOUBLE_CLASS, mxREAL) ; tempBuffer = (double*) mxGetData(out[OUT_BIAS]) ; *tempBuffer = svm->bias ; } if (nout == 3) { out[OUT_INFO] = createInfoStruct(svm) ; } if (homkermap) { vl_homogeneouskernelmap_delete(map); } vl_svmdataset_delete(dataset) ; vl_svmpegasos_delete(svm,freeModel) ; vl_free(disp) ; }
/** @brief MEX driver entry point **/ void mexFunction (int nout, mxArray * out[], int nin, const mxArray * in[]) { enum {IN_TREE = 0, IN_DATA, IN_END} ; enum {OUT_ASGN = 0} ; vl_uint8 const *data; int opt ; int next = IN_END ; mxArray const *optarg ; int N = 0 ; int method_type = VL_IKM_LLOYD ; int verb = 0 ; /* ----------------------------------------------------------------- * Check the arguments * -------------------------------------------------------------- */ if (nin < 2) mexErrMsgTxt ("At least two arguments required."); else if (nout > 1) mexErrMsgTxt ("Too many output arguments."); if (mxGetClassID (in[IN_DATA]) != mxUINT8_CLASS) { mexErrMsgTxt ("DATA must be of class UINT8"); } N = mxGetN (in[IN_DATA]); /* n of elements */ data = (vl_uint8 *) mxGetPr (in[IN_DATA]); 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() ; } } /* ----------------------------------------------------------------- * Do the job * -------------------------------------------------------------- */ { VlHIKMTree *tree ; vl_uint *ids ; int j; int depth ; tree = matlab_to_hikm (in[IN_TREE], method_type) ; depth = vl_hikm_get_depth (tree) ; if (verb) { mexPrintf("hikmeanspush: ndims: %d K: %d depth: %d\n", vl_hikm_get_ndims (tree), vl_hikm_get_K (tree), depth) ; } out[OUT_ASGN] = mxCreateNumericMatrix (depth, N, mxUINT32_CLASS, mxREAL) ; ids = mxGetData (out[OUT_ASGN]) ; vl_hikm_push (tree, ids, data, N) ; vl_hikm_delete (tree) ; for (j = 0 ; j < N*depth ; j++) ids [j] ++ ; } }