Python-Znajdź dominujący / najczęstszy kolor w obrazie
Szukam sposobu na znalezienie najbardziej dominującego koloru / tonu w obrazie za pomocą Pythona. Wystarczy średni odcień lub najczęstszy z RGB. Zajrzałem do biblioteki obrazowania Pythona i nie mogłem znaleźć niczego związanego z tym, czego szukałem w ich podręczniku, a także krótko w VTK.
Znalazłem jednak skrypt PHP, który robi to, czego potrzebuję, TUTAJ (login wymagany do pobrania). Skrypt wydaje się zmieniać rozmiar obrazu do 150*150, aby wydobyć dominantę colors= Jednak po tym jestem dość zagubiony. Rozważałem napisanie czegoś, co zmieniłoby Rozmiar obrazu na mały rozmiar, a następnie sprawdziłoby co drugi Piksel lub tak dla obrazu, chociaż wyobrażam sobie, że byłoby to bardzo nieefektywne (choć implementacja tego pomysłu jako modułu Pythona C może być pomysłem).
Jednak, po tym wszystkim, wciąż jestem zakłopotany. Więc zwracam się do ciebie. Czy istnieje łatwy i skuteczny sposób na znalezienie dominującego koloru na obrazie.
7 answers
Oto kod wykorzystujący pil i Pakiet klastra Scipy .
Dla uproszczenia zakodowałem na twardo nazwę pliku jako " image.jpg". Zmiana rozmiaru obrazu jest dla szybkości: jeśli nie masz nic przeciwko czekaniu, skomentuj połączenie zmiany rozmiaru. Po uruchomieniu tego przykładowego obrazu niebieskiej papryki zazwyczaj mówi się, że dominującym kolorem jest #d8c865, co odpowiada mniej więcej jasnożółtemu obszarowi w lewym dolnym rogu dwóch papryk. Mówię "zwykle", ponieważ grupowanie zastosowany algorytm ma pewien stopień losowości. Istnieją różne sposoby, aby to zmienić, ale dla Twoich celów może to dobrze pasować. (Sprawdź opcje w wariancie kmeans2 (), jeśli potrzebujesz deterministycznych wyników.)
import struct
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 = ''.join(chr(int(c)) for c in peak).encode('hex')
print 'most frequent is %s (#%s)' % (peak, colour)
Uwaga: kiedy zwiększam liczbę klastrów, aby znaleźć od 5 do 10 lub 15, często dawało to wyniki, które były zielonkawe lub niebieskawe. Biorąc pod uwagę obraz wejściowy, są to również rozsądne wyniki... Nie mogę też powiedzieć, który kolor jest naprawdę dominujący w tym obrazie, więc nie winię algorytmu!
Również mały bonus: Zapisz obraz o zmniejszonym rozmiarze tylko z N najczęstszych kolorów:
# 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'
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-12-03 19:11:57
Biblioteka obrazowania Pythona posiada metody getcolors na obiektach obrazu:
Im.getcolors () = > a list of (count, kolor) krotki lub brak
Myślę, że nadal możesz spróbować zmienić rozmiar obrazu przed tym i zobaczyć, czy działa lepiej.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2010-07-13 23:19:07
Możesz użyć PIL, aby wielokrotnie zmieniać rozmiar obrazu w dół o współczynnik 2 w każdym wymiarze, aż osiągnie 1x1. Nie wiem, jaki algorytm pil wykorzystuje do zmniejszania o Duże czynniki, więc przejście bezpośrednio do 1x1 w jednej zmianie rozmiaru może stracić informacje. Może nie jest najbardziej wydajny, ale da ci "średni" kolor obrazu.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2010-07-13 23:46:57
Jeśli nadal szukasz odpowiedzi, oto, co zadziałało dla mnie, choć niezbyt wydajne:
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)
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-01-23 18:59:51
Aby dodać do odpowiedzi Petera, jeśli pil daje Ci obraz z trybem " P "lub praktycznie dowolnym trybem, który nie jest "RGBA", musisz zastosować maskę Alfa, aby przekonwertować go na RGBA. Można to zrobić całkiem łatwo z:
if im.mode == 'P':
im.putalpha(0)
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-01-27 03:52:51
Poniżej znajduje się przykład oparty na C++ Qt, aby odgadnąć dominujący kolor obrazu. Możesz użyć PyQt i przetłumaczyć to samo Na odpowiednik Pythona.
#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();
}
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-01-17 07:44:29
Spróbuj Color-thief . Jest oparty na PIL
i działa świetnie.
Instalacja
pip install colorthief
Użycie
from colorthief import ColorThief
color_thief = ColorThief('/path/to/imagefile')
# get the dominant color
dominant_color = color_thief.get_color(quality=1)
Może również znaleźć paletę kolorów
palette = color_thief.get_palette(color_count=6)
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-08-26 09:01:25