I'm working on a project that requires me to select "unique" colors for each item. At times there could be upwards of 400 items. Is there some way out there of selecting the 400 colors that differ the most? Is it as simple as just changing the RGB values by a fixed increment?
+2
A:
You could come up with an equal distribution of 400 colours by incrementing red, green and blue in turn by 34.
That is:
- You know you have three colour channels: red, green and blue
- You need 400 distinct combinations of R, G and B
- So on each channel the number of increments you need is the cube root of 400, i.e. about 7.36
- To span the range 0..255 with 7.36 increments, each increment must be about 255/7.36, i.e. about 34
Tim Robinson
2010-07-07 16:33:48
Would +1, but I ran out of upvotes. :(
mcandre
2010-07-07 16:37:12
pow(+1, 1./3.) upvotes would have sufficed
Tim Robinson
2010-07-07 16:43:09
A:
Probably HSL or HSV would be a better representations than RGB for this task.
You may find that changing the hue gives better variability perception to the eye, so adjust your increments in a way that for every X units changed in S and L you change Y (with Y < X) units of hue, and adjust X and Y so you cover the spectrum with your desired amount of samples.
bashflyng
2010-07-07 16:42:02
I'm trying to use this HSV method. This is what I've come up with http://pastebin.com/pDGZhBXB. Only problem is it doesn't create 400 unique colors. Any ideas?
blcArmadillo
2010-07-07 17:37:13
I'm not sure, but by giving it a quick look, looks like the problem is that hsv_to_rgb expects the three values to be between 0.0 and 1.0, while you are using degrees for H.http://docs.python.org/library/colorsys.html
bashflyng
2010-07-07 21:55:33
A:
Here is my final code. Hopefully it helps someone down the road.
from PIL import Image, ImageDraw
import math, colorsys, os.path
# number of color circles needed
qty = 400
# the lowest value (V in HSV) can go
vmin = 30
# calculate how much to increment value by
vrange = 100 - vmin
if (qty >= 72):
vdiff = math.floor(vrange / (qty / 72))
else:
vdiff = 0
# set options
sizes = [16, 24, 32]
border_color = '000000'
border_size = 3
# initialize variables
hval = 0
sval = 50
vval = vmin
count = 0
while count < qty:
im = Image.new('RGBA', (100, 100), (0, 0, 0, 0))
draw = ImageDraw.Draw(im)
draw.ellipse((5, 5, 95, 95), fill='#'+border_color)
r, g, b = colorsys.hsv_to_rgb(hval/360.0, sval/100.0, vval/100.0)
r = int(r*255)
g = int(g*255)
b = int(b*255)
draw.ellipse((5+border_size, 5+border_size, 95-border_size, 95-border_size), fill=(r, g, b))
del draw
hexval = '%02x%02x%02x' % (r, g, b)
for size in sizes:
result = im.resize((size, size), Image.ANTIALIAS)
result.save(str(qty)+'/'+hexval+'_'+str(size)+'.png', 'PNG')
if hval + 10 < 360:
hval += 10
else:
if sval == 50:
hval = 0
sval = 100
else:
hval = 0
sval = 50
vval += vdiff
count += 1
blcArmadillo
2010-07-08 12:10:00