Skip to content

Instantly share code, notes, and snippets.

@segiddins
Created December 16, 2012 03:20
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 segiddins/4302910 to your computer and use it in GitHub Desktop.
Save segiddins/4302910 to your computer and use it in GitHub Desktop.
Python script to return the dominant colors in an image, along with opening a webpage containing paint chips of them
#!/usr/bin/python
from collections import namedtuple
from math import sqrt
import random
import os
import sys
import time
from PIL import Image
Point = namedtuple('Point', ('coords', 'n', 'ct'))
Cluster = namedtuple('Cluster', ('points', 'center', 'n'))
filetoanalyze = sys.argv[1]
if len(sys.argv) > 2:
numcolors = int(sys.argv[2])
else:
numcolors = 3
def get_points(img):
points = []
w, h = img.size
for count, color in img.getcolors(w * h):
points.append(Point(color, 3, count))
return points
rtoh = lambda rgb: '#%s' % ''.join(('%02x' % p for p in rgb))
def colorz(filename, n=3):
img = Image.open(filename)
img.thumbnail((200, 200))
w, h = img.size
points = get_points(img)
clusters = kmeans(points, n, 1)
rgbs = [map(int, c.center.coords) for c in clusters]
return map(rtoh, rgbs)
def euclidean(p1, p2):
return sqrt(sum([
(p1.coords[i] - p2.coords[i]) ** 2 for i in range(p1.n)
]))
def calculate_center(points, n):
vals = [0.0 for i in range(n)]
plen = 0
for p in points:
plen += p.ct
for i in range(n):
vals[i] += (p.coords[i] * p.ct)
return Point([(v / plen) for v in vals], n, 1)
def kmeans(points, k, min_diff):
clusters = [Cluster([p], p, p.n) for p in random.sample(points, k)]
while 1:
plists = [[] for i in range(k)]
for p in points:
smallest_distance = float('Inf')
for i in range(k):
distance = euclidean(p, clusters[i].center)
if distance < smallest_distance:
smallest_distance = distance
idx = i
plists[idx].append(p)
diff = 0
for i in range(k):
old = clusters[i]
center = calculate_center(plists[i], old.n)
new = Cluster(plists[i], center, old.n)
clusters[i] = new
diff = max(diff, euclidean(old.center, new.center))
if diff < min_diff:
break
return clusters
colors = colorz(filetoanalyze, numcolors)
print colors
fobj_out = open("myFile.html", "w")
myFile = '''
<!DOCTYPE HTML>
<html>
<head>
<title>ImageColors</title>
<style>span {dispay: inline; width:185px; height:185px; float:left; margin:15px; padding:15px}</style>
</head>
<body>
<img src='%s' width="350px" height="350px" />
<div>
''' % (filetoanalyze)
for x in xrange(0, numcolors):
myFile += '''<span style='background-color: %s'>%s</span>''' % (colors[x], colors[x])
myFile += '''</div>
</body>
</html>
'''
fobj_out.write(myFile)
fobj_out.close()
os.system('open myFile.html')
time.sleep(4.0)
os.system('rm myFile.html')
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment