Comparing KMeans centers for the best match
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!
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, andimg.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:
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?