Ask Your Question

Detection of red rectangle and environment lighting

asked 2019-06-16 14:11:47 -0500

DRD gravatar image

updated 2019-06-16 18:07:08 -0500

Hi, I'm in the process of writing some code which detects the largest red rectangle in an image. I'm using the code below, but the detection is very prone to changes in the environment lighting, if it works at all.

Does anyone have any ideas about how to make the detection more robust and less prone to light changes? Should I use adaptiveThreshold for this or something else?

After running findContours below I find the largest rectangle by checking for area size and number of vertices.

// convert the frame to HSV
Imgproc.cvtColor(frame, hsvImage, Imgproc.COLOR_BGR2HSV);
// Limit color range to reds in the image
Mat redMask1 = new Mat(); 
Mat redMask2 = new Mat(); 
Mat redMaskf = new Mat();

Core.inRange(hsvImage, new Scalar(0, 70, 50), new Scalar(10, 255, 255), redMask1); 
Core.inRange(hsvImage, new Scalar(170, 70, 50), new Scalar(180, 255, 255), redMask2);          
Core.bitwise_or(redMask1, redMask2, redMaskf);

Imgproc.medianBlur(redMaskf, blurredImage, 9);
Imgproc.Canny(blurredImage, edges, 300, 600, 5, true);
Imgproc.findContours(edges, contours, new Mat(), Imgproc.RETR_LIST, Imgproc.CHAIN_APPROX_SIMPLE);

I'm using this image as a reference for testing

image description


Btw. I can post the full method if it helps

edit retag flag offensive close merge delete



could you post some sample images

sturkmen gravatar imagesturkmen ( 2019-06-16 15:19:05 -0500 )edit

Sure, I added a image to my post. Thanks

DRD gravatar imageDRD ( 2019-06-16 18:07:28 -0500 )edit

I suggest after Core.inRange blur the image and then use threshold instead of bitwise_or and Canny, then use findContours. I don't know any theoretical explanation of why it is better just saying it based on my own experience. When I had to find an object with a specific color with Canny it was impossible but with threshold, it worked pretty well.

Lucy8 gravatar imageLucy8 ( 2019-06-17 06:56:01 -0500 )edit

2 answers

Sort by ยป oldest newest most voted

answered 2019-06-18 07:02:56 -0500

Below are four images. The first is the red channel extracted from the original image. The 2nd is this extracted image thresholded at about 200. The 3rd is the result of using findContours with external option used and then only keep the largest contour. The 4th is the contour mask after some morphology to clean up the corners: 1 iteration of erosion with a very wide kernel about 50 x 3 and 1 iteration with a very tall kernel about 3 x 50

image description

edit flag offensive delete link more


hi, could you leave the code for this?

PoriaTheGreat gravatar imagePoriaTheGreat ( 2020-02-27 08:42:45 -0500 )edit

answered 2019-06-18 05:23:41 -0500

updated 2019-06-18 05:34:35 -0500

finding blue in HSV is easier so you can use COLOR_RGB2HSV flag instead of COLOR_BGR2HSV

you can test the code below and see the result.

  Mat hsvImage = new Mat();       
  // convert the frame to HSV
  // using COLOR_RGB2HSV flag will change red to blue
  Imgproc.cvtColor(frame, hsvImage, Imgproc.COLOR_RGB2HSV);
  // Limit color range to blue in the image
  Mat blueMask = new Mat(); 
  Core.inRange(hsvImage, new Scalar(110, 50, 50), new Scalar(130, 255, 255), blueMask);
edit flag offensive delete link more

Question Tools



Asked: 2019-06-16 14:11:47 -0500

Seen: 634 times

Last updated: Jun 18 '19