Ask Your Question
0

OpenCV c++ K-Means Color Clustering

asked 2018-01-09 04:33:12 -0600

piowes86 gravatar image

Hi,

I found some interesting article about colour clustering with OpenCV and Python:

https://www.pyimagesearch.com/2014/05...

I am trying to convert that into c++. Until now without success. Did someone do that already?

Currently I have a problem with following lines:

// reshape the image to be a list of pixels image = image.reshape((image.shape[0] * image.shape[1], 3))

// cluster the pixel intensities clt = KMeans(n_clusters = args["clusters"]) clt.fit(image)

edit retag flag offensive close merge delete

Comments

1

you probably should not try to solve a c++ problem from a python blog ..

berak gravatar imageberak ( 2018-01-09 04:34:53 -0600 )edit

I know, but I need to perform image so like in provided link. Needed results in my situation is to obtain information about 3-4 main colours on the image with the information about quantity of the colour on the image.

piowes86 gravatar imagepiowes86 ( 2018-01-09 04:45:27 -0600 )edit
1

"Needed results in my situation is to obtain information about 3-4 main colours on the image with the information about quantity" -- can it be you wanted a histogram, instead, not clustering (which makes "artificial" centers ?

berak gravatar imageberak ( 2018-01-09 05:17:49 -0600 )edit

1 answer

Sort by ยป oldest newest most voted
2

answered 2018-01-09 04:48:10 -0600

berak gravatar image

assuming a 3channel, bgr image (CV_8UC3):

Mat ocv = ...

// convert to float & reshape to a [3 x W*H] Mat 
//  (so every pixel is on a row of it's own)
Mat data;
ocv.convertTo(data,CV_32F);
data = data.reshape(1,data.total());

// do kmeans
Mat labels, centers;
kmeans(data, 8, labels, TermCriteria(CV_TERMCRIT_ITER, 10, 1.0), 3, 
       KMEANS_PP_CENTERS, centers);

// reshape both to a single row of Vec3f pixels:
centers = centers.reshape(3,centers.rows);
data = data.reshape(3,data.rows);

// replace pixel values with their center value:
Vec3f *p = data.ptr<Vec3f>();
for (size_t i=0; i<data.rows; i++) {
   int center_id = labels.at<int>(i);
   p[i] = centers.at<Vec3f>(center_id);
}

// back to 2d, and uchar:
ocv = data.reshape(3, ocv.rows);
ocv.convertTo(ocv, CV_8U);
edit flag offensive delete link more

Comments

Thank you Berak for the code. I was trying to execute the code and I received the following error: The total width is not divisible by the new number of channels in function reshape . Do you know what can be the reason of that and how to solve that?

piowes86 gravatar imagepiowes86 ( 2018-01-09 05:10:15 -0600 )edit

you probably tried with a grayscale image as input

berak gravatar imageberak ( 2018-01-09 05:16:11 -0600 )edit

I was able to solve the problem I have changed centers.reshape(3,centers.rows); into centers.reshape(0,centers.rows); The results are like follow: https://ibb.co/e6nkBm (original image) https://ibb.co/bYTLcR (after perform). I do not convert image into grayscale. I strictly use your code.

piowes86 gravatar imagepiowes86 ( 2018-01-09 05:26:54 -0600 )edit

ok, that's the same, for a single channel image.

berak gravatar imageberak ( 2018-01-09 05:28:04 -0600 )edit

Question Tools

1 follower

Stats

Asked: 2018-01-09 04:33:12 -0600

Seen: 8,505 times

Last updated: Jan 09 '18