Ask Your Question
1

Correct HSV InRange Values for 'Red' Objects

asked 2014-02-23 23:30:42 -0500

ashgabat gravatar image

updated 2015-10-12 04:30:28 -0500

pklab gravatar image

I am using OpenCV 2.4.6 to try to detect white objects in an image that is primarily green-grey. (See the following picture).

I have converted this image into the HSV format and these white objects (houses) as expected are converted into a reddish-orange equivalent when printed out. I've been trying to find the values that cover these reddish oranges so I can then use connected components to detect the objects.

However, experimentally trying to find the ranges has not been working - so far it has produced somewhat adequate results with the range 190 to 255. Looking around, I have found sources saying thresholds of 0 to 10 work, or 110 to 140, but sources also say that the HSV InRange values in OpenCV only range from 0 to 180.

  1. How am I still getting results with my current parameters?
  2. How do I detect this red color in the HSV plane?

FYI: There is background noise such as a road and fields but that's not important right now, I just want to find out the 'correct' InRange Values.

Here is a snippet of my current code:

// Convert to HSV for better thresh results Mat src = read from image file; Mat dest = new Mat();

Imgproc.cvtColor(src, dest, Imgproc.COLOR_RGB2HSV);
Highgui.imwrite(outputFilename + "HSV.png", dest);

List<MatOfPoint> contours = new ArrayList<MatOfPoint>();
Core.inRange(dest, new Scalar(190, 0, 0), new Scalar(256, 256, 256), dest);

Highgui.imwrite(outputFilename + "Filter.png", dest);

Pictures:

C:\fakepath\Houses8.png

C:\fakepath\GrayOutHSV.png

Thanks in advance.

edit retag flag offensive close merge delete

1 answer

Sort by ยป oldest newest most voted
7

answered 2014-02-23 23:59:19 -0500

Haris gravatar image

updated 2019-06-21 12:48:24 -0500

Hi,

Below I am sharing the code I created to chose HSV value easily while HSV-color segmentation ,you can use it and choose correct HSV-Range. Hope this will helpful for the user who working with HSV colour segmentation.

image description

Code:

#include "opencv2/imgproc.hpp"
#include "opencv2/imgcodecs.hpp"
#include "opencv2/highgui.hpp"
#include <iostream>

#define HUEMAX 179
#define SATMAX 255
#define VALMAX 255

using namespace std;
using namespace cv;

Mat HSV;
int H = 170;
int S = 200;
int V = 200;
int R = 0;
int G = 0;
int B = 0;

int MAX_H = 179;
int MAX_S = 255;
int MAX_V = 255;
int mouse_x = 0;
int mouse_y = 0;
char window_name[20] = "HSV Color Plot";

//Global variable for hsv color wheel plot
int max_hue_range = 179;
int max_step = 3; //nuber of pixel for each hue color
int wheel_width = max_hue_range * max_step;
int wheel_hight = 50;
int wheel_x = 50; //x-position of wheel
int wheel_y = 5;//y-position of wheel

//Global variable plot for satuarion-value plot
int S_V_Width = MAX_S;
int S_V_Height = MAX_S;
int S_V_x = 10;
int S_V_y = wheel_y + wheel_hight + 20;

//Global variable for HSV plot
int HSV_Width = 150;
int HSV_Height = 150;
int HSV_x = S_V_x + S_V_Width + 30;
int HSV_y = S_V_y + 50;


void onTrackbar_changed(int, void*);
static void onMouse(int event, int x, int y, int, void*);
void drawPointers(void);

int main()
{
    HSV.create(390, 640, CV_8UC3);
    HSV.setTo(Scalar(200, 0, 200));

    namedWindow(window_name);
    createTrackbar("Hue", window_name, &H, HUEMAX, onTrackbar_changed);
    createTrackbar("Saturation", window_name, &S, SATMAX, onTrackbar_changed);
    createTrackbar("Value", window_name, &V, VALMAX, onTrackbar_changed);
    onTrackbar_changed(0, 0); //initialize window

    setMouseCallback(window_name, onMouse, 0);
    while (true)
    {
        int c;
        c = waitKey(20);
        if ((char)c == 27)
        {
            break;
        }
    }

    return 0;
}

void onTrackbar_changed(int, void*) {

    //Plot color wheel.
    int hue_range = 0;
    int step = 1;
    for (int i = wheel_y; i < wheel_hight + wheel_y; i++) {
        hue_range = 0;
        for (int j = wheel_x; j < wheel_width + wheel_x; j++) {
            if (hue_range >= max_hue_range) hue_range = 0;
            if (step++ == max_step) {
                hue_range++;
                step = 1;
            }
            Vec3b pix;
            pix.val[0] = hue_range;
            pix.val[1] = 255;
            pix.val[2] = 255;


            HSV.at<Vec3b>(i, j) = pix;

        }
    }


    //Plot for saturation and value
    int sat_range = 0;
    int value_range = 255;
    for (int i = S_V_y; i < S_V_Height + S_V_y; i++) {
        value_range--;
        sat_range = 0;
        for (int j = S_V_x; j < S_V_Width + S_V_x; j++) {
            Vec3b pix;
            pix.val[0] = H;
            pix.val[1] = sat_range++;
            pix.val[2] = value_range;
            HSV.at<Vec3b>(i, j) = pix;

        }

    }

    //Plot for HSV
    Mat roi1(HSV, Rect(HSV_x, HSV_y, HSV_Width, HSV_Height));
    roi1 = Scalar(H, S, V);
    drawPointers();

    Mat RGB;
    cvtColor(HSV, RGB, COLOR_HSV2BGR);

    imshow(window_name, RGB);
    imwrite("hsv.jpg", RGB);

}

static void onMouse(int event, int x, int y, int f, void*) {
    if (f&EVENT_FLAG_LBUTTON) {
        mouse_x = x;
        mouse_y = y;
        if (((wheel_x <= x) && (x <= wheel_x + wheel_width)) && ((wheel_y <= y) && (y <= wheel_y + wheel_hight))) {
            H = (x - wheel_x) / max_step;
            setTrackbarPos("Hue", window_name, H);
        }
        else if (((S_V_x <= x) && (x <= S_V_x + S_V_Width)) && ((S_V_y <= y) && (y <= S_V_y + S_V_Height))) {

            S = x - S_V_x;
            y = y - S_V_y;
            V = 255 - y;

            setTrackbarPos("Saturation", window_name, S);
            setTrackbarPos("Value", window_name, V);
        }

    }

}

void drawPointers() {
    // Point p(S_V_x+S,S_V_y+(255-V));
    Point p(S, 255 - V ...
(more)
edit flag offensive delete link more

Comments

Thank you very much! How can I run your code with Java (since yours is in C) or can I use gcc to compile your C code?

ashgabat gravatar imageashgabat ( 2014-02-25 00:27:49 -0500 )edit
1

HSV- is cylindrical co-ordinate system that's why red has different cut-off, that is for red you can see two hue range like 165-179 and 0-10. So for segmenting red just apply inrange() in these two range with different destination image and add up the result to get full red range.

Haris gravatar imageHaris ( 2014-02-25 01:10:02 -0500 )edit
1

Thats a nice answer. I am gonna have a hard time translating it to java. :(

Srinivasan Natarajan gravatar imageSrinivasan Natarajan ( 2015-03-30 02:15:57 -0500 )edit
Login/Signup to Answer

Question Tools

1 follower

Stats

Asked: 2014-02-23 23:30:42 -0500

Seen: 69,109 times

Last updated: Jun 21