Skip to content

Instantly share code, notes, and snippets.

@sevagh
Created November 30, 2019 05:44
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save sevagh/72c36817fe590db40501835620e59eb9 to your computer and use it in GitHub Desktop.
Save sevagh/72c36817fe590db40501835620e59eb9 to your computer and use it in GitHub Desktop.
Count colors in an image
#!/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