Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Python 3: Most common color in image kmeans data type match

I am trying to adapt some python 2.4 code to 3.5. I am trying to use the top answer from this thread: Python - Find dominant/most common color in an image, but it's giving me trouble. This author also had trouble, but different trouble Error with hex encode in Python 3.3

Specifically something to do with scipy and kmeans variable types? Here is the code and traceback. Your wisdom is appreciated! -S

import struct
from PIL import Image
import scipy
import scipy.misc
import scipy.cluster
import numpy as np

NUM_CLUSTERS = 3

print('reading image')
im = Image.open('image.jpg')
im = im.resize((150, 150))      # optional, to reduce time
ar = scipy.misc.fromimage(im)
shape = ar.shape
ar = ar.reshape(scipy.product(shape[:2]), shape[2])

print ('finding clusters')
print(ar)
print("Variable type:", type(ar))
codes, dist = scipy.cluster.vq.kmeans(ar, NUM_CLUSTERS)
print('cluster centres:\n', codes)

vecs, dist = scipy.cluster.vq.vq(ar, codes)         # assign codes
counts, bins = scipy.histogram(vecs, len(codes))    # count occurrences
index_max = scipy.argmax(counts)                    # find most frequent
peak = codes[index_max]

colour = ''.join(format(c, '02x') for c in peak).encode('hex_codec')
print ('most frequent is %s (#%s)' % (peak, colour))

and the traceback is:

=========== RESTART: /Users/splash/Dropbox/PY/image-dom-color.py ============
reading image
finding clusters
[[255 255 255]
 [255 255 255]
 [255 255 255]
 ..., 
 [255 255 255]
 [255 255 255]
 [255 255 255]]
Variable type: <class 'numpy.ndarray'>
Traceback (most recent call last):
  File "/Users/splash/Dropbox/PY/image-dom-color.py", line 20, in <module>
    codes, dist = scipy.cluster.vq.kmeans(ar, NUM_CLUSTERS)
  File "/Library/Frameworks/Python.framework/Versions/3.5/lib/python3.5/site-packages/scipy/cluster/vq.py", line 568, in kmeans
    book, dist = _kmeans(obs, guess, thresh=thresh)
  File "/Library/Frameworks/Python.framework/Versions/3.5/lib/python3.5/site-packages/scipy/cluster/vq.py", line 436, in _kmeans
    code_book, has_members = _vq.update_cluster_means(obs, obs_code, nc)
  File "scipy/cluster/_vq.pyx", line 347, in scipy.cluster._vq.update_cluster_means (scipy/cluster/_vq.c:4695)
TypeError: type other than float or double not supported
>>> 
like image 729
Plashkes Avatar asked Feb 08 '23 09:02

Plashkes


1 Answers

The stacktrace tells us that the only supported data types for scipy.cluster._vq.update_cluster_means() are float and double. Checking out scipy's source code confirms this:

def update_cluster_means(np.ndarray obs, np.ndarray labels, int nc):
    """
    The update-step of K-means. Calculate the mean of observations in each
    cluster.
    Parameters
    ----------
    obs : ndarray
        The observation matrix. Each row is an observation. Its dtype must be
        float32 or float64.
    ...

Source: _vq.pyx on GitHub

To solve your problem you first need to convert the input into a supported data type using numpy.ndarray.astype():

codes, dist = scipy.cluster.vq.kmeans(ar.astype(float), NUM_CLUSTERS)
# Or:       = scipy.cluster.vq.kmeans(ar.astype('double'), NUM_CLUSTERS)
like image 152
elmis Avatar answered Feb 12 '23 12:02

elmis