How to use kmeans clustering on a binary image in python?

Viewed 1210

I am trying to take binary masks say with two different people and everything else is black. Now I want to group each person into their own clusters using K-means so that I can eventually draw bounding boxes around them. Here is the code I have so far:

def kmeans(img):
  k_values = range(1, 5)
  pixels = np.float32(img.reshape(-1,1))
  criteria = (cv2.TERM_CRITERIA_EPS + cv2.TERM_CRITERIA_MAX_ITER, 10, 1.0)
  flags = cv2.KMEANS_PP_CENTERS
  min_ssd = 0
  for k in k_values:
    ssd,labels,centers = cv2.kmeans(pixels,k,None,criteria,10,flags)
    if k == 1 or ssd < min_ssd: #looking for elbow in graph
      min_ssd = ssd
      min_labels = labels 
      min_centers = centers

  return min_labels,min_centers

As it stands, this code is returning the centers as pixel values and not coordinates so I am losing the spatial information in the frame. I am not quite sure how to change this code in order to obtain the cluster center as a point in the image and be able to visualize the clusters.

Example photo

Edit: I have changed the approach, first I start with OpenCV's simpleblobdetector() to detect the centroids of each blob in the image. From here I am initializing the centroids with those values. I plan to update the code when I finish making the changes

Centroid detection

Final Code

def kmeans_helper(img, centroids):
  data = np.nonzero(img)
  data = tuple(zip(data[0],data[1]))
  data = np.asarray(data).reshape(-1,2)

  num_clusters = len(centroids)
  kmeans = KMeans(n_clusters = num_clusters, init = centroids, n_init = 1)
  kmeans.fit(data)
  centroids_array = np.uint8(kmeans.cluster_centers_)

  num_labels = np.unique(kmeans.labels_)
  clusters = [data[kmeans.labels_ == label] for label in num_labels]

  return clusters

I figured I would update my final code for anyone who might need this in the future.

0 Answers
Related