0

Here is a figure from which I want to count the number of objects from each color. What is a simple way of doing this, without using opencv perhaps?

[Edit 2]: The approach I have tried is the following: (1) Colored objects count

from PIL import Image
im = Image.open('./colored-polka-dots.png').getcolors()
im.sort(key=lambda k: (k[0]), reverse=True)
print('Top 5 colors: {}'.format((im[:5])))

# View non-background colors
color_values = []
for color in im[1:5]:
    color_values.append(color[1])
    arr = np.asarray(color[1]).reshape(1,1,4).astype(np.uint8)
    plt.imshow(arr)
    plt.show() # get top 4 frequent colors as green,blue,pink,ornage

# Create a dict of color names and their corressponding rgba values
color_dict = {}
for color_name,color_val in zip(['green','blue','pink','orange'],color_values):
    color_dict[color_name] = color_val

# Make use of ndimage.measurement.labels from scipy 
# to get the number of distinct connected features that satisfy a given threshold
for color_name,color_val in color_dict.items():
    b = ((img[:,:,0] ==color_val[0]) * (img[:,:,1] ==color_val[1]) * (img[:,:,2] ==color_val[2]))*1
    labeled_array, num_features = scipy.ndimage.measurements.label(b.astype('Int8'))
    print('Color:{} Count:{}'.format(color_name,num_features))

> Output:

orange: 288

green: 288

pink: 288

blue: 288

Although this achieves the purpose, I want to know if there is a more efficient and elegant way of solving this problem.

4
  • 4
    Can you show us what you have tried so far? Commented Jul 11, 2017 at 20:08
  • 1
    This post tells how to find the count of coloured objects using just numpy/scipy. You can modify this for your purpose Commented Jul 11, 2017 at 20:12
  • possible duplicate of this. The solution here might help Commented Jul 11, 2017 at 20:27
  • @Professor_Joykill, I have added my solution. Could you suggest improvements? Commented Jul 11, 2017 at 22:10

1 Answer 1

6

Here's a simpler solution based on scikit-image:

Code:

import numpy as np
from skimage import io, morphology, measure
from sklearn.cluster import KMeans

img = io.imread('https://i.sstatic.net/du0XZ.png')

rows, cols, bands = img.shape
X = img.reshape(rows*cols, bands)

kmeans = KMeans(n_clusters=5, random_state=0).fit(X)
labels = kmeans.labels_.reshape(rows, cols)

for i in np.unique(labels):
    blobs = np.int_(morphology.binary_opening(labels == i))
    color = np.around(kmeans.cluster_centers_[i])
    count = len(np.unique(measure.label(blobs))) - 1
    print('Color: {}  >>  Objects: {}'.format(color, count))

Output:

Color: [ 254.  253.  253.  255.]  >>  Objects: 1
Color: [ 255.  144.   36.  255.]  >>  Objects: 288
Color: [  39.  215.  239.  255.]  >>  Objects: 288
Color: [ 255.   38.  135.  255.]  >>  Objects: 288
Color: [ 192.  231.   80.  255.]  >>  Objects: 288

Remarks:

  • I've clustered colors through KMeans to make the program robust to slight variations in pixel colors.

  • The RGB coordinates of the cluster centers have been rounded through around just for visualization purposes.

  • I've also performed an opening operation through binary_opening in order to get rid of isolated pixels.

  • It is necessary to subtract 1 from the number of labels yielded by label to take into account only those connected regions with the considered color label.

  • The first line of the output obviously corresponds to the white background.

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.