I am using emgucv with opencv.

I have an object I wish to detect based on colour. I convert the image to Hsl colour space and perform a filter on it.

The object I am detecting is perceived as yellow so I cover that range and make sure I am using/filtering good saturation.

This has been working well.

But I have now upgrade my usb camera and I have changed the lighting in the room.

Now running the same code I can it is ‘missing’ a lot of the object.

So, I inspect the hue of the pixels that have been missed out.

I can now see that the hues of those pixels have ‘shifted’ to the red range. This incidentally is more noticeable when the object is closer to the camera.

So my question is this;

Is yellow an unreliable colour to detect compared to say red, green, blue etc?

Is the object not truly yellow? Though when the object is further away it does not appear to be a problem,

Is colour segmentation unreliable?

Should I consider using a different colour space?

I will post my existing code if people require but I do not think it is required?



1 Answer 1


A standard color camera, along with its software driver, is suppose to reflect the color that the eye would see. If it isn't doing that, then you have a badly designed camera or driver. In that case, either get a good camera+driver combo, or if the damage is linear you might be able to repair it by first multiplying the RGB with a 3x3 matrix that you have designed. Start with a unity matrix and adjust the elements until the output looks most like it does when you are looking right at the object (and assuming there is negligible color damage caused by the monitor you use to do this). Or you could even programmatically create the matrix by comparing the camera output with an ideal camera output. Once that is taken care of then you can pass the output to the algorithm that recognizes the object.

As far as the color space used for recognizing the object, a simple algorithm might do best keying off of the hue and saturation, so HSL might be best for that. But your real goal is to key off the intensities of all three colors (RGB) but still ignore luminance. So I suggest you use normalized RGB. That is, first scale the RGB so the total energy is some constant (say, unity). Specifically: ScaledRGB = RGB / VectorMagnitude(RGB). Once it's been normalized, you simply measure how far that normalized RGB "vector" is from the target color.

Other than the above points, there shouldn't be an issue with the particular color you are using, except that it should be most different from the particular background environment.

EDIT: answering subsequent questions...

If the scene lighting changes, you must first measure the change by noting the coloration of parts of the scene or the whole scene that always remain in view. For example, if you know of a mostly white object that remains in view and remains stationary, you can use that color vector as the normalization divisor rather than the magnitude of the pixel as described earlier (that is, divide a pixel's red by the white object's red, etc.). If you don't know of any white objects that remain in view and remains stationary, then take the average RGB of the entire scene (including the target object, if present, since you don't know where it is, yet. And also ideally compensate for known coloration of these background objects, if possible) and use that RGB as the divisor in your normalization (pixel's red divided by average red, etc.). This normalizes the scene for lighting and camera oddities. Then you can search for the object without regard of changes in lighting, etc..

  • $\begingroup$ Thanks for your answer. I could apply a normalisation technique and see if that improves things. I have noticed whatever camera I am using it gives the same result. If I have an object that is yellow and a red light is beamed on it the object will take on a red hue. So, if the yellow object is 'bathed' in outside sunny light then that could explain the perceived colour change? So, do you think this/could will be offset by applying normalisation? I will of course test this myself to see but as you are active here I thought I would just ask :) $\endgroup$ Apr 25, 2019 at 16:26
  • $\begingroup$ Edited my answer $\endgroup$
    – Digiproc
    Apr 26, 2019 at 10:07
  • $\begingroup$ Thanks seems logical :) $\endgroup$ Apr 26, 2019 at 15:55

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.