Ask Your Question
1

Insane max Hue ranges?

asked 2015-03-24 12:12:41 -0600

215 gravatar image

updated 2015-10-26 11:09:55 -0600

I don't why.. but for some reason is my histogram showing that the max hue value of my image is around 339498 which doesn't make sense for me..

I am trying to create a mask, that recognizes the dominant color of the picture, and based on that creates a mask. I've converted my image to HSV , and created a histogram based on the Hue channel, for which i look at the highest value.

then I manually check each Hue-value in the picture, to create a binary image of the things that contains the dominant color.

But for some reason is my max Hue value too high no idea why.. here is the code.

#include <iostream>
#include "opencv2/opencv.hpp"

using namespace std;
using namespace cv;

int main(int argc, const char * argv[]) {
    std::cout << "Hello, World!\n";
    Mat src;
    src = imread("/Users/x/Desktop/IMG_3607.jpg");
    Mat src_HSV;
    cvtColor(src, src_HSV, CV_RGB2HSV);
    //vector<Mat> HSV_planes;
    //split(src_HSV, HSV_planes);
    int hbins = 30;
    int histSize[] = {hbins};
    float hranges[] = { 0, 180 };
    const float* ranges[] = { hranges };
    Mat hist;
    int channels[] = {0};

    calcHist(&src_HSV, 1, channels, Mat(), hist, 1, histSize, ranges,true,false);
    double maxVal=0;
    minMaxLoc(hist, 0, &maxVal, 0, 0);
    cout << "highest Hue value: " << maxVal << endl;
    Mat histImg = Mat::zeros(hbins*10,hbins*10, CV_8UC3);
    Mat result(src_HSV.rows,src_HSV.cols,CV_8UC1);
    for (int i = 0; i<src_HSV.rows; i++) {
        for (int j = 0; j<src_HSV.cols; j++) {
            Vec3b HSV = src_HSV.at<Vec3b>(i,j);
            if (HSV[0]==maxVal)
            {
                cout << "HSV Lower: " << HSV[0] << endl;
                result.at<uchar>(i,j) = 0;
            }
            else
            {
                cout << "HSV Higher': " << HSV[0] << endl;
                result.at<uchar>(i,j) = 255;
            }
        }
    }

    /// Draw for each channel
    for( int h = 0; h < hbins; h++ )
        for( int s = 0; s < hbins; s++ )
        {
            float binVal = hist.at<float>(h, s);
            int intensity = cvRound(binVal*255/maxVal);
            rectangle( histImg, Point(h*10, s*10),
                      Point( (h+1)*10 - 1, (s+1)*10 - 1),
                      Scalar::all(intensity),
                      CV_FILLED );
        }

    while (waitKey(1)) {
        imshow("Hue-channel",  src_HSV);
        //imshow("S-channel", HSV_planes[1]);
        //imshow("V-channel", HSV_planes[2]);
        imshow("histimage",histImg);
        imshow("result", result);
    }



    return 0;
}

test image image description

edit retag flag offensive close merge delete

Comments

@215 I do not think that there is a problem in your solution. Considering that you have an image of 816 x 612 dimensions (i.e. your test image above) it gives us 499392 pixels values. Now taking out the pixels values of the non-dominant colours, a value of 339498 pixels of the same/dominant colour = the highest peak in your histogram seems quite possible to me.

theodore gravatar imagetheodore ( 2015-03-24 19:47:01 -0600 )edit

So the value i receive isn't the highest Hue value, but "only" the amount of pixels which have the highest hue value.. How do i convert that number into a Hue value..

215 gravatar image215 ( 2015-03-25 08:43:49 -0600 )edit

just get the .col value of your hist image at that spot = peak. Since your hist image ranges between 0-180 you should get one of these values.

theodore gravatar imagetheodore ( 2015-03-25 09:01:24 -0600 )edit

I am not quite sure how you are going to do that.. At the moment am i just saving a point which contains the highest value, and thresholding it based on that.

215 gravatar image215 ( 2015-03-25 09:17:36 -0600 )edit

1 answer

Sort by ยป oldest newest most voted
1

answered 2015-03-25 09:43:34 -0600

theodore gravatar image

updated 2015-03-25 09:51:21 -0600

replace the following lines in your code:

double maxVal=0;
minMaxLoc(hist, 0, &maxVal, 0, 0);
cout << "highest Hue value: " << maxVal << endl;

with this:

double maxVal=0;
Point maxLoc;
cv::minMaxLoc(hist, 0, &maxVal, 0, &maxLoc);
cout << "highest Hue value: " << maxVal << "at the " << maxLoc.y << " bin." << endl; // maxLoc.y shows you in which bin you have the most of your pixels values
edit flag offensive delete link more

Comments

I want the highest Hue value, not the bin number.. I think i found a solution for my thresholding using the point as described above.. But the weird thing is.. I am now also calculating a histogram for the saturation, if use that, and come it against the the max Hue value, i get a pretty good filtration..

Mat result(HSV_planes[0].rows,HSV_planes[0].cols,CV_8UC1);
for (int i = 0; i<HSV_planes[0].rows; i++) {
    for (int j = 0; j<HSV_planes[0].cols; j++) {
        if (HSV_planes[1].at<uchar>(i,j)>(max_Hue))
        {
            //cout << "HSV Lower: " << HSV_planes[0].at<uchar>(i,j) << endl;
            result.at<uchar>(i,j) = 255;
        }
        else
        {
            //cout << "HSV Higher': " << HSV_planes[0].at<uchar>(i,j) <<
215 gravatar image215 ( 2015-03-25 09:56:47 -0600 )edit

Continued.. In which HSV_planes[], //[0] = hue channel, [1], saturation, [2] = value.

when i filter it get these results.. How come? http://imgur.com/5htzYZu

I would say it's pretty good results, but do not have any theory to support it.

215 gravatar image215 ( 2015-03-25 09:59:51 -0600 )edit
3

is there any specific reason that you are using as a histSize = 30 and not 180? the bin number then will correspond to the highest Hue value.

theodore gravatar imagetheodore ( 2015-03-25 10:08:07 -0600 )edit

Used a example from openCV.. But yeah, it makes sense to use 180..

215 gravatar image215 ( 2015-03-25 10:16:00 -0600 )edit

Question Tools

1 follower

Stats

Asked: 2015-03-24 12:12:41 -0600

Seen: 940 times

Last updated: Mar 25 '15