DescentBB http://www.descentbb.net/ 

Color wheel corrected for human discernment http://www.descentbb.net/viewtopic.php?f=7&t=21654 
Page 1 of 1 
Author:  Jeff250 [ Thu Dec 04, 2014 6:21 pm ] 
Post subject:  Color wheel corrected for human discernment 
I'm making for myself some hiking maps in the form of *.kml files that I can import into Google Earth. I wanted each hiking trail to have a different color, and so I assigned each trail a random color from the rainbow. Specifically, if there are n trails, then for each trail, I randomly choose a color (without replacement) from the sequence of colors printed by the following python function: Code: import colorsys def rainbow(n): for i in xrange(n): rgb = colorsys.hsv_to_rgb(float(i) / n, 1.0, 1.0) rgb = tuple(round(x * 255) for x in rgb) print '#%.2x%.2x%.2x' % rgb In this sequence, each color has approximately equidistant hue from its neighbors. In the maps I'm creating, most trails have many intersections and many other nearby trails in general. One thing I noticed is if two nearby trails colored in the purplishreddish part of the spectrum happened to intersect each other, it was difficult to tell the trails apart, whereas this problem didn't exist in other parts of the spectrum, such as the yellowishgreenish part. I suspect that human vision is better at discerning between hues in some parts of the spectrum versus others. So how would I write a function similar to the above that, instead of generating colors with equidistant hues, generates colors with hues with distance such that each hue is equally discernible from its neighbors? For instance, in such a sequence, I'd imagine there would be fewer reddishpurplish colors, since they need to be of greater hue distance to tell apart, whereas there would be more yellowishgreenish colors, since they don't need as much hue distance to tell apart. Another solution to the map problem in general is to try assign colors to trails not entirely randomly but such that trails that intersect each other or are otherwise nearby each other don't have similar colors, but I think that even if this solution were employed, coloring trails with the most easily discernible hues would still be valuable, for instance, for creating a map legend. Plus, this seems like an interesting problem that must have a known solution. But I haven't been able to come across anything so far. Any thoughts? 
Author:  Foil [ Fri Dec 05, 2014 10:32 am ] 
Post subject:  Re: Color wheel corrected for human discernment 
A few thoughts, in no particular order:

Author:  Jeff250 [ Thu Dec 11, 2014 3:10 pm ] 
Post subject:  Re: Color wheel corrected for human discernment 
I found that there are colorspaces such as CIELAB and CIELUV that are perceptually uniform, that is, the human perceptual difference between colors in these spaces is the euclidean distance between the colors. So one way to solve this problem would be to choose maximally equidistant points in these spaces, but I don't think this is easy, as these colorspaces don't have simple shapes. What I ended up returning to was the original problem of generating a perceptually uniform rainbow of n colors. First, I needed a perceptual distance metric. One such metric could be to just convert colors to the CIELAB colorspace and calculate their euclidean distance, but I ended up using the simpler metric proposed here: http://www.compuphase.com/cmetric.htm Using this distance metric, for a given n, I perform binary search over perceptual distances to find the perceptual distance that evenly divided the rainbow into n divisions. To find each successive hue with perceptual distance d from the previous, I use binary search over hues. Here are the results... Rainbow with linear hues: Attachment: rainbow.png [ 466 Bytes  Viewed 1150 times ] Rainbow with perceptually uniform hues: Attachment: perceptual.png [ 520 Bytes  Viewed 1150 times ] This approach seems to have shrunk the purplyreddish part of the spectrum, like I was hoping it would. It also seems to have shrunk the green and the blue parts of the spectrum too, which I hadn't noticed in my maps as being a problem, but looking at the original rainbow, it seems like this should be helpful too. Maybe a different distance metric would have even better results? Here's the code: Code: #!/usr/bin/env python from math import sqrt import sys BLACK = 0.0, 0.0, 0.0 WHITE = 1.0, 1.0, 1.0 def distance(rgb1, rgb2): r1, g1, b1 = rgb1 r2, g2, b2 = rgb2 rmean = (r1 + r2) / 2.0 rdiff = (r1  r2) * 256 gdiff = (g1  g2) * 256 bdiff = (b1  b2) * 256 rweight = 2 + rmean gweight = 4.0 bweight = 2 + (1.0  rmean) return sqrt(rweight * rdiff * rdiff + gweight * gdiff * gdiff + bweight * bdiff * bdiff) MAX_DIST = distance(BLACK, WHITE) def rgb_to_hex(rgb): return '#%.2x%.2x%.2x' % tuple(round(x * 255) for x in rgb) def hue_to_rgb(h): i = int(h * 6.0) f = h * 6.0  i g = 1.0  f i %= 6 if i == 0: return 1.0, f, 0.0 elif i == 1: return g, 1.0, 0.0 elif i == 2: return 0.0, 1.0, f elif i == 3: return 0.0, g, 1.0 elif i == 4: return f, 0.0, 1.0 else: # i == 5 return 1.0, 0.0, g def next_hue(h, desired_distance): h = max(0.0, min(1.0, h)) rgb1 = hue_to_rgb(h) # Perform binary search over hues to find hue with desired perceptual # distance from h... lo = h hi = min(1.0, h + 0.5) while hi  lo >= 1e12: mid = (lo + hi) / 2 rgb2 = hue_to_rgb(mid) dist = distance(rgb1, rgb2) if dist <= desired_distance: lo = mid if dist >= desired_distance: hi = mid return hi def rainbow(n): return [hue_to_rgb(float(i) / n) for i in xrange(n)] def perceptual_rainbow(n): n = max(0, n) # Perform binary search over perceptual distance to find perceptual # distance that evenly divides all hues into n divisions... hues = [0.0] * (n + 1) lo = 0.0 hi = MAX_DIST while hi  lo >= 1e12: mid = (lo + hi) / 2 for i in xrange(1, n + 1): h = next_hue(hues[i  1], mid) hues[i] = h if hues[n] == 1.0: hi = mid else: lo = mid return [hue_to_rgb(hues[i]) for i in xrange(n)] def usage(): sys.stderr.write('Usage: %s N\n' % sys.argv[0]) sys.exit(1) def main(): if len(sys.argv) != 2: usage() try: n = int(sys.argv[1]) except ValueError: usage() else: for rgb in perceptual_rainbow(n): print rgb_to_hex(rgb) if __name__ == '__main__': main() Example usage: Code: $ python rainbow.py 10
#ff0000 #ff7200 #ffe500 #78ff00 #00ff55 #00ffd9 #0091ff #001fff #9200ff #ff00a2 
Author:  snoopy [ Fri Dec 12, 2014 7:19 am ] 
Post subject:  Re: Color wheel corrected for human discernment 
Another idea/suggestion: Why not try to take advantage of the other dimensions in your color space? You would want to stay away from 0 saturation and 0 value, but if you treat spacing in a 3dimensional sense (humancorrected or no), you're crippling yourself by using only a single ring. 
Author:  Jeff250 [ Fri Dec 12, 2014 8:51 am ] 
Post subject:  Re: Color wheel corrected for human discernment 
One good way to do that if I knew how would be to choose maximally equidistant points in the CIELAB colorspace. It's just not clear to me how to do that though. As a heuristic though, I could, say, add 50% darkness to the oddnumbered colors on the generated rainbow, and see where that goes. 
Page 1 of 1  All times are UTC06:00 
Powered by phpBB © 2000, 2002, 2005, 2007 phpBB Group http://www.phpbb.com/ 