Exercise 3. K-means proccess
This example was based on the kmeans.cpp algorithm and answers to the proposed exercises at [agostinhobritojr.github.io]https://agostinhobritojr.github.io/tutorial/pdi/#_exerc%C3%ADcios_8).
The following steps were used to accomplish this effect:
What does this program do?
The k-means algorithm works according to the following steps:
- Choose k as the number of classes for the vectors xi of N samples, i = 1,2, ⋯, N.
- Choose m1, m2, ⋯, mk as initial approximations for the class centers.
- Sort each sample xi using, for example, a minimum distance classifier (Euclidean distance).
- Recalculate the averages mj using the result of the previous step.
- If the new averages are consistent (do not change considerably), finalize the algorithm. If not, recalculate the centers and redo the classification.
#include <opencv2/opencv.hpp>
#include <cstdlib>
#include <ctime>
using namespace cv;
int main( int argc, char** argv ){
for(int i = 0; i < 10; i++){
int nClusters = 20;
Mat labels;
int nRounds = 1;
Mat centers;
char name[30];
if(argc!=3){
exit(0);
}
Mat img = imread( argv[1], CV_LOAD_IMAGE_COLOR);
Mat samples(img.rows * img.cols, 3, CV_32F);
for( int y = 0; y < img.rows; y++ ){
for( int x = 0; x < img.cols; x++ ){
for( int z = 0; z < 3; z++){
samples.at<float>(y + x*img.rows, z) = img.at<Vec3b>(y,x)[z];
}
}
}
kmeans(samples,
nClusters,
labels,
TermCriteria(CV_TERMCRIT_ITER|CV_TERMCRIT_EPS, 10000, 0.0001),
nRounds,
KMEANS_RANDOM_CENTERS,
centers );
Mat labeled( img.size(), img.type() );
for( int y = 0; y < img.rows; y++ ){
for( int x = 0; x < img.cols; x++ ){
int indice = labels.at<int>(y + x*img.rows,0);
labeled.at<Vec3b>(y,x)[0] = (uchar) centers.at<float>(indice, 0);
labeled.at<Vec3b>(y,x)[1] = (uchar) centers.at<float>(indice, 1);
labeled.at<Vec3b>(y,x)[2] = (uchar) centers.at<float>(indice, 2);
}
}
sprintf(name, "test%d.jpg", i);
imwrite(name, labeled);
//waitKey( 0 );
}
}