Home > OS >  How to produce binned histogram from vector using std::map in C ?
How to produce binned histogram from vector using std::map in C ?

Time:11-09

I have a std::vector of float which contains 1300 data, i.e. {1.45890123, 1.47820920, 1.48326172, ...} I would like to build the histogram of the vector using std::map and then plot the histogram with OpenCV. This is how I use std::map to get the count of each data but I have no idea on how to do the binning?

size_t frames = 1300
float_t *tdata = (float_t *)malloc(frames * sizeof(float_t));

std::vector<float_t> hdata(tdata, tdata   frames);
std::vector<double> hdata_range, hdata_count;
std::map<float_t, int> hgram;
for (const auto &x : hdata)   hgram[x];
transform(hgram.begin(), hgram.end(), back_inserter(hdata_range), [](const auto& val){return val.first;});
transform(hgram.begin(), hgram.end(), back_inserter(hdata_count), [](const auto& val){return val.second;});

Then I do plotting of the histogram with OpenCV,

    Ptr<plot::Plot2d> plot_1b = plot::Plot2d::create(hdata_range, hdata_count);
    plot_1b->setNeedPlotLine(true);
    plot_1b->setShowText(false);
    plot_1b->setShowGrid(false);
    plot_1b->setPlotBackgroundColor(Scalar(255, 255, 255));
    plot_1b->setPlotLineColor(Scalar(0, 0, 0));
    plot_1b->setPlotLineWidth(5);
    plot_1b->setInvertOrientation(true);
    plot_1b->setPlotTextColor(Scalar(0, 0, 0));
    plot_1b->render(cv_display_hdata);

A window containing the histogram appears, but since I did not have binning, the counts are generally 1 for each data. But I would like to add binning to the histogram to produce the Gaussian (Normal) distribution histogram.

How can I do that with std::map?

Thanks, rolly

No binning histogram Matlab histogram

CodePudding user response:

If you want to use a std::map for binning data, you can simply choose the bin's starting value as the key. For that, divide by the bin size and then compute the floor. This will give you a whole number uniquely identifying the bin.

float_t binsize = 1.0f;
std::map<float_t, int> hgram;
for (auto x : hdata) {
      hgram[std::floor(x / binsize)];
}

To massage the histogram data range into the form used in your question, just scale the key by the bin size. You can choose whatever single value you want to represent the bin. It might be the start or end value of the bin. Or, in the example below I choose the center of the bin:

hdata_range.reserve(hgram.size());
hdata_count.reserve(hgram.size());
for (const auto& keyval : hgram)
{
    hdata_range.push_back((keyval.first   0.5f) * binsize);
    hdata_count.push_back(keyval.second);
}
  • Related