4

I'm using a graphing package that can draw lines of color (255,255,255). So basically what I'm doing is (Random.Next(0,255),Random.Next(0,255),Random.Next(0,255)) to generate a color each time a line is added.

This is all well and good, but sometimes, I get colors that look very similar, making it difficult for the user to discern which data corresponds to which line.

Is there a more clever way to generate random and unique colors in the (255,255,255) format?

sooprise
  • 22,657
  • 67
  • 188
  • 276
  • By only generating values for one or two of the RGB triples and leaving the other two or one at zero, you will generate saturated colors -- colors without any gray in them. Further limit your random selection to the 64-255 range so that the colors are light enough to distinguish, and you should be well on the way to keeping colors distinguishable, though without a better algorithm (like those below), there's no guarantees. – Brenda Holloway Jun 28 '10 at 19:20

8 Answers8

13

A better option is to typically generate a random hue, and the convert the hue to an RGB color using an HSL or HSV color (with that hue). By using a random "hue" instead of random color, you'll get much more variation in your colors. You can also randomize the other components (saturation/value, etc), if you need even more variation.

See Wikipedia for details on working in colors using HSV/HSL, including how to convert HSV to RGB.

Reed Copsey
  • 554,122
  • 78
  • 1,158
  • 1,373
  • How is it more variant? A random hue could be close to the previous hue, at least in perception. You'd still have to do some sort of "closeness" checking – Neil N Jun 28 '10 at 18:43
  • @Neil: Yes, it's not guaranteed to be different (or it wouldn't be random), but since you're distributing the random function across hue instead of RGB, you're going to (for practical purposes) get colors that are more unique to the human eye. Even if you add a distance check in there, you'll find that you have far fewer "recalculations". In practical purposes, though, this tends to provide "random" colors, where-as randomizing RGB tends to give you much grayer looking "random" color schemes, that aren't as differentiatable. – Reed Copsey Jun 28 '10 at 18:56
  • I think your making a lot of assumptions. How is Hue more unique? They both cover the same color space. And how, in manthmatical terms would there be any less likelyhood of recalcs due to a distance check? – Neil N Jun 28 '10 at 19:01
  • 1
    @Neil:Hue is the “attribute of a visual sensation according to which an area appears to be similar to one of the perceived colors: red, yellow, green, and blue, or to a combination of two of them”. By randomizing just the hue, you're actually doing a random function in a projected space specifically designed to handle differences in **perceived** color. You're not gaining any more values mathematically, but you DO cause a single, random function to work over a space where the human physiology perceives differences in colors. By randomizing huge instead of trying to randomize 3 rgb values... – Reed Copsey Jun 28 '10 at 19:06
  • @Neil: ... you create a random distribution that is **perceptually** more unique (not mathematically). Try this sometime - with random RGB values, you have to take a lot of care, because its very easy to "randomize" yourself into the "gray" color ranges, mostly because the human eye doesn't perceive the differences as well in highly saturated, lower value color schemes. Just randomizing hue avoids these colors, which tends to make the colors "appear" more unique (they're mathematically less unique - but practically more useful). – Reed Copsey Jun 28 '10 at 19:08
  • Reed, there is still no discernable difference. HSL is essentially the visible colors projected into a cylindar, RGB is the same color space projected into a cube. Mathematically speaking, using HSL instead of native RGB is only adding an uneccesary conversion layer. Remember that he is trying to get the COMPUTER to generate the colors. The computer doesnt "percieve" colors as humans do. HSL is for humans. – Neil N Jun 28 '10 at 19:12
  • @Neil: Except that I'm suggesting he randomize over JUST hue (or at least, primarily hue). This will force the randomization to occur in a space where the human eye has a better chance of perception. This is something I've specifically had to deal with in my "day job" - your experience may vary, but it's been my experience than I can generate apparently "random" colors much more effectively by using a randomized hue than by working in RGB space. In addition, I find that using color distance computations are more effective if you compare in HSV/HSL space than RGB. – Reed Copsey Jun 28 '10 at 19:22
  • I guess "more effective" is pretty subjective. As I've also done this in my "day job". You would still need to avoid grays in Hue the same as you would the R==G==B axis in RGB. In the end, staying in RGB is just plain simpler. HSL was designed for human friendly color pickers, and thats pretty much where thier practical uses end. – Neil N Jun 28 '10 at 19:29
  • @Neil: If you randomize Hue, you'll have 0 grays in the result. I was saying to only randomize HUE, and leave the Sat/Value values constant (or near constant). Anyways, your mileage may vary - but it's worth trying out sometime, as I've had very good luck with this - much more so than trying to randomize RGB directly. – Reed Copsey Jun 28 '10 at 20:00
7

Check the "color distance"

Assume RGB are XYZ coordinates, do a 3D distance calculation. If a color isn't at least N away from all previously generated colors, try again.

N is a value you decide.

Neil N
  • 24,862
  • 16
  • 85
  • 145
1

assuming difference in shades is a measure of euclidean distance between coordinates, you can
1. Remember the previous color generated (a,b,c)
2. make sure that the next one generated (x,y,z) is atleast more than half the max possible distance
i.e sqrt [(a-x)^2 + (b-y)^2 + (c-z)^2] > 1/2 sqrt (3 * 255^2)
3. keep generating random triplets until you get one that satisfies above.. if 1/2 is not good enough, try 2/3 etc.strong text

prat
  • 607
  • 2
  • 8
  • 22
0

A very simple solution might be to use more distinct levels by taking ((Random.Next(0, 32) * 8) % 256) for example. Perhaps a lookup table can be used to skip colors that have been used already.

Sandor Drieënhuizen
  • 6,310
  • 5
  • 37
  • 80
  • but if R,G, and B are all generated using this method, you'd end up with near gray colors from light to dark. – Neil N Jun 28 '10 at 18:42
  • Yeah, you're right about that, some (dark) ranges should be excluded and primary values should not be allowed to be too close (except for being equal). – Sandor Drieënhuizen Jun 28 '10 at 18:43
0

Concerning uniqueness, have a look here.

For clearer color differences, you might try not to allow all possible values from 0 to 255, but only some steps, e.g. 0-32-64-96-128-160-192-224-255, so you get a bit of contrast.

Community
  • 1
  • 1
phimuemue
  • 34,669
  • 9
  • 84
  • 115
0

I wrote a utility function once to do that.

The idea was to linearise the RGB space into a 1D [0, 1] interval. For example doing (R + G*256 + B*256*256)/(256^3*256^2+256).

Then, everytime you need a new colour, you split an interval generated by previous samplings in 2. You pick the first colour as 0.0 in the new space, the second as 1.0, the third as 0.5, then 0.25, then 0.75 and so on. This kinda guarantees that if you generate few colours they have maximum 'separation' (though nor measured in terms of hue). As you generate more and more colours, they tend to get closer to one generated before, but always respecting a max-separation principle.

Once you have your [0, 1] value, you use the inverse function (triplet of functions actually) to go back to RGB.

In the basic implementation you get white and black as the two first colours. If you want something different, once you have generated your 'input' [0, 1] value, you can rotate it, say by a third, inside the same interval.

This works pretty well and it behaves deterministically (no unbounded number of retries).

Mau
  • 14,234
  • 2
  • 31
  • 52
0

Is there any reason to randomize colors, rather than outputting them in a fixed sequence? I would suggest that you use an index which gets incremented each color. Use a constant (probably maximum) saturation for your colors, have lightness be frac(indexconst1) and hue be frac(indexconst2). I'm not sure how best to compute const1 and const2; that will depend in some measure on how many points you'll have.

supercat
  • 77,689
  • 9
  • 166
  • 211
0

If the goal is to produce relatively uniformly distributed colours rather than just random, a standard technique is to set the Hue for the nth colour to n * 137 degrees. 137 (ish) is the "golden angle" which has some special properties that lead to a relatively well spaced distribution.

If you also want to vary the saturation and level I suspect that you can do something similar by mapping angles to a limited range and instead of using the golden angle use multiples of it to avoid tight association between the three components. E.g, use ((n * 2 * 137) mod 360)/720.0 + 0.5 for saturation and ((n * 4 * 137) mod 360)/720.0 + 0.25 for the level.

RD1
  • 3,305
  • 19
  • 28