OpenCV中的HSV图像用于颜色识别

3
我有一张BGR图像(一辆车的前部),我想识别它的颜色。

enter image description here

我将其转换为HSV(我知道imshow()不理解HSV,会将其打印为BGR) enter image description here 1: 现在,我想获取色调值并知道它属于哪个范围以识别颜色。
- 如何计算色调的数量或值? - 如何指定范围?使用标量方法会给出BGR范围。
代码
int main()
{
    Mat image;
    image = imread("carcolor.png", CV_LOAD_IMAGE_COLOR);

    if (!image.data)
    {
        cout << "Could not open or find the image" << std::endl;
        return -1;
    }

    // Create a new matrix to hold the HSV image
    Mat HSV;

    // convert RGB image to HSV
    cvtColor(image, HSV, CV_BGR2HSV);

    namedWindow("Display window", CV_WINDOW_AUTOSIZE);
    imshow("Display window", image);

    namedWindow("Result window", CV_WINDOW_AUTOSIZE);
    imshow("Result window", HSV);


    vector<Mat> hsv_planes;
    split(HSV, hsv_planes);
    Mat h = hsv_planes[0]; // H channel
    Mat s = hsv_planes[1]; // S channel
    Mat v = hsv_planes[2]; // V channel

    namedWindow("hue", CV_WINDOW_AUTOSIZE);
    imshow("hue", h);
    namedWindow("saturation", CV_WINDOW_AUTOSIZE);
    imshow("saturation", s);
    namedWindow("value", CV_WINDOW_AUTOSIZE);
    imshow("value", v);



    //// red color range
    Scalar hsv_l(170, 150, 150);
    Scalar hsv_h(180, 255, 255);
    Mat bw;
    inRange(HSV, hsv_l, hsv_h, bw);
    imshow("Specific Colour", bw);
    ////

    // hue value

    //define ranges

    waitKey(0);
    return 0;
}

请展示一张"特定颜色"窗口的图片。您的inRange代码看起来没问题,但也许范围不正确。红色有两个色调范围,从0到x和从180-x到180。 - Micka
@Micka inRange函数在原始BGR图像中并不能检测到所有的红色区域,它只能检测到在HSV图像中得到的红色触摸部分。 - Maram
正如我所说,由于色相颜色空间的循环性,红色色彩范围被分成两个范围。请查看我的答案,您需要两个范围来提取整个红色色彩范围。或者,您可以通过使用 hueVal = (hueVal+50)%180 来移动整个色相通道,这样红色就会以色相值50为中心。 - Micka
1个回答

2
Hue是一个圆形范围,红色恰好位于该圆的起始/结束位置,因此红色Hue值由两个不同的范围覆盖:[0 .. n][360-n .. 360]。正如您在代码中使用的那样,由于字节覆盖,openCV还将整个范围减半为[0 .. 180]
因此,除了Scalar hsv_l(170, 150, 150);Scalar hsv_h(180, 255,255);之外,您还需要第二个范围。
查找范围的完整代码可能是:
//// red color rangeS
int redRange = 10;

Scalar hsv_upper_l(180-n, 150, 150);
Scalar hsv_upper_h(180, 255, 255);
Mat red_hue_upper;
inRange(HSV, hsv_upper_l, hsv_upper_h, red_hue_upper);

Scalar hsv_lower_l(0, 150, 150);
Scalar hsv_lower_h(0+n, 255, 255);
Mat red_hue_lower;
inRange(HSV, hsv_lower_l, hsv_lower_h, red_hue_lower);

cv::Mat whole_red_hue = red_hue_lower | red_hue_upper;

imshow("Specific Colour", whole_red_hue);

将这个输入转化为那个输出:

在此输入图像描述 在此输入图像描述

对于不同的颜色,这会更容易(因为它们没有放置在圆的起点/终点附近):

int hueCenter = ...; // any hue value of the color
int hueRange = 10; // or any other range
cv::Mat hueMask;
inRange(HSV, Scalar(hueCenter-hueRange, 150, 150), Scalar(hueCenter+hueRange, 255, 255), hueMask);

希望这能帮到你。

如果你想要遮盖更多的白色/黑色区域,你需要将下限饱和度范围提高到200,下限值范围提高到230。 - Micka
你的代码中的“n”是什么?抱歉问这个新手问题,我对opencv非常陌生。我也想在图像中检测颜色。 - harsh

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接