【问题标题】:What does OpenCV Core.MinMaxLocResult return?OpenCV Core.MinMaxLocResult 返回什么?
【发布时间】:2014-03-05 11:58:12
【问题描述】:

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

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

直方图是否应该归一化?为何如此?我见过像“equalizeHist”和“normalize”这样的方法,但我真的不知道如何使用它们以及它们将如何帮助我。

另外,一旦我得到了一个合理的“最常出现”的色调数字,我如何将其转换为实际的颜色阴影(例如“绿色是这张图片中出现次数最多的颜色”)?有标准的色调范围吗?比如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");

【问题讨论】:

    标签: opencv colors histogram hue


    【解决方案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;
    }
    

    【讨论】:

    • 谢谢。我已经在我的代码中测试了这个概念,并且通过使用比你更多的垃圾箱,能够辨别出正确的颜色。但是,这只对我有用一次。之后,嵌套的 for 循环导致性能超级差;我的整个应用程序变慢了,而且我遇到了堆/分配问题。我在 Android 中做这一切,所以也许你没有遇到同样的问题?我认为内置的openCV直方图计算在内部效率更高。
    • 我没有遇到过这样的问题。对我来说,它只需要 4 毫秒。第二件事是,它比 opencv 的内置 calcHist() 具有更好的控制,因为在这种情况下,我们可以通过设置饱和度和 V 通道的一些阈值来消除白色和黑色像素,因此只能使用某些像素进行直方图计算。此外,正如您提到的那样,您增加了 bin 的数量,因此,即使 calcHist() 也随着 bin 数量的增加而变得非常慢,但是您想使用它,您可以尝试一下...它很容易使用它...
    【解决方案2】:

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

    -您正在寻找主要颜色值,因此您应该只使用色调通道。

    -你的 hranges 应该是 0-180。

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

    ==> 之后,maxValLoc 将以“Point”格式告诉您具有最大值的 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”将告诉您包含该最大值的点的行和列值。

    【讨论】:

    • 我已经用 Code 更新了我的帖子。你能检查一下吗?我已经考虑了您的所有建议,但仍然没有为“mostOccurringHue”变量获得有效的色调(0 到 180 之间)。我尝试了规范化和没有。
    • 我已经发布了另一个答案,其中包含自己创建色调直方图的代码......请看看它
    【解决方案3】:

    如果您发布部分代码会很好。您可以通过以下方式标准化直方图:

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

    要预测得到绿色的范围,最好检查一下绿色图像的 H 分量中的像素值。对我来说,53-65 是在撒谎。

    【讨论】:

      猜你喜欢
      • 2017-11-29
      • 2016-10-15
      • 2016-05-28
      • 1970-01-01
      • 2012-09-17
      • 2014-04-17
      • 2015-07-11
      • 1970-01-01
      • 2019-07-03
      相关资源
      最近更新 更多