OpenCV Core.MinMaxLocResult返回什么?

时间:2014-02-07 21:55:06

标签: opencv colors histogram hue

我正在尝试做类似这篇文章的内容:Getting dominant colour value from HSV Histogram

我有一张图片,想要从中提取主色(Hue)。我已经达到了计算直方图的程度,并从minMaxLoc获得了maxValue。但是我从Core.MinMaxLocResult中检索的数字完全没有意义。我得到的东西像806924和1067036; Hue的预期值不应该在0到180之间吗?

直方图应该归一化吗?怎么会这样?我见过像“equalizeHist”和“normalize”这样的方法,但不知道如何使用这些方法以及它们如何帮助我。

另外,一旦我得到一个明智的“最常见的”Hue数字,我该如何将其转换为实际的色调(例如“绿色是此图像中最常出现的颜色”)?是否有标准的Hue范围?像0-10是红色,10-20是紫色等?

更新:这是我的代码:

    private void processImage(String imgFilename) {
            channels = new MatOfInt[] { new MatOfInt(0), new MatOfInt(1),
            new MatOfInt(2) };
    histSize = new MatOfInt(histSizeNum);
    hRanges = new MatOfFloat(0f, 180f); // hue varies from 0 to 179
    // use openCV stuff to convert from RGB to HLS space
    Mat src = Highgui.imread(imgFilename);
    Mat hls = new Mat();// destination color space
    Imgproc.cvtColor(src, hls, Imgproc.COLOR_RGB2HLS);
    Core.split(hls, hlsChannels);
    Mat hue = hlsChannels.get(0);
    Mat lum = hlsChannels.get(1);
    Mat sat = hlsChannels.get(2);
    // we compute the histogram from the 0-th channel for hue
    Imgproc.calcHist(Arrays.asList(hls), channels[0], new Mat(), hist,
            histSize, hRanges);

     Core.normalize(hist, hist, 0,2, Core.NORM_MINMAX, -1, new Mat());

    Core.MinMaxLocResult result = Core.minMaxLoc(hist);
    // max value should contain the most-recurring Hue value.
    double mostOccurringHue = result.maxVal;
    double leastOccurringHue = result.minVal;
    //double mostOccurringHue = result.maxLoc.x;
    //double leastOccurringHue = result.minLoc.x;

    // print out for sanity checking
    System.out.println("MAX HUE = " + Double.toString(mostOccurringHue) +"\n");
    System.out.println("MIN HUE = " + Double.toString(leastOccurringHue) +"\n");

3 个答案:

答案 0 :(得分:1)

我建议你再次检查一下你所提到的链接上的答案。你应该考虑以下几点:

- 您正在寻找主导颜色值,因此您应该只使用Hue频道。

- 你的陌生人应该是0-180。

-dims应该是1(而不是2),因为你只需要值直方图。

==>之后,maxValLoc将以“点”格式告诉您具有最大值的bin,其中point将包含x和y坐标。

例如:

double minVal; double maxVal; Point minLoc; Point maxLoc;
minMaxLoc( hist_image, &minVal, &maxVal, &minLoc, &maxLoc, Mat() );

现在你的“maxVal”将包含最大值和“maxLoc.y”& “maxLoc.x”将告诉您包含该最大值的点的行和列值。

答案 1 :(得分:1)

我没有使用openCV的ibuilt计算直方图及其规范化的方法,而是编写了我自己的代码,因为我们只为色调通道创建直方图。看看我的代码。

int main()
{

    Mat input = imread("jan31/class4Jan31.jpg",1);
    Mat hsv_input;
    int h_bins = 5;
    Mat hist_input = Mat::zeros( 1, h_bins, CV_32FC1);
    int h_range = 179;
    int totalNumberPixels = 0;

    cvtColor(input, hsv_input, CV_RGB2HSV);
    Mat hsv_channels[3];

    split( hsv_input, hsv_channels );

    for (int i=0; i<hsv_channels[0].rows; i++)
    {
        for (int j=0; j<hsv_channels[0].cols; j++)
        {               
            if( (int)hsv_channels[1].at<uchar>(i,j)>10 &&    (int)hsv_channels[1].at<uchar>(i,j)>100)
            {               
                totalNumberPixels++;
                int pixel_value = (int)hsv_channels[0].at<uchar>(i,j);
                int corresponding_bin =  ( pixel_value * h_bins ) / h_range;                
                hist_input.at<float>( 0, corresponding_bin ) = ( hist_input.at<float>( 0, corresponding_bin ) + 1 );                
            }                                                                                       
        }
    }

    cout<<"\n total pixels: "<<totalNumberPixels;

    for(int i=0; i<hist_input.rows; i++)
    {
        for (int j=0; j<hist_input.cols; j++)
        {
            float pixel = hist_input.at<float>(i,j);
            hist_input.at<float>(i,j) = pixel / totalNumberPixels;

            pixel = hist_input.at<float>(i,j);
            cout<<"\n Pixel: "<<pixel;
        }
    }

    cv::waitKey(0);
    return 0;
}

答案 2 :(得分:0)

如果您发布部分代码,那将是件好事。您可以通过以下方式标准化直方图:

normalize( hist_input, hist_input, 0, 2, NORM_MINMAX, -1, Mat() );  

要预测获得绿色范围,如果您自己检查绿色图像的H分量中的像素值,那将是一件好事。对我来说,这是在53-65岁。