Ask Your Question
0

Comparing KMeans centers for the best match

asked 2015-07-14 15:32:53 -0600

albertJ gravatar image

updated 2015-07-14 17:11:18 -0600

I'm working on implementing the VZ classifier (http://www.robots.ox.ac.uk/~vgg/resea...), and am having problems creating the models.

The first stage is to cluster a large number of filter responses to generate a texton dictionary, where every texton is a kmeans cluster center.

Then i need to get filter responses from a test image then get a single kmeans cluster center from each response, marking what is the closest texton(archived cluster center) to the new center.

Then i'll display or store a histogram showing which textons were used and how frequently from the training images filter responses.

From what i've read labels seem promising, although i dont know i could input the whole texton database and work out which best fitted image.

Below is small bit of code i was using to try feeding the centers from one kmeans into the labels for a second kmeans on the same image. I was hoping that this could compare the cluster centers and show they're the same. (seemed logical at the time, have been stuck on this for a while..).



include "opencv2/core/core.hpp"
include "stdio.h"
include "string"
include "iostream"
include "opencv2/imgproc/imgproc.hpp"
include "opencv2/highgui/highgui.hpp"

using namespace cv; using namespace std;

Mat kmeansFunc(Mat samples, Mat labels, int clusterCount) { // KMeans parameters int attempts = 5; Mat centers= Mat::zeros(2,2,CV_32F); // Apply KMeans kmeans(samples, clusterCount, labels, TermCriteria(CV_TERMCRIT_ITER|CV_TERMCRIT_EPS, 10000, 0.0001), attempts, KMEANS_USE_INITIAL_LABELS, centers); return centers; }

Mat createSamples(Mat src, Mat labels, int clusterCount) { // Create sampleMat, same size as input image Mat samples(src.rows * src.cols, 1, CV_32F); // Copy across input image for (int y = 0; y < src.rows; y++) { for (int x = 0; x < src.cols; x++) { samples.at<float>(y, x) = src.at<float>(y, x); } } Mat labels1 = Mat::eye(samples.rows,samples.cols,CV_32S);

// Put combined Mat through kmeans return kmeansFunc(samples, labels1, clusterCount); }

int main(int argc, char** argv) {

/------------------------- Load Image ---------------------------/ Mat img;

if(argc !=2) { cout << "img path name not found. Exiting." << endl; return -1; }

cout << "importing File: " << argv[1] << endl; // Read in image Mat in = imread(argv[1], CV_LOAD_IMAGE_GRAYSCALE); // Equalise image equalizeHist(in, img); waitKey();

/--------------------- Cluster image --------------------------/ Mat labels, floatImg;

// Convert input image to a float img.convertTo(floatImg, CV_32F);

Mat centers3 = createSamples(floatImg, labels, 4); cout << "This is the cluster centers of the first kmeans: " << endl << centers3.at<float>(0) << endl; cout << "And the full cluster: " << endl << centers3 << endl; waitKey(); Mat centers1 = Mat::eye(floatImg.rows,floatImg.cols,CV_32S);

//centers3.convertTo(centers1,CV_32S);

Mat centers2 = createSamples(floatImg, centers1, 5); cout << "This is the cluster centers of the second kmeans: " << endl << centers3.at<float>(0) << endl; cout << "And the full cluster: " << endl << centers3 << endl;

//Mat centers3 = createSamples(floatImg, labels);

// FileStorage fs("clusterCenters.xml", FileStorage::WRITE); // fs << "clusters" << centers3; // fs.release(); // cout << "finished saving clusteres. Exiting." << endl;

return 0; }

Any help would be really appreciated. Thanks!

edit retag flag offensive close merge delete

Comments

imho, your kmeansFunc() and createSamples() look quite broken (if you'd run a debug build, you'd get a ton of runtime errors) better don't try to preallocate the centers(wrong shape, anyway) or use initial labels (Mat::eye is the wrong way to calculate them)

the input to kmeans is a Mat where each row is a flattened output from the filterbank convolution, so nImages*nConvolutions rows, and img.rows*img.cols columns.

then the output from kmeans(centers) will be a Mat with 10 rows and img.rows*img.cols columns, too.

pseudocode:

Mat kdata; // start empty
for each img from convolution:
      Mat flat = img.reshape(1,1);
      kdata.push_back(flat);

Mat labels,centers; // empty
kmeans(kdata, 10, labels, TermCriteria(), 5, KMEANS_PP_CENTERS, centers);
berak gravatar imageberak ( 2015-07-15 00:47:37 -0600 )edit

thanks berak, yeah i meant to clean it up, although haven't found a good debugger for atom yet.

-Interesting about kmeans, can i create a single set of clusters from several images, the pseudo code above give me an error about the matrix not being continuous. would a continuous matrix of several images give the same centers as if i blended the same images together and ran it through kmeans?

-Also the key point, is there a way to find the nearest cluster centre for an image from a previous set of cluster centres?

albertJ gravatar imagealbertJ ( 2015-07-15 08:27:20 -0600 )edit

1 answer

Sort by ยป oldest newest most voted
0

answered 2015-08-15 12:13:44 -0600

albertJ gravatar image

For anyone looking for an answer or hints on this or specifically about being able to cluster multiple images easily, the way i found was using parts of the Bag of Words classes in the c++ api for opencv.

BOWTrainer::add

specifically will allow you to push back as multiple Mat images easily and and then generate a set of cluster centers using:

BOWTrainer::cluster

Definitely better than messing around trying to cluster them with the traditional kmeans function.

I haven't yet found a good solution to matching the cluster centres with the the generated vocabulary yet, as the other BOW opencv classes as far as i can tell wont work when using filterbanks. So i'll update it when i find something, otherwise you can check my current implementation on github: https://github.com/albertJ32/multiCha...

edit flag offensive delete link more

Comments

it would be nice if you could upload some images showing actually what the code in github implements, and even better if you are willing to make a tutorial or something ;-)

theodore gravatar imagetheodore ( 2015-08-15 12:57:33 -0600 )edit

Hi, yeah i'll be happy to do that when i get some more time, it's for my masters thesis so am rushing to finish it by september.

albertJ gravatar imagealbertJ ( 2015-08-18 15:14:24 -0600 )edit

Question Tools

1 follower

Stats

Asked: 2015-07-14 15:32:53 -0600

Seen: 872 times

Last updated: Aug 15 '15