Ask Your Question
0

how to get new center points in kmeans

asked 2014-11-04 06:57:01 -0600

canavaroski90 gravatar image

hi,

trying to get new center points of newly created clusters with kmeans function. applying kemeans function as below;

kmeans(tmpsp[1], 4, labels, TermCriteria(CV_TERMCRIT_EPS + CV_TERMCRIT_ITER, 10, 1.0/*CV_TERMCRIT_ITER, 1, 1.0*/), 3, KMEANS_RANDOM_CENTERS, newCenters);

and this is tmpsp[1] dataset (actually it is an image with the size of 91x53, and the type is CV_32F); image description

this is labels, it contains numbers from 0 to (cluster count-1), it is in size of 1x53;

image description

and this is newCenters, matrix in size of 94x53;

image description

1) how can i get centroids of found clusters? i need accurate x and y points for each clusters. 2) how can I give initial centroids?

thanks.

edit retag flag offensive close merge delete

Comments

what are you trying to achieve ?

kmeans will cluster row-vectors, not 2d (hmm points?circles?neighbourhoods?).


(btw, newCenters should come out as matrix in size of 91x4, no?)

berak gravatar imageberak ( 2014-11-04 07:17:57 -0600 )edit

did you want the center points of the 4 black areas ?

berak gravatar imageberak ( 2014-11-04 07:49:38 -0600 )edit

nope, trying to seperate white area in 4 section and find theirs centroids. however, as i understood, kmeans algorithm takes the 2D matrix as a complete feature vector set. in example, in my question 2D vector has been given as a parameter to kmeans function, and it is 91x53 matrix. so, kmeans recognizes it as 53 samples with 93 features and when it finishes its job, gives me newcenters which are calculated by looking 93 features of all 53 samples in complete vector set. that is why i'm getting newcenters matrix in sizes of 91x4 when i request for 4 clusters. if i can get the coordinates of all pixels whose value is 255, put those coordinates to a matrix and give it to kmeans, it will calculate me new points as well.

canavaroski90 gravatar imagecanavaroski90 ( 2014-11-04 08:07:30 -0600 )edit
1

so here is a new question; how can i get coordinates of all pixels whose value is 255 and write them into a new Mat object?

canavaroski90 gravatar imagecanavaroski90 ( 2014-11-04 08:08:10 -0600 )edit

2 answers

Sort by ยป oldest newest most voted
3

answered 2014-11-04 08:39:41 -0600

berak gravatar image

updated 2014-11-04 08:51:24 -0600

so, answer to the rephrased question:

"trying to seperate the white area into 4 section and find their centroids"


Mat coords;
for ( int i=0; i<tmpsp.rows; i++ )
for ( int j=0; j<tmpsp.cols; j++ )
{
    if ( tmpsp.at<uchar>(i,j) < 60 ) // some threshold
       continue;
    coords.push_back(Point(j,i));
}
coords = coords.reshape( 1, coords.cols/2 ); // n rows a 2 cols
coords.convertTo(coords , CV_32F);


Mat labels,centers;

kmeans(coords , 4, labels, TermCriteria(CV_TERMCRIT_EPS + CV_TERMCRIT_ITER, 10, 1.0/*CV_TERMCRIT_ITER, 1, 1.0*/), 3, KMEANS_RANDOM_CENTERS, centers);

cerr << centers.size() << endl;   
cerr << centers<< endl;
cerr << labels.size() << endl;

for (int i=0; i<4; i++) {
    circle(ocv,Point(centers.at<float>(i,0),centers.at<float>(i,1)),4,Scalar(200));
}

[2 x 4]
[26.261696, 15.105264;
  46.481853, 10.9375;
  72.73671, 30.278481;
  14.530172, 38.497845]
[1 x 2039]

image description

edit flag offensive delete link more

Comments

thank you for your response. actually i started to write a method exactly same with the one you suggested. however i wonder if there is any other (faster or one-line-code) method instead of writing 2 nested for loops? i mean a method which returns a vector contains the points which has a value that i interested.

canavaroski90 gravatar imagecanavaroski90 ( 2014-11-04 10:15:20 -0600 )edit

like: Mat coords = img.where(13); ? yea, that would be nice to have ;)

berak gravatar imageberak ( 2014-11-04 10:51:50 -0600 )edit

that would be nice to have :)

canavaroski90 gravatar imagecanavaroski90 ( 2014-11-04 11:02:04 -0600 )edit
1

answered 2014-11-04 07:34:50 -0600

You can get the centroid by passing an additional output parameter (exactly what are you are doing right now...)

Mat centers(clusterCount, 1, points.type());

kmeans(points, clusterCount, labels,
  TermCriteria( cv::TermCriteria::EPS+cv::TermCriteria::MAX_ITER, 10, 1.0),
  3, cv::KMEANS_PP_CENTERS, centers);

For setting the initial centroids, you can pass the KMEANS_USE_INITIAL_LABELS-flag. The centroids are then computed from your given labels. I don't know a direct way of setting the centroid.

edit flag offensive delete link more

Comments

thank you for your answer but know i recognize that kmeans is not working the way i think. i used to use matlab for fast prototyping in image process operations, however, opencv and matlab functions may differ occasionally. if i give all image to kmeans method in matlab it returns new centroids without an effort.

canavaroski90 gravatar imagecanavaroski90 ( 2014-11-04 08:12:23 -0600 )edit

Question Tools

Stats

Asked: 2014-11-04 06:57:01 -0600

Seen: 3,227 times

Last updated: Nov 04 '14