Why isn't inRange function detecting blue color when I have given it the entire possible Hue range for the blue color?

早过忘川 提交于 2020-01-07 08:46:51

问题


On the website colorizer.org, they have an HSV range of H=0-360, S=0-100, V=0-100. We are also aware that the HSV range in OpenCV is H=0-180, S=0-255, V=0-255.

I wanted to select a range for any shade of (what we perceive as) blue color, so I looked at colorizer.org, and saw that blue Hue ranges roughly from 170 to 270. So I scaled this Hue range to OpenCV by dividing by 2, which gives 85-135.

Now, I took the following screenshot of color [H=216, S=96, V=67] from the preview at the website

Then I run the app on my phone and captured the following camera frame from the laptop screen. I understand that the HSV channel values will differ from those in website to some extent because there are other conditions like additional light (V in HSV) in the room when I captured the camera frame, etc.

Then I converted this Mat to HSV color space by Imgproc.cvtColor(rgbaFrame, hsvImage, Imgproc.COLOR_RGB2HSV_FULL);, which resulted in the following image.

Then I called the inRange function:

Core.inRange(hsvImage, new Scalar(85, 50, 40), new Scalar(135, 255, 255), maskedImage);

which resulted in the following maskedImage.

The question is that why isn't it detecting the blue color when I have included all the Hue Range possible for blue color really?


IMPORTANT: Except the first original image, all the images were stored in sdcard using Highgui.imwrite function, so that I could move them to my computer in order to upload them on Stackoverflow. You must have noticed that the blue color in the first original screenshot is converted to red color in the second image. The reason is that the frame captured by the camera (that is the photo/frame of the first screenshot captured by the mobile phone camera) is an RGBA image. But OpenCV converts all images to BRG by default when it saves them to sdcard of something. So be assured that the original image is RGBA, and it is only converted to BGR internally by OpenCV for saving into sdcard. That's why red appears blue.


回答1:


using this code does work for me (C++):

    cv::Mat input = cv::imread("../inputData/HSV_RGB.jpg");

    //assuming your image to be in RGB format after loading:
    cv::Mat hsv;
    cv::cvtColor(input,hsv,CV_RGB2HSV);

    // hue range:
    cv::Mat mask;
    inRange(hsv, cv::Scalar(85, 50, 40), cv::Scalar(135, 255, 255), mask);

    cv::imshow("blue mask", mask);

I used this input image (saved and loaded in BGR format although it in fact is a RGB image, that's why we have to use RGB2HSV instead of BGR2HSV):

resulting in this mask:

The difference to your code is that I used CV_RGB2HSV instead of CV_RGB2HSV_FULL. Flag CV_RGB2HSV_FULL uses the whole byte to store the hue values, so range 0 .. 360 degrees will be scaled to 0 .. 255 instead of 0 .. 180 as in CV_RGB2HSV

I could verify this by using this part of the code:

    // use _FULL flag:
    cv::cvtColor(input,hsv,CV_RGB2HSV_FULL);
    // but scale the hue values accordingly:
    double hueScale = 2.0/1.41176470588;
    cv::Mat mask;
    // scale hue values:
    inRange(hsv, cv::Scalar(hueScale*85, 50, 40), cv::Scalar(hueScale*135, 255, 255), mask);

giving this result:

For anyone who wants to test with the "right" image:

Here's the input converted to BGR: If you want to use that directly you have to switch conversion from RGB2HSV to BGR2HSV. But I thought it would be better to show the BGR version of the input, too...



来源:https://stackoverflow.com/questions/34200353/why-isnt-inrange-function-detecting-blue-color-when-i-have-given-it-the-entire

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!