Ось код, що використовує кластерний пакет Pillow і Scipy .
Для простоти я жорстко закодував ім'я файлу як "image.jpg". Зміна розміру зображення призначена для швидкості: якщо ви не проти зачекати, прокоментуйте виклик зміни розміру. При запуску на цьому зразку зображення синього перцю зазвичай кажуть, що домінуючим кольором є # d8c865, що приблизно відповідає яскраво-жовтуватій області внизу ліворуч від двох перців. Я кажу "зазвичай", оскільки алгоритм кластеризації має певний ступінь випадковості. Існують різні способи змінити це, але для ваших цілей це може підійти. (Перевірте параметри варіанту kmeans2 (), якщо вам потрібні детерміновані результати.)
from __future__ import print_function
import binascii
import struct
from PIL import Image
import numpy as np
import scipy
import scipy.misc
import scipy.cluster
NUM_CLUSTERS = 5
print('reading image')
im = Image.open('image.jpg')
im = im.resize((150, 150))
ar = np.asarray(im)
shape = ar.shape
ar = ar.reshape(scipy.product(shape[:2]), shape[2]).astype(float)
print('finding clusters')
codes, dist = scipy.cluster.vq.kmeans(ar, NUM_CLUSTERS)
print('cluster centres:\n', codes)
vecs, dist = scipy.cluster.vq.vq(ar, codes)
counts, bins = scipy.histogram(vecs, len(codes))
index_max = scipy.argmax(counts)
peak = codes[index_max]
colour = binascii.hexlify(bytearray(int(c) for c in peak)).decode('ascii')
print('most frequent is %s (#%s)' % (peak, colour))
Примітка: коли я розширюю кількість скупчень, щоб знайти з 5 до 10 або 15, це часто дає результати, які мають зеленуватий або синюватий відтінок. Враховуючи вхідне зображення, це теж розумні результати ... Я теж не можу сказати, який колір насправді є домінуючим у цьому зображенні, тому я не винен алгоритм!
Також невеликий бонус: збережіть зображення зменшеного розміру, використовуючи лише N найчастіших кольорів:
import imageio
c = ar.copy()
for i, code in enumerate(codes):
c[scipy.r_[scipy.where(vecs==i)],:] = code
imageio.imwrite('clusters.png', c.reshape(*shape).astype(np.uint8))
print('saved clustered image')