【问题标题】:Extracting the Percentage of color (Red,blue,green,yellow,orange) in an image in Opencv?在Opencv中提取图像中颜色(红色,蓝色,绿色,黄色,橙色)的百分比?
【发布时间】:2014-02-23 02:39:28
【问题描述】:

我必须区分 5 种类型的图像,这些图像可能主要是红色、绿色、蓝色、橙色或黄色,还有一些白色或黑色。我必须找到图像中突出的颜色。

图像的来源是网络摄像头,因此实际颜色还取决于图像与网络摄像头的照明和距离。可以在这里看到我的图像示例:

http://ian-albert.com/hazmat_placards/placard-2-flammable-gas.png

我正在尝试根据“色调”值计算百分比。我为每种颜色指定了一些范围。我的范围是:

红色: 0-10
绿色: 50-65

黄色: 18-21

蓝色: 100-115

问题:即使显示的图像不是红色,我的红色百分比仍然很高。

我的代码如下:

int findRect::checkByHSV(int svmResult, Mat detectedSquare)
{

    Mat hsv_img;
    cvtColor(detectedSquare,hsv_img,CV_BGR2HSV);

    Vec3b pixel;
    float totalPixel=0; // to count the total number of pixels in an image---to get the Percentage later
    float totalClass[6];// because we want to test for 5 classes+ a garbage class.{{ Class-0 -> Garbage, Class-1->Orange, Class-2->Green, Class-3->Red, 
                        //  Class-4->Blue, Class-5->Yellow }} 

    for(int i=0; i<hsv_img.rows; i++)
    {
        for (int j=0; j<hsv_img.cols; j++)
        {

            totalPixel++;
            pixel= hsv_img.at<Vec3b>(i,j);

            if(  pixel[0]>0 &&  pixel[0]<1  )           totalClass[1]++;    // Class-1->Orange
            else if (  pixel[0]>50 &&  pixel[0]<65  )   totalClass[2]++;    // To check Green class-2 //svmResult==2 && 
            else if (  pixel[0]>0 &&  pixel[0]<10  )        totalClass[3]++;    // Class-3->Red
            else if (  pixel[0]>100 &&  pixel[0]<115  )     totalClass[4]++;    // Class-4->Blue
            else if (  pixel[0]>18 &&  pixel[0]<21  )       totalClass[5]++;    // Class-5->Yellow
        }

    }

    float percentage[5];
    totalClass[0]=0; //Putting zero to the Garbage class

    for (int i=0; i<=5; i++)
    {
        percentage[i] = (totalClass[i] / totalPixel )*100;
    }

    cout<<"\n Organge: "<<percentage[1]<<"  Green: "<<percentage[2]<<"  Red: "<<percentage[3]<<"  Blue: "<<percentage[4]<<"  Yellow: "<<percentage[5]<<"\n \n";

    return svmResult;
}

【问题讨论】:

  • 图片是什么颜色的?此外,OpenCV 色相谱环绕。红色将是 0-10 和 170-180
  • @Osiris:正如我已经提到的,图像可以主要由红色、绿色、橙色、蓝色或黄色组成......还有一些黑色或白色。
  • 不,我指的是这张特殊的图片。你是说显示的图像不是红色的。你期待什么输出?也许您可以在帖子中包含图片。
  • 我无法在 SO 中嵌入图像。我的意思是任何不是红色的图像,即主要是绿色、蓝色或黄色。问题是,对于这些图像,我的红色百分比很高。
  • 黄色图像出现重大问题...

标签: opencv colors hsv


【解决方案1】:

问题是黑色或白色的 Hue=0(即红色)。但在这种情况下,饱和度非常低。您可以做的是将每个像素乘以某处的饱和度。

例如:

  • 使用阈值和 AND 运算,创建一个二值图像,其中“红色”像素为白色,所有非红色像素为黑色。
  • 将此图像乘以饱和度。现在您将获得一张灰度图像,显示每个像素的红色程度。
  • 如果您需要二值图像,您可以对第二张图像进行阈值处理

纯黑色算作红色 (HUE=0),但蓝黑色(非常深的蓝色)也会有同样的问题。因此,对于您想要检测的所有颜色,都应该重复前面的过程。

【讨论】:

    【解决方案2】:

    你提到你可以有一些白色和/或一些黑色。

    HSV 允许您为 H 组件设置任何值,并且:

    1. 高 V,低 S 产生白色
    2. 低 V 呈现黑色

    换句话说:如果你只根据 H 分量来判断,白色和黑色可以给你红色 OR 绿色 OR 橙色 OR ...等。

    我个人会说坚持使用 RGB(或 BGR 等),或者补偿 S 和 V 会影响颜色的事实。

    【讨论】:

    • 但我认为在 RGB 中会有很多组合来提取特定颜色,但在 HSV 中我可以直接从 HUE 组件中提取颜色。所有图像中的白色和黑色成分或多或少相同。图像因主色不同而不同,可能是红色、绿色、橙色、蓝色或黄色
    • 绿色 => 小红,小蓝,大部分是绿色。蓝色 => 小红,多为蓝,小绿。红色 => 主要是红色、小蓝、小绿。橙色=> 主要是红色、小蓝色、半绿色。黄色=> 多为红色,小蓝色,多为绿色。 Source
    【解决方案3】:

    您可以使用函数 countNonZero 并除以图像的总像素数。使用示例:

    vector<Mat> channels;
    split(hsv_img,channels);
    
    Mat red, blue, green;
    inRange(channels[0], Scalar(0), Scalar(10), red); // red
    // ... do the same for blue, green, etc only changing the Scalar values
    
    double image_size = hsv_img.cols*hsv_img.rows;
    double red_percent = ((double) cv::countNonZero(red))/image_size;
    

    但它可能不是最佳的,具体取决于应用程序(例如,如果您需要扫描大量图像)。无论如何,您可以使用它来比较值。

    【讨论】:

    • 感谢您的回复。您的答案似乎是结构化的,但我也通过使用其他代码来做同样的事情。实际上,输入图像会不断变化,光照也会发生变化。
    • 这不会有问题,只是重新加载图像并再次使用代码的问题。关于光照的变化,你可以在做操作之前均衡直方图。编辑:我没有看到你在问题中提到的网络摄像头。我认为可以实时运行代码。尝试测试,看看它是否有效。
    • 因为我没有得到想要的结果,所以我认为最好进行直方图匹配。
    • 现在,我想创建两个图像(输入图像和样本图像)的直方图。因为,这两个图像的大小几乎相似,所以我不想在另一个上滑动来计算某个窗口上的直方图......你能告诉我我该怎么做吗?
    • 您可以提出新问题作为您的评论。我不确定我是否理解幻灯片部分,但要比较/匹配直方图,请查看本教程:docs.opencv.org/doc/tutorials/imgproc/histograms/…
    猜你喜欢
    • 2011-10-28
    • 1970-01-01
    • 2012-04-25
    • 2011-05-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-07-07
    • 2020-06-10
    相关资源
    最近更新 更多