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.
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.stack.imgur.com/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.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.