4

Is there a way to identify colors, given by their hex codes, as being shades of a certain color ?
I think I found a way, not sure how accurate - but how can I tell if the color match I found is not good enough ?

I need to be able to identify color matches for specific colors - a fixed set (red, yellow, orange, blue, green, brown, purple, gray, black, white).

At the moment I am doing a color match based on distance:

Given a color c from the fixed color list above (which I set using hex colors to hopefully be in the middle of the range for that color, which I am not quite sure how to get - right now I am using a color that looks "good"), and a list of colors available list, I try to find the index from the list with the closest color.

int matchColor(QColor c, QList<QColor> list)
{
    int bestIndex = 0;
    int distance;
    int bestMatch = 0;
    int sz = list.size() - 1;

    for (int i = 0; i <= sz; ++i)
    {
        int Rdiff = 255 - qAbs(c.red() - list.at(i).red());
        int Gdiff = 255 - qAbs(c.green() - list.at(i).green());
        int Bdiff = 255 - qAbs(c.blue() - list.at(i).blue());
        distance = Rdiff + Gdiff + Bdiff;

        if (distance > bestMatch)
        {
            bestMatch = distance;
            bestIndex = i;
        }
    }

    // if(bestMatch < 600 ? or something ?) return -1;

    return bestIndex;
}

The problem is, because this match is supposed to be strictly enforced (for some standards), I must return shades of the specific color c and fail if I can't.
I am not 100% certain the color match is good - though it seems fairly ok.

But other than finding the best color match - what is a reasonable value of distance, for which I should reject a match ? (expecting distance between 0 and 765, with 765 being perfect match).
Are there certain ranges I can check ?

Would the range be different for each color ?

Note - I found some similar questions, some have references to more complex algorithms that I could not understand - but I saw nothing that can tell me how to reject a match... I would appreciate a better solution if any.

Thalia
  • 13,637
  • 22
  • 96
  • 190
  • 1
    Yes, the range will be different for each color, unless you first convert to a perceptually uniform color space such as [CIE Lab](https://en.wikipedia.org/wiki/Lab_color_space). – Mark Ransom Jul 26 '16 at 21:08

2 Answers2

6

It is basically impossible to tell you which tolerances are acceptable to your use case, but I would strongly suggest converting to HSV before trying to match colors. The H component is critical, and should probably have a tolerance of no more than 20 or 30 degrees. S and V are far less critical; you might be able to either ignore them, or only filter out the extreme cases where the hue disappears completely.

The conversion is described here: Algorithm to convert RGB to HSV and HSV to RGB in range 0-255 for both

Community
  • 1
  • 1
H. Guijt
  • 3,325
  • 11
  • 16
  • Using the `QColor` methods from qt, I can get the HSL values - and I am trying to compare the hue if positive. For white, black, shades of gray, the hue is given as -1 so I compare the value. Seems easy... But comparing some colors like brown - "#8b4513" (hue=25) finds best match orange - "#e98300" (hue = 33) (difference=8) (from a random list of colors) - it found the closest match (like the euclidian difference method did) but seems the hue is not discerning enough to reject that match, and 8 is really a small difference – Thalia Jul 27 '16 at 15:55
  • Ok, sorry to hear that. I was using the method myself many years ago, when I still had to support 8-bit (palette) color output, and found it to give good results for my purpose. It seemed like a good match for your problem as well. – H. Guijt Jul 27 '16 at 16:19
4

The most standard way of measuring color differences is something called Delta E. Delta E is computed from 2 Lab values where Lab is a standard way colors are described.

DeltaE=sqrt(pow(L1-L2,2)+pow(a1-a2,2)+pow(b1-b2,2))

There are three Lab values, L, a, and b. L is a measure of luminousness. a and b determine hue and saturation. Think of a and b as a vector. The length is color saturation and the angle is hue.

Select the color that produces the smallest Delta E. There is a slightly better version called DeltaE2000 that improves matching of small color differences but the math is more complex and DeltaE is good enough for most purposes.

See here for converting sRGB values to Lab.

RGB to CIE LAB

Community
  • 1
  • 1
doug
  • 3,840
  • 1
  • 14
  • 18