Created
November 30, 2019 05:44
-
-
Save sevagh/72c36817fe590db40501835620e59eb9 to your computer and use it in GitHub Desktop.
Count colors in an image
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/env python3 | |
from collections import Counter | |
import numpy | |
from PIL import Image | |
from webcolors import css3_hex_to_names, hex_to_rgb | |
from urllib.request import urlopen | |
import sys | |
import time | |
import matplotlib.pylab as plb | |
import matplotlib.pyplot as plt | |
plt.switch_backend('cairo') | |
plb.switch_backend('cairo') | |
BASEWIDTH = 50 | |
def plot_colorpalette_result(name, element_labels, element_fracs, element_color_names): | |
plb.figure(1, figsize=(10, 10)) | |
labels = element_labels | |
fracs = element_fracs | |
plb.pie(fracs, labels=labels, shadow=True, startangle=90, colors=element_color_names) | |
plb.title(name, bbox={'facecolor': '1', 'pad': 5}) | |
filename = '{0}.png'.format(time.strftime('%y%m%d%H%M%s')) | |
plb.savefig(filename) | |
def color_palette(path): | |
mc = _get_image_palette(urlopen(path)).most_common() | |
elements = {x[1]: x[0] for x in mc} | |
element_total = sum(elements.keys()) | |
elements = {int(k / element_total * 100): v for k, v in elements.items() | |
if k > element_total / 20} | |
element_labels = ['{0},{1}%'.format(v, k) for k, v in elements.items()] | |
plot_colorpalette_result(path, element_labels, list(elements.keys()), | |
list(elements.values())) | |
def _resize_image(image): | |
width, height = image.size | |
if width > BASEWIDTH: | |
wpercent = (BASEWIDTH / float(image.size[0])) | |
hsize = int((float(image.size[1]) * float(wpercent))) | |
return image.resize((BASEWIDTH, hsize), Image.ANTIALIAS) | |
return image | |
def _get_image_palette(path): | |
image = _resize_image(Image.open(path)) | |
data = numpy.asarray(image).reshape(numpy.prod(image.size), 3) | |
counter = Counter(tuple(map(tuple, data))) | |
color_names = [_get_closest_color(element) for element | |
in counter.elements()] | |
return Counter(color_names) | |
def _get_closest_color(c): | |
m = {((v[0] - c[0]) ** 2 + (v[1] - c[1]) ** 2 + (v[2] - c[2]) ** 2): k for | |
k, v in | |
{v: hex_to_rgb(k) for k, v in css3_hex_to_names.items()}.items()} | |
return m[min(m.keys())] | |
if __name__ == '__main__': | |
try: | |
color_palette(sys.argv[1]) | |
except IndexError: | |
print('Rerun with url as first arg', file=sys.stderr) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment