Ask Your Question
0

How to draw a circle on a histogram

asked 2018-10-19 13:27:04 -0600

sjhalayka gravatar image

updated 2018-10-19 16:24:36 -0600

I'm trying to draw a circle at the most populated bin in the histogram. I've tried a lot of things, but I just can't figure it out:

Mat data(1, total_lengths.size(), CV_8UC1, Scalar(0));

// ...

int histSize = 256;
float range[] = { 0, 256 }; //the upper boundary is exclusive
const float* histRange = { range };
bool uniform = true, accumulate = false;
Mat hist;
calcHist(&data, 1, 0, Mat(), hist, 1, &histSize, &histRange, uniform, accumulate);

int hist_w = 600, hist_h = 600;
int bin_w = cvRound((double)hist_w / histSize);
Mat histImage(hist_h, hist_w, CV_8UC3, Scalar(255, 255, 255));
normalize(hist, hist, 0, histImage.rows, NORM_MINMAX, -1, Mat());

float largest_hist = 0;
float largest_hist_j = 0;
float largest_hist_i = 0;

for (int j = 0; j < hist.rows; j++)
{
    for (int i = 0; i < hist.cols; i++)
    {
        if (hist.at<float>(j, i) > largest_hist)
        {
            largest_hist = hist.at<float>(j, i);
            largest_hist_j = j;
            largest_hist_i = i;
        }
    }
}

for (int i = 1; i < histSize; i++)
{
    line(histImage, Point(bin_w*(i - 1), hist_h - cvRound(hist.at<float>(i - 1))),
        Point(bin_w*(i), hist_h - cvRound(hist.at<float>(i))),
        Scalar(0, 0, 0), 1, 8, 0);
}

// this is where it goes haywire
largest_hist_j /= hist.rows;
largest_hist_j *= hist_w;


circle(histImage, Point(largest_hist_j, 0), 2, Scalar(255, 127, 0), 2);

imshow("calcHist Demo", histImage);
waitKey();
edit retag flag offensive close merge delete

Comments

1

E_NEEDS_MORE_COFFEE. (clear lack of concentration here ;)

Point(largest_hist_i * bin_w, hist_h - largest_hist)

also remember, that a histogram is an 1d array (in a 2d Mat), so j is always 0.

berak gravatar imageberak ( 2018-10-20 01:17:55 -0600 )edit

I made two small changes to your code and it now works perfectly (on normalized histograms):

Point(largest_hist_j * bin_w, 0)

Thanks again @berak!

sjhalayka gravatar imagesjhalayka ( 2018-10-20 13:40:31 -0600 )edit

1 answer

Sort by ยป oldest newest most voted
0

answered 2018-10-20 13:44:43 -0600

sjhalayka gravatar image

updated 2018-10-20 13:46:42 -0600

Thanks to @berak, the answer (for normalized histograms) is:

Mat data(1, total_lengths.size(), CV_8UC1, Scalar(0));

// ...

int histSize = 256;
float range[] = { 0, 256 }; //the upper boundary is exclusive
const float* histRange = { range };
bool uniform = true, accumulate = false;
Mat hist;
calcHist(&data, 1, 0, Mat(), hist, 1, &histSize, &histRange, uniform, accumulate);

int hist_w = 600, hist_h = 600;
int bin_w = cvRound((double)hist_w / histSize);
Mat histImage(hist_h, hist_w, CV_8UC3, Scalar(255, 255, 255));
normalize(hist, hist, 0, histImage.rows, NORM_MINMAX, -1, Mat());

float largest_hist = 0;
float largest_hist_j = 0;

for (int j = 0; j < hist.rows; j++)
{
    for (int i = 0; i < hist.cols; i++)
    {
        if (hist.at<float>(j, i) > largest_hist)
        {
            largest_hist = hist.at<float>(j, i);
            largest_hist_j = j;
        }
    }
}

for (int i = 1; i < histSize; i++)
{
    line(histImage, Point(bin_w*(i - 1), hist_h - cvRound(hist.at<float>(i - 1))),
        Point(bin_w*(i), hist_h - cvRound(hist.at<float>(i))),
        Scalar(0, 0, 0), 1, 8, 0);
}

circle(histImage, Point(largest_hist_j * bin_w, 0), 2, Scalar(255, 127, 0), 2);

imshow("calcHist Demo", histImage);
waitKey();
edit flag offensive delete link more

Question Tools

1 follower

Stats

Asked: 2018-10-19 13:27:04 -0600

Seen: 285 times

Last updated: Oct 20 '18