0
votes

I have a data set of paired values like (x,y). For example: x ranges from -40 to 60 and y from 0 to 100. Initially they are stored in a std::vector<std::pair<float,float>> but in a loop I convert them to a 2 channel cv::Mat to be able to pass it to OpenCV's cv::calcHist function. I'd like to achieve a 1D histogram like so: here. Since I actually have two data ranges, I always end up with a 2D Histogram as a result cv::Mat from cv::calcHist, but I basically would like to calculate based on a given bin_size x_bin for the x-axis the average of values in y.

Take as an example: x ranges from -40 to 60, desired bins = 10, bin_size = 10, data points (x,y): (-35, 10), (-39, 20) The 1D histogram would then need to calculate the average of y = (10+20)/2 for the bin range from -40 to -30.

So the sum of each bin shouldn't be a simple count of values falling in that specific bin range but rather the average of values.

I hope I could state the problem in an understandable way. Any help is appreciated.

1

1 Answers

1
votes

I don't think OpenCV's cv::calcHist would be able to give you what you want, especially because you are trying to get stats on Y based on X. Anyway, it's not too hard to do it without OpenCV.

void calcHist(const std::vector<std::pair<float, float>>& data, const float min_x, const float max_x, const int num_bins, std::vector<float>& hist)
{
  hist.resize(num_bins, 0.f);
  std::vector<int> hist_counts(num_bins, 0);
  float bin_size = (max_x-min_x)/num_bins;
  for (const auto& p : data) {
    // Assign bin
    int bin = static_cast<int>((p.first-min_x)/bin_size);
    // Avoid out of range
    bin = std::min(std::max(bin, 0), num_bins-1);
    hist[bin] += p.second;
    hist_counts[bin]++;
  }
  // Compute average
  for (int i = 0;i < num_bins; ++i) {
    if (hist_counts[i]) {
      hist[i] /= static_cast<float>(hist_counts[i]);
    }
  }
}