Ask Your Question

color detection in different background of human machine interface

asked 2019-05-14 05:20:26 -0500

gino0717 gravatar image

Now I want to use a camera to help me look at the human-machine interface of plc so I can fool around during working.

When I do a little test, I use InRange function to detect some yellow color in HSV color space in (H,S,V)=(10,45,150)~(30,255,255)

at first, everything is fine.

image descriptionimage description

However, if I want to change the background to other colors, all things go wrong. I change to a slightly yellow background and the colors go wired and the HSV range does not work for now.

image description

image description

and green background, you can see that the color of the lights changed.

image description

I think this is a white-balance issue so I try to write a white balance algorithm such as gray world white balance but It didn't help this situation. I also disable the white balance of my camera but the color shifting is still there. what kind of keyword I can search for this problem?

image description

edit retag flag offensive close merge delete

1 answer

Sort by ยป oldest newest most voted

answered 2019-05-14 10:57:51 -0500

updated 2019-05-17 08:58:17 -0500

Here are the steps that seem to work well from left to right in the image below.

  1. original image

  2. apply Sobel filter with 5x5 kernel and first order derivatives in both x and y

  3. convert to mono and threshold about 80

  4. dilation with Rect 3x3 kernel for 4 iterations

From, here you can filter contours by aspect ratio and size so only the powdered donuts are left.

image description

And here are the results on all three.

image description

Here was my simple white balance trick. After finding the locations of the lights, pick an area in between 2 lights that should be background. Use OpenCV mean to get the average rgb values in this background area. A "white" background should have r==b==g but some of these images are blue-green. So compute an offset or delta that will change this average so that rgb are all equal and apply this delta to the whole image.

Scalar colorAvg = mean(srcImg, maskImg);

float channelAvg = (colorAvg[0] + colorAvg[1] + colorAvg[2]) / 3;

Scalar delta(channelAvg - colorAvg[0], channelAvg - colorAvg[1], channelAvg - colorAvg[2]);

balanceImg = srcImg + delta;
enter code here

Then using the found locations of the lights, set up a mask that is a semicircle on the bottom half of the light (first image below). The reason for this is to avoid the glare on the top half of the light. Then we can use OpenCV mean to get the average rgb values in that masked area for each different light. Then I apply this logic to the rgb mean: if (g > r && g > b) then green else if (r > 1.3 * max(b, g)) then red else yellow

image description

edit flag offensive delete link more


thanks for the answer. But actually what I need is to detect the yellow color.

gino0717 gravatar imagegino0717 ( 2019-05-14 19:03:49 -0500 )edit

Question Tools

1 follower


Asked: 2019-05-14 05:20:26 -0500

Seen: 966 times

Last updated: May 17 '19