Search code examples
c++opencvimage-processingcolors

OpenCV better detection of red color?


I have the following image:

enter image description here

I would like to detect the red rectangle using cv::inRange method and HSV color space.

int H_MIN = 0;
int H_MAX = 10;
int S_MIN = 70; 
int S_MAX = 255;
int V_MIN = 50;
int V_MAX = 255;

cv::cvtColor( input, imageHSV, cv::COLOR_BGR2HSV );

cv::inRange( imageHSV, cv::Scalar( H_MIN, S_MIN, V_MIN ), cv::Scalar( H_MAX, S_MAX, V_MAX ), imgThreshold0 );

I already created dynamic trackbars in order to change the values for HSV, but I can't get the desired result.

Any suggestion for best values (and maybe filters) to use?


Solution

  • In HSV space, the red color wraps around 180. So you need the H values to be both in [0,10] and [170, 180].

    Try this:

    #include <opencv2\opencv.hpp>
    using namespace cv;
    
    int main()
    {
        Mat3b bgr = imread("path_to_image");
    
        Mat3b hsv;
        cvtColor(bgr, hsv, COLOR_BGR2HSV);
    
        Mat1b mask1, mask2;
        inRange(hsv, Scalar(0, 70, 50), Scalar(10, 255, 255), mask1);
        inRange(hsv, Scalar(170, 70, 50), Scalar(180, 255, 255), mask2);
    
        Mat1b mask = mask1 | mask2;
    
        imshow("Mask", mask);
        waitKey();
    
        return 0;
    }
    

    Your previous result:

    enter image description here

    Result adding range [170, 180]:

    enter image description here


    Another interesting approach which needs to check a single range only is:

    • invert the BGR image
    • convert to HSV
    • look for cyan color

    This idea has been proposed by fmw42 and kindly pointed out by Mark Setchell. Thank you very much for that.

    #include <opencv2\opencv.hpp>
    using namespace cv;
    
    int main()
    {
        Mat3b bgr = imread("path_to_image");
    
        Mat3b bgr_inv = ~bgr;
        Mat3b hsv_inv;
        cvtColor(bgr_inv, hsv_inv, COLOR_BGR2HSV);
    
        Mat1b mask; 
        inRange(hsv_inv, Scalar(90 - 10, 70, 50), Scalar(90 + 10, 255, 255), mask); // Cyan is 90
    
        imshow("Mask", mask);
        waitKey();
    
        return 0;
    }
    

    enter image description here