Ejemplo n.º 1
0
static VlHIKMNode * 
xmeans (VlHIKMTree *tree, 
        vl_uint8 const *data, 
        int N, int K, int height)
{
  VlHIKMNode *node = vl_malloc (sizeof(VlHIKMNode)) ;
  vl_uint     *ids = vl_malloc (sizeof(vl_uint) * N) ;

  node-> filter   = vl_ikm_new (tree -> method) ;    
  node-> children = (height == 1) ? 0 : vl_malloc (sizeof(VlHIKMNode*) * K) ;

  vl_ikm_set_max_niters (node->filter, tree->max_niters) ;
  vl_ikm_set_verbosity  (node->filter, tree->verb - 1  ) ;
  vl_ikm_init_rand_data (node->filter, data, tree->M, N, K) ;
  vl_ikm_train          (node->filter, data, N) ;
  vl_ikm_push           (node->filter, ids, data, N) ;
  
  /* recurse for each child */
  if (height > 1) {
    int k ;
    for (k = 0 ; k < K ; k ++) {
      int partition_N ;
      int partition_K ;
      vl_uint8 *partition ;
      
      partition = vl_hikm_copy_subset
        (data, ids, N, tree->M, k, &partition_N) ;
      
      partition_K = VL_MIN (K, partition_N) ;
      
      node->children [k] = xmeans
        (tree, partition, partition_N, partition_K, height - 1) ;
      
      vl_free (partition) ;

      if (tree->verb > tree->depth - height) {
        VL_PRINTF("hikmeans: branch at depth %d: %6.1f %% completed\n", 
                  tree->depth - height,
                  (double) (k+1) / K * 100) ;
      }
    }
  }
  
  vl_free (ids) ;
  return node ;
}
Ejemplo n.º 2
0
/* 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 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;
	}
}
Ejemplo n.º 4
0
PyObject * vl_ikmeans_python(
		PyArrayObject & inputData,
		int K,
		int max_niters,
		char * method,
		int verb)
{
	// check types
	assert(inputData.descr->type_num == PyArray_UBYTE);
	assert(inputData.flags & NPY_FORTRAN);

	npy_intp M, N;
	int err = 0;

	vl_uint8 * data;

	VlIKMFilt *ikmf;

	M = inputData.dimensions[0]; /* n of components */
	N = inputData.dimensions[1]; /* n of elements */

	// K must be a positive integer not greater than the number of data.
	assert(K>0 && K<=N);

	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);
	}

	/* ------------------------------------------------------------------
	 *                                                         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:
			assert (0);
		}
		printf("ikmeans: MaxInters = %d\n", max_niters);
		printf("ikmeans: Method    = %s\n", method_name);
	}

	data = (vl_uint8*) inputData.data;
	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)
		printf("ikmeans: possible overflow!");

	/* ------------------------------------------------------------------
	 *                                                       Return results
	 * --------------------------------------------------------------- */

	// allocate PyArrayObject for centers (column-majored)
	npy_intp dims[2];
	dims[0] = M;
	dims[1] = K;
	PyArrayObject * centers = (PyArrayObject*) PyArray_NewFromDescr(
		&PyArray_Type, PyArray_DescrFromType(PyArray_INT32),
		2, dims, NULL, NULL, NPY_F_CONTIGUOUS, NULL);

	// copy data
	int * centers_data = (int*) centers->data;
	memcpy(centers_data, vl_ikm_get_centers(ikmf), sizeof(vl_ikm_acc) * M * K);


	// allocate PyArrayObject for cluster assignment array
	PyArrayObject * asgn = (PyArrayObject*) PyArray_SimpleNew(
		1, (npy_intp*) &N, PyArray_UINT32);

	// copy data
	unsigned int * asgn_data = (unsigned int*) asgn->data;
	int j;
	vl_ikm_push(ikmf, (vl_uint*) asgn_data, data, N);

	// clean
	vl_ikm_delete(ikmf);

	if (verb) {
		printf("ikmeans: done\n");
	}

	// construct tuple to return both results: (regions, frames)
	PyObject * tuple = PyTuple_New(2);
	PyTuple_SetItem(tuple, 0, PyArray_Return(centers));
	PyTuple_SetItem(tuple, 1, PyArray_Return(asgn));

	return tuple;
}