All centers coincide on K-Means clustering

Viewed 368

I am trying to apply K-Means through the following code-snippet in Python. Basically, the arr is a numpy array having values in three columns (Data with Multiple Features that I want to cluster). Here, I have used the following values: cv.TERM_CRITERIA_EPS = 1.0, cv.TERM_CRITERIA_MAX_ITER = 10 and attempts = 10. (as per the default values in the OpenCV documnetation link above).

To be specific, my three column arr is a RGB image, that is reshaped such that each column represents a color channel.

import cv2
import numpy as np 

Z = np.float32(arr)
criteria = (cv2.TERM_CRITERIA_EPS + cv2.TERM_CRITERIA_MAX_ITER, 10, 1.0)
ret, label, center = cv2.kmeans(Z, 4, None, criteria, 10, cv2.KMEANS_RANDOM_CENTERS)
labelToUse = (label.flatten()).astype('int32')
centerToUse = center.astype('float64')

While this gives me perfect results 70% of the time, but in 30% of the time I'm experiencing a weird case, as in the picture below (left one is centerToUse, right one is labelToUse). That is, all my cluster centers are (0, 0, 0), while labels are 0 for all the data points, except the last three (3, 2 and 1 respectively). Also, for the same arr, in some runs this abnormal case arises while in others, the results are just perfect.

enter image description here

Can anyone suggest me, about what should be my approach to eliminate this abnormality. I want to get decent results from K-Means each time, and not wait for good fortune. Also (don't know though whether this is relevant or not here), the situation is same in the scikit-learn representation of K-Means. This improves a bit if I increase n_init and max_iter to 30 and 300 respectively, but still persists. K-Means++ initialization also does not help.

EDIT: Based on the comment of @dhanushka, I recorded the compactness value on using cv2.KMEANS_PP_CENTERS. It came as follows (picture below), i.e. compactness = 61555894.92789865 when the output is perfect, while compactness = 0.0 for the 'weird' case (all centers at (0,0,0)). Possible that it exceeds the limit for the data-type.

enter image description here

Any leads in this issue will be highly appreciated.

1 Answers

Your code works fine for me every time:

import cv2
import numpy as np 

arr=cv2.imread('F:/ImagesForTest/lena.jpg')
Z = np.float32(arr)
criteria = (cv2.TERM_CRITERIA_EPS + cv2.TERM_CRITERIA_MAX_ITER, 10, 1)
ret, label, center = cv2.kmeans(Z, 4, None, criteria, 10, cv2.KMEANS_RANDOM_CENTERS)
labelToUse = (label.flatten()).astype('uint8')
centerToUse = center.astype('float64')
print(ret)
print(labelToUse)
print(centerToUse)

output is always looks like this:

746189834.28125
[0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2
 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2
 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2
 2 2 2 2 2 2 2 2 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3
 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3
 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3
 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3
 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3
 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3
 3 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1]
[[111.20652008 134.6521759  228.45652771 ...  76.47826385  51.76087189
  126.43478394]
 [ 62.84615707  27.25000191  92.94231415 ...  76.61538696  51.42308044
  130.98077393]
 [ 78.15841675  65.23762512 168.42573547 ... 122.78217316 136.54455566
  209.80197144]
 [ 78.06511688  57.17674255 149.40930176 ... 133.32092285 150.96278381
  207.73487854]]
Related