Python – поиск доминирующего / наиболее распространенного цвета в изображении

Я ищу способ найти наиболее доминирующий цвет / тон изображения с помощью python. Будет либо средний оттенок, либо самый распространенный из RGB. Я просмотрел библиотеку Python Imaging и не нашел ничего, что касалось того, что я искал в их руководстве, а также кратко в VTK.

Однако я нашел PHP-скрипт, который делает то, что мне нужно, здесь (для загрузки требуется логин). Сценарий, похоже, изменяет размер изображения до 150 * 150, чтобы вывести доминирующие цвета. Однако после этого я довольно потерян. Я подумал о том, чтобы написать что-то, что изменит размер изображения до небольшого размера, а затем проверит каждый пиксель или его изображение, хотя я предполагаю, что это будет очень неэффективно (хотя реализация этой идеи как модуля C python может быть идеей).

Однако, после всего этого, я все еще тупой. Поэтому я обращаюсь к вам, ТАК. Есть простой и эффективный способ найти доминирующий цвет в изображении.

  • python manage.py runningerver, shell, dbshell зависает на git-bash
  • Модуль, импортированный несколько раз
  • Tweedy Streaming API возвращает «Нет» для координат в твитах с поддержкой геоинформации
  • Анализ HTML с помощью BeautifulSoup
  • Ошибка python: ImportError: sys.meta_path - None, Python, вероятно, отключается
  • Как реализовать приложение Flask Dispatching by Path с WSGI?
  • Быстрый поиск коротких строк в Python
  • Не удалось установить matplotlib на Mac OS X
  • 6 Solutions collect form web for “Python – поиск доминирующего / наиболее распространенного цвета в изображении”

    Вот код, использующий кластер PIL и Scipy .

    Для простоты я жестко закодировал имя файла как «image.jpg». Изменение размера изображения для скорости: если вы не против ожидания, закомментируйте запрос изменения размера. При запуске на этом образце синего перца обычно говорят, что доминирующим цветом является # d8c865, что примерно соответствует ярко-желтоватой области в левом нижнем углу двух перцев. Я говорю «обычно», потому что используемый алгоритм кластеризации имеет определенную степень случайности. Существуют различные способы изменить это, но для ваших целей это может подойти хорошо. (Проверьте варианты в варианте kmeans2 (), если вам нужны детерминированные результаты.)

    import struct import Image 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 = scipy.misc.fromimage(im) shape = ar.shape ar = ar.reshape(scipy.product(shape[:2]), shape[2]) 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 = ''.join(chr(c) for c in peak).encode('hex') print 'most frequent is %s (#%s)' % (peak, colour) 

    Примечание: когда я увеличиваю количество кластеров, чтобы найти от 5 до 10 или 15, он часто давал результаты, которые были зеленоватыми или голубоватыми. Учитывая входное изображение, это тоже разумные результаты … Я не могу сказать, какой цвет действительно доминирует в этом изображении, поэтому я не ошибаюсь алгоритм!

    Также небольшой бонус: сохраните уменьшенное изображение только с N наиболее частыми цветами:

     # bonus: save image using only the N most common colours c = ar.copy() for i, code in enumerate(codes): c[scipy.r_[scipy.where(vecs==i)],:] = code scipy.misc.imsave('clusters.png', c.reshape(*shape)) print 'saved clustered image' 

    Библиотека изображений Python имеет метод getcolors для объектов Image:

    im.getcolors () => список (подсчет, цвет) кортежей или None

    Я думаю, вы все равно можете попробовать изменить размер изображения до этого и посмотреть, будет ли он работать лучше.

    Вы можете использовать PIL для многократного изменения размера изображения в 2 раза в каждом измерении до достижения 1×1. Я не знаю, какой алгоритм использует PIL для уменьшения масштаба большими факторами, поэтому переход непосредственно к 1×1 при одном изменении размера может потерять информацию. Он может быть не самым эффективным, но он даст вам «средний» цвет изображения.

    Чтобы добавить к ответу Питера, если PIL дает вам изображение с режимом «P» или почти любым режимом, который не является «RGBA», тогда вам нужно применить альфа-маску, чтобы преобразовать ее в RGBA. Вы можете сделать это довольно легко:

     if im.mode == 'P': im.putalpha(0) 

    Ниже приведен пример c ++ на основе Qt, чтобы угадать преобладающий цвет изображения. Вы можете использовать PyQt и переводить то же самое на эквивалент Python.

     #include <Qt/QtGui> #include <Qt/QtCore> #include <QtGui/QApplication> int main(int argc, char** argv) { QApplication app(argc, argv); QPixmap pixmap("logo.png"); QImage image = pixmap.toImage(); QRgb col; QMap<QRgb,int> rgbcount; QRgb greatest = 0; int width = pixmap.width(); int height = pixmap.height(); int count = 0; for (int i = 0; i < width; ++i) { for (int j = 0; j < height; ++j) { col = image.pixel(i, j); if (rgbcount.contains(col)) { rgbcount[col] = rgbcount[col] + 1; } else { rgbcount[col] = 1; } if (rgbcount[col] > count) { greatest = col; count = rgbcount[col]; } } } qDebug() << count << greatest; return app.exec(); } 

    Если вы все еще ищете ответ, вот что сработало для меня, хотя и не очень эффективно:

     from PIL import Image def compute_average_image_color(img): width, height = img.size r_total = 0 g_total = 0 b_total = 0 count = 0 for x in range(0, width): for y in range(0, height): r, g, b = img.getpixel((x,y)) r_total += r g_total += g b_total += b count += 1 return (r_total/count, g_total/count, b_total/count) img = Image.open('image.png') #img = img.resize((50,50)) # Small optimization average_color = compute_average_image_color(img) print(average_color) 
    Python - лучший язык программирования в мире.