在Opencv中提取图像中的颜色百分比(红色,蓝色,绿色,黄色,橙色)?

时间:2014-01-30 16:49:40

标签: opencv colors hsv

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

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

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

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

红色: 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;
}

3 个答案:

答案 0 :(得分:1)

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

HSV允许您拥有H组件的任何值,并且:

  1. 高V,低S给白
  2. 低V为黑色
  3. 换句话说:如果你只用H分量判断,白色和黑色可以给你红色或绿色或橙色等等。

    我个人认为坚持使用RGB(或BGR无论如何),或者补偿S和V会影响颜色的事实。

答案 1 :(得分:0)

您可以使用函数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;

但根据应用程序的不同,它可能不是最佳的(例如,如果您需要扫描大量图像)。无论如何,你可以用它来比较价值。

答案 2 :(得分:0)

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

例如:

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

纯黑色被计为红色(HUE = 0),但是你会遇到蓝黑色(非常深蓝色)的问题。因此,应对要检测的所有颜色重复上一步骤。