Кластеризация OpenCV 1.1 K-средних в больших размерных пространствах - PullRequest
2 голосов
/ 27 июня 2010

Я пытаюсь написать пакет функций системы распознавания образов системы.Один шаг в алгоритме состоит в том, чтобы взять большее количество небольших патчей изображения (скажем, 7x7 или 11x11 пикселей) и попытаться сгруппировать их в группы, которые выглядят одинаково.Я получаю свои патчи из изображения, превращаю их в серые патчи изображения с плавающей точкой, а затем пытаюсь заставить cvKMeans2 кластеризовать их для меня.Я думаю, что у меня проблемы с форматированием входных данных, так что KMeans2 возвращает согласованные результаты.Раньше я использовал KMeans для 2D и 3D кластеризации, но 49D кластеризация кажется другим зверем.

Я продолжаю получать значения мусора для возвращаемого вектора кластеров, так что, очевидно, это проблема типа мусора в / мусора.Кроме того, алгоритм работает намного быстрее, чем я думаю, для такого огромного набора данных.

В приведенном ниже коде прямая memcpy - это только моя последняя попытка получить входные данные в правильном формате, я потратил некоторое время на использование встроенных функций OpenCV, но это сложно, когда ваш базовый тип - CV_32FC (49).

Может ли алгоритм KMeans OpenCV 1.1 поддерживать этот вид многомерного анализа?

Кто-нибудь знает правильный метод копирования из изображений во входную матрицу K-Means?

Может ли кто-нибудь указать мне бесплатный алгоритм KMeans не-GPL, который я могу использовать вместо этого?

Это не лучший код, поскольку я просто пытаюсь заставить вещи работать сейчас:

    std::vector<int> DoKMeans(std::vector<IplImage *>& chunks){
 // the size of one image patch, CELL_SIZE = 7
 int chunk_size = CELL_SIZE*CELL_SIZE*sizeof(float);
 // create the input data, CV_32FC(49) is 7x7 float object (I think)
 CvMat* data = cvCreateMat(chunks.size(),1,CV_32FC(49) );


 // Create a temporary vector to hold our data
 // we'll copy into the matrix for KMeans
 int rdsize = chunks.size()*CELL_SIZE*CELL_SIZE;
 float * rawdata = new float[rdsize];

 // Go through each image chunk and copy the 
 // pixel values into the raw data array.
 vector<IplImage*>::iterator iter;
 int k = 0;
 for( iter = chunks.begin(); iter != chunks.end(); ++iter )
 {

  for( int i =0; i < CELL_SIZE; i++)
  {
   for( int j=0; j < CELL_SIZE; j++)
   {
    CvScalar val;
    val = cvGet2D(*iter,i,j);
    rawdata[k] = (float)val.val[0];
    k++;
   }

  }
 }

 // Copy the data into the CvMat for KMeans
 // I have tried various methods, but this is just the latest.
 memcpy( data->data.ptr,rawdata,rdsize*sizeof(float));

 // Create the output array
 CvMat* results = cvCreateMat(chunks.size(),1,CV_32SC1);

 // Do KMeans
 int r = cvKMeans2(data, 128,results, cvTermCriteria(CV_TERMCRIT_EPS+CV_TERMCRIT_ITER, 1000, 0.1));

 // Copy the grouping information to our output vector
 vector<int> retVal;
 for( int y = 0; y < chunks.size(); y++ )
 {
  CvScalar cvs = cvGet1D(results, y);
  int g =  (int)cvs.val[0];
  retVal.push_back(g);
 }

 return retVal;}

Заранее спасибо!

Ответы [ 2 ]

0 голосов
/ 30 июня 2010

Несмотря на то, что я не знаком с «набором функций», вы рассматривали возможность использования характерных точек, таких как угловые детекторы и SIFT?

0 голосов
/ 27 июня 2010

Возможно, вы захотите проверить http://bonsai.ims.u -tokyo.ac.jp / ~ mdehoon / software / cluster / для другого пакета кластеризации с открытым исходным кодом.

Использование memcpy выглядит следующим образомПодозреваю, потому что когда вы делаете:

 int rdsize = chunks.size()*CELL_SIZE*CELL_SIZE;

Если CELL_SIZE и chunks.size () очень велики, вы создаете что-то большое в rdsize.Если это больше, чем наибольшее хранимое целое число, у вас может быть проблема.

Вы хотите изменить «чанки» в этой функции?Я предполагаю, что это не так, так как это проблема K-средних.

Поэтому попробуйте перейти по ссылке к const здесь.(И, вообще говоря, это то, что вы хотите делать)

, поэтому вместо:

std::vector<int> DoKMeans(std::vector<IplImage *>& chunks)

это будет:

std::vector<int> DoKMeans(const std::vector<IplImage *>& chunks)

Также в этом случаелучше использовать static_cast, чем старое приведение в стиле c.(например, static_cast (переменная), а не (переменная)).

Также вы можете удалить «rawdata»:

 float * rawdata = new float[rdsize];

можно удалить с помощью:

delete[] rawdata;

в противном случае у вас может быть утечка памяти.

...