We closed this forum 18 June 2010. It has served us well since 2005 as the ALPHA forum did before it from 2002 to 2005. New discussions are ongoing at the new URL http://forum.processing.org. You'll need to sign up and get a new user account. We're sorry about that inconvenience, but we think it's better in the long run. The content on this forum will remain online.
IndexProgramming Questions & HelpSyntax Questions › evaluate a color and give it a score
Page Index Toggle Pages: 1
evaluate a color and give it a score (Read 874 times)
evaluate a color and give it a score
Jan 21st, 2010, 2:53pm
 
Hello guys, im trying to think which is the best to achieve this :
i have 2 variables , each one with a color, the first variable is my "ideal" color, for example red : color (255, 0 , 0)  and my second varialbe holds a random color  generated randomly by the program ,
my question is  : i would like to know which mechanisms does exist in order to evalue my random generated color  using my first variable color as evaluating criteria , for example if my random generated color is (255,  0, 0) its going to have 10 points ( the max)  because its the same as my "ideal"color , but if my generated random color is  0, 255, 255 it is going to have 0 points because is the worst option.

So my question which mechanism does exist in order to evaluate a color using an "ideal"color for giving a score?

any idea
?

thanks

Sebastiano
Re: evaluate a color and give it a score
Reply #1 - Jan 21st, 2010, 3:06pm
 
Calculate the distance between the two colors.
Re: evaluate a color and give it a score
Reply #2 - Jan 21st, 2010, 4:07pm
 
As JR suggested:

Quote:
color c1 = color(000,128,000);
color c2 = color(128,000,128);

float dist_colors(color cA, color cB){ // pure distance between them
 return( dist( cA >> 16 & 0xFF, cA >> 8 & 0xFF, cA & 0xFF, cB >> 16 & 0xFF, cB >> 8 & 0xFF, cB & 0xFF ) );
}

float score_colors(color cA, color cB){ // the pure distance mapped to the 0 to 10 range
  return( map( dist_colors(cA,cB), 0, 441.67294, 0, 10 ) );
// 441.67294 = dist(0,0,0,255,255,255)

int rank_colors(color cA, color cB){ // a rank on a scale of 0 to 10
  return( (int)( 10.5 - score_colors(cA,cB) ) );
}

void setup(){
  println( " dist_colors( c1, c2 ): " +  dist_colors( c1, c2 ) );
  println( "score_colors( c1, c2 ): " + score_colors( c1, c2 ) );
  println( " rank_colors( c1, c2 ): " +  rank_colors( c1, c2 ) );
  noStroke();
  fill(c1);
  rect(0,0,width,height);
  fill(c2);
  rect(width/2.0,0,width,height/2.0);
  rect(0,height/2.0,width/2.0,height);
}

Re: evaluate a color and give it a score
Reply #3 - Jan 21st, 2010, 10:16pm
 
TfGuy44 wrote on Jan 21st, 2010, 4:07pm:
  return( map( dist_colors(cA,cB), 0, 441.67294, 0, 10 ) );
// 441.67294 = dist(0,0,0,255,255,255)

sqrt(255*255*3) comes out as 441.67295593006... using Microsoft Calculator ("calc" on Windows), so I should expect the rounded dist() result to be 441.67296 (not that this will make much difference, mind you!).

Moving on...

This "distance" is the Euclidean distance, and my suggestion is that this isn't the most appropriate measure in this case.

I suggest using the sum of the differences of each colour channel. Differs only one of red, green or blue: max distance is 255 (with score of 6.67). Differs in two of red, green and blue: max distance is 255*2=510 (with score of 3.33). Differs in all three red, green and blue: max distance is 255*3=765 (with score of 0). This is the so-called "Manhattan distance" ("taxicab distance"), or rectilinear distance.

Warning: following code untested!

Code:
float scoreRGB = map( abs(test.red()-ideal.red()) + abs(test.green()-ideal.green()) + abs(test.blue()-ideal.blue()), 0, 255*3, 10, 0 ); // Note score goes down to 0 as distance goes up 



You might further decide that taking some measure of "RGB distance" isn't really what you want. Maybe other qualities of the colour are more important. Perhaps it would produce a more meaningful score based on the HSB colour model - hue, saturation, brightness - and perhaps you might weight those properties differently, eg score affected more by change in hue than by change in saturation. You will have to watch out for the "hue" wrapping around though!

Warning: following code untested!

Code:
float MIN_SCORE = 0;
float MAX_SCORE = 10;

float r[] = { 360, 100, 100 }; // H,S,B ranges
float m[] = { 180, 100, 100 }; // max distances
float w[] = { 2, 1, 1 }; // weights

colorMode(HSB, r[0], r[1], r[2]);

float d[] = new float[3]; // H,S,B differences

// Max hue difference is "half-way around", after which
// the hue gets closer again
d[0] = abs(test.hue() - ideal.hue());
if (d[0] > m[0]) d[0] = r[0] - d[0];

d[1] = abs(test.saturation() - ideal.saturation());
d[2] = abs(test.brightness() - ideal.brightness());

float sum = 0;
float weightDivisor = 0;

for (int i = 0; i < d.length; i++)
{
 sum += d[i] / m[i] * w[i]; // Normalise and weight
 weightDivisor += w[i];
}

float weightedDistance = sum / weightDivisor;

// Note: score goes down as distance goes up
float score = map(weightedDistance, 0, 1, MAX_SCORE, MIN_SCORE );


Unfortunately, almost nothing worthwhile is easy, and the above code (or something like it) would need to be augmented to handle special cases: the HSB model has some degenerate values, such as when brightness is zero (in which case hue and saturation have no meaning nor effect), or saturation is zero (in which case hue doesn't have any meaning).

-spxl
Re: evaluate a color and give it a score
Reply #4 - Jan 22nd, 2010, 2:57am
 
I'd just like to make it clear that my posted code above is not, nor did I claim it was, the definitive way to compare colors. It just seemed like what sebastiano wanted. Feel free to edit/tweak it to suit your own needs/desires/situation!  Cheesy
Re: evaluate a color and give it a score
Reply #5 - Jan 22nd, 2010, 7:54am
 
Not suggesting that you did, TfGuy.  Smiley
Re: evaluate a color and give it a score
Reply #6 - Jan 22nd, 2010, 8:23am
 
also keep in mind that RGB isn't a "perceptual" colorspace (neither is HSB, tho it's perhaps closer to being so).  that is, in RGB, the difference between values of 30-10=20 is almost imperceptable, but the difference between 240-220=20 is dramatic.  throw in all 3 axes and it gets really non-intuitive, regardless of distance measure (euc/man).  it's very easy to come up with RGB pairs that are "closer" than some other, even though the other appears a closer visual match to a human eye.

 so at a bare minimum you probably want to gamma-correct the values to flatten/linearize the response curves a bit.  (if using HSB, you'd gamma-correct just "B")  converting to CIELAB might help, since it's intended as a perceptual space, though the conversion isn't straightforward.

hth
Page Index Toggle Pages: 1