Кластеризация OpenCV 1.1 K-средних в больших пространствах
Я пытаюсь написать пакет функций системы распознавания образов системы. Один шаг в алгоритме состоит в том, чтобы взять большее количество небольших патчей изображения (скажем, 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 ответа
Хотя я не знаком с "набором функций", вы рассматривали возможность использования таких функций, как угловые детекторы и SIFT?
Вы можете проверить 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;
в противном случае вы можете потерять память здесь.