views:

1034

answers:

9

Anyone have any suggestions on how to make randomized colors that are all greenish? Right now I'm generating the colors by this:

color = (randint(100, 200), randint(120, 255), randint(100, 200))

That mostly works, but I get brownish colors a lot.

+42  A: 

Simple solution: Use the HSL or HSV color space instead of rgb (convert it to RGB afterwards if you need this). The difference is the meaning of the tuple: Where RGB means values for Red, Green and Blue, in HSL the H is the color (120 degree or 0.33 meaning green for example) and the S is for saturation and the V for the brightness. So keep the H at a fixed value (or for even more random colors you could randomize it by add/sub a small random number) and randomize the S and the V. See the wikipedia article.

theomega
+1 only thing I would add is that you could even vary H from probably 0.31 to 0.35 or even more to get some slightly different hues.
Moose
Thanks for the hint, changed that.
theomega
Great ideas. Thanks
Echo
+13  A: 

Check out the colorsys module:

http://docs.python.org/library/colorsys.html

Use the HSL or HSV color space. Randomize the hue to be close to green, then choose completely random stuff for the saturation and V (brightness).

Anthony Mills
Choosing saturation and brightness completely at random would include pure black and white as possible outcomes.
Wim Coenen
If I could accept 2 answers, I would accept this one too. Thanks.
Echo
You can choose random values between about 0.2 and 1 for saturation and value, without it looking too bad (in HTML at least)
dbr
@wcoenen: It all depends on Echo's definition of "greenish". Maybe the hue needs to be really narrow, or maybe a bit wider definition is good. But the main thing is to get the colorspace conversion code in there so it's possible to play around with the numbers.@Echo: Btw, you might also want to play around with using something other than a straight linear random function. Something like random.normalvariate or so. But that wouldn't really give a good cutoff point to make sure every output color is green (though most would be)... hmm.
Anthony Mills
+4  A: 

So in this case you are lucky enough to want variations on a primary color, but for artistic uses like this it is better to specify color wheel coordinates rather than primary color magnitudes.

You probably want something from the colorsys module like:

colorsys.hsv_to_rgb(h, s, v)
    Convert the color from HSV coordinates to RGB coordinates.
DigitalRoss
A: 

The simplest way to do this is to make sure that the red and blue components are the same, like this: (Forgive my Python)

rb = randint(100, 200)
color = (rb, randint(120, 255), rb)
SLaks
Slight differences between red and blue should be allowed. - See Moose's comment to theomega's answer.
Danny Varod
Hmm... This method can generate a color with G component smaller than R and B components, like (200, 120, 200) in the most extreme case. This is a purplish color, not even remotely greenish.
AndreyT
@Danny: This sounds illogical to me. In RGB terms I would define "geenish" as any color with G component greater than both R and B components. It doesn't matter how large the difference between R and B is, as long as G is greater than both of them the color will appear greenish. The degree of "greenishness" can be parametrized by how much G is larger than R and B, but the difference between the R and B still doesn't play any significant role.
AndreyT
I tried it; he may be right. Paste the following code into LINQPad: `var form = new Form();var rand = new Random();form.Click += delegate{var green = rand.Next(128,255);var rb = rand.Next(100);form.BackColor=Color.FromArgb(rb,green,rb+rand.Next(-5,5));};form.ShowDialog();`
SLaks
A: 

What you want is to work in terms of HSL instead of RGB. You could find a range of hue that satisfies "greenish" and pick a random hue from it. You could also pick random saturation and lightness but you'll probably want to keep your saturation near 1 and your lightness around 0.5 but you can play with them.

Below is some actionscript code to convert HSL to RGB. I haven't touched python in a while or it'd post the python version.

I find that greenish is something like 0.47*PI to 0.8*PI.

    /**
@param h hue [0, 2PI]
@param s saturation [0,1]
@param l lightness [0,1]
@return object {r,g,b} {[0,1],[0,1][0,1]}
*/
public function hslToRGB(h:Number, s:Number, l:Number):Color
{
    var q:Number = (l<0.5)?l*(1+s):l+s-l*s;
    var p:Number = 2*l-q;
    var h_k:Number = h/(Math.PI*2);
    var t_r:Number = h_k+1/3;
    var t_g:Number = h_k;
    var t_b:Number = h_k-1/3;
    if (t_r < 0) ++t_r; else if (t_r > 1) --t_r;
    if (t_g < 0) ++t_g; else if (t_g > 1) --t_g;
    if (t_b < 0) ++t_b; else if (t_b > 1) --t_b;
    var c:Color = new Color();
    if (t_r < 1/6) c.r = p+((q-p)*6*t_r);
    else if (t_r < 1/2) c.r = q;
    else if (t_r < 2/3) c.r = p+((q-p)*6*(2/3-t_r));
    else c.r = p;
    if (t_g < 1/6) c.g = p+((q-p)*6*t_g);
    else if (t_g < 1/2) c.g = q;
    else if (t_g < 2/3) c.g = p+((q-p)*6*(2/3-t_g));
    else c.g = p;
    if (t_b < 1/6) c.b = p+((q-p)*6*t_b);
    else if (t_b < 1/2) c.b = q;
    else if (t_b < 2/3) c.b = p+((q-p)*6*(2/3-t_b));
    else c.b = p;
    return c;
}
putgeminmouth
+11  A: 
dbr
+6  A: 

If you stick with RGB, you basically just need to make sure the G value is greater than the R and B, and try to keep the blue and red values similar so that the hue doesn't go too crazy. Extending from Slaks, maybe something like (I know next to nothing about Python):

greenval = randint(100, 255)
redval = randint(20,(greenval - 60))
blueval = randint((redval - 20), (redval + 20))
color = (redval, greenval, blueval)
Matt Bayliss
+1, this works surprisingly well. Sample output: http://img11.imageshack.us/img11/1226/simplerandgreen.png (compared to a more complicated method using HSV, which looks much the same: http://img197.imageshack.us/img197/5770/randomgreens.png )
dbr
Thanks for generating that dbr, good to see it actually works! ;)
Matt Bayliss
+1 for simplicity and elegance
Justin L.
+2  A: 

The solution with HSx color space is a very good one. However, if you need something extremely simplistic and have no specific requirements about the distribution of the colors (like uniformity), a simplistic RGB-based solution would be just to make sure that G value is greater than both R and B

rr = randint(100, 200)
rb = randint(100, 200)
rg = randint(max(rr, rb) + 1, 255)

This will give you "greenish" colors. Some of them will be ever so slightly greenish. You can increase the guaranteed degree of greenishness by increasing (absolutely or relatively) the lower bound in the last randint call.

AndreyT
There's a typo in your code, `rg = randint(max(rg ...`, and Python doesn't need the explicit line-terminating semi-colons!
dbr
Thank you! Fixed.
AndreyT
A: 

I'd go with with the HSV approach everyone else mentioned. Another approach would be to get a nice high resolution photo which some greenery in it, crop out the non-green parts, and pick random pixels from it using PIL.

Dickon Reed