I'm trying to create an algorithm that will output a set of different RGB color values, that should be as distinct as possible. For Example:
following a set of 3 colors:
- (255, 0, 0) [Red]
- (0, 255, 0) [Green]
- (0, 0, 255) [Blue]
the next 3 colors would be:
- (255, 255, 0) [Yellow]
- (0, 255, 255) [Cyan]
- (255, 0, 255) [Purple]
The next colors should be in-between the new intervals. Basically, my idea is to traverse the whole color spectrum systematic intervals similar to this:
A set of 13 colors should include the color in between 1 and 7, continue that pattern infinitely.
I'm currently struggling to apply this pattern to an algorithm to RGB values as it does not seem trivial to me. I'm thankful for any hints that can point me to a solution.
Here is my attempt. You didn't specify a language, so I'll write it in Python (not optimized, so as to be easily translated to other languages)
The colors are first set all to grey, i.e., put in the center of a color cube, and then moved in the color cube in such a way as to hopefully maximize the minimum distance between colors.
To save CPU time the square of the distance is used instead of the distance itself, which would require the calculation of a square root.
To compensate for the different sensitivity of the cones in our eyes, we use different weights (
rw
,gw
andbw
) in the 3 color directions when calculating the Euclidean distance. This causes the color cube to effectively become a color cuboid.Colors are moved one at a time, by a maximum of 1 in each of the 3 directions, to one of the adjacent colors that maximizes the minimum distance from the other colors. By so doing, the global minimum distance is (approximately) maximized.
The “global move” phases are needed in order to overcome situations where no color would move, but forcing all colors to move to a position which is not much worse than their current one causes the whole to find a better configuration with the subsequent regular moves. This can best be seen with 3 colors and no global moves, setting
rw
,gw
andbw
all to1
: the configuration becomeswhile, by adding 2 global moves, the configuration becomes the expected one
The algorithm produces one of 8 solutions. The other 7 are produced by replacing
c
with255-c
, wherec
isr
,g
orb
, in all combinations.The algorithm makes a simplifying assumption regarding color “distances”. I don't know whether a warp of the color cuboid exists that would cause the perceived distance between 2 colors to be equal to the Euclidean distance. If there is, moving colors within this warp would produce better results.
I have not corrected for the monitor's gamma, because it's purpose is precisely that of altering the spacing of the brightness in order to compensate for the eyes' different sensitivity at high and low brightness. Of course, the screen gamma may not do this precisely, and a (screen dependent!) modification of the gamma would yield better results, but the standard gamma is a good starting point.
This is the output of the algorithm for 25 colors:
WARNING
After posting this answer I found the Wikipedia article on color difference. The weights I have used may be appropriate for the components' contribution to brightness, but not for the perception of color differences. Furthermore a better formula is available (without completely changing the color space), so I will have to fix these two aspects.