Я ищу способ найти самый доминирующий цвет/тон в изображении с помощью Python. Или средний оттенок или наиболее распространенное из RGB сделают. Я посмотрел на библиотеку Python Imaging и не мог найти ничего касающегося, что я искал в их руководстве, и также кратко в VTK.
Я действительно однако находил Сценарий PHP, который делает то, в чем я нуждаюсь, здесь (вход в систему, требуемый загружать). Сценарий, кажется, изменяет размер изображения к 150*150, производит доминирующие цвета. Однако после этого я справедливо потерян. Я действительно рассматривал запись чего-то, что изменит размер изображения к небольшому размеру, затем проверяют любой пиксель или так поскольку это - изображение, хотя я предполагаю, что это было бы очень неэффективно (хотя реализовывая эту идею, поскольку модуль Python C мог бы быть идеей).
Однако после всего этого, я все еще озадачен. Таким образом, я обращаюсь к Вам, ТАКИМ ОБРАЗОМ. Есть ли легкий, эффективный способ найти доминирующий цвет в изображении.
Вот код, использующий 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)) # optional, to reduce time
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) # assign codes
counts, bins = scipy.histogram(vecs, len(codes)) # count occurrences
index_max = scipy.argmax(counts) # find most frequent
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 наиболее частыми цветами:
# bonus: save image using only the N most common colours
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')
Библиотека изображений Python имеет метод getcolors для объектов Image:
im.getcolors() => список (count, color) кортежей или None
Думаю, вы можете попробовать изменить размер изображения перед этим и посмотреть, будет ли результат лучше.
Вы можете использовать PIL для многократного уменьшения размера изображения с коэффициентом 2 в каждом измерении, пока оно не достигнет 1x1. Я не знаю, какой алгоритм использует PIL для масштабирования с большим коэффициентом, поэтому переход непосредственно к 1x1 при одном изменении размера может привести к потере информации. Возможно, это не самый эффективный вариант, но он даст вам «средний» цвет изображения.