使用C ++中预定义数量的bin构建直方图

时间:2018-04-12 09:26:33

标签: c++ key histogram bins

我想在C ++中构建一个具有由键定义的预定数量的bin(在这种情况下为12 * 5 = 60)的直方图,并且不知道如何操作。这是一个最低限度的例子:

using namespace std;
using namespace cv;

// Function to calculate the keys defining specific ranges of r1 and theta_1
void getKeys(vector<float> r1_vector, vector<float> theta_1_vector, vector<vector<float>> &keys) {
    int r1_bin = 0;
    int r2_bin = 0;
    int theta1_bin = 0;

    vector<float> key;

    // r1 is divided equally into 5 bins ranging from -0.3 to 1.3

    for (size_t i = 0; i < r1_vector.size(); i++) {
        if (-0.3 <= r1_vector[i] && r1_vector[i] < 0.02) {
            r1_bin = 1;
        }
        else if (0.02 <= r1_vector[i] && r1_vector[i] < 0.34) {
            r1_bin = 2;
        }
        else if (0.34 <= r1_vector[i] && r1_vector[i] < 0.66) {
            r1_bin = 3;
        }
        else if (0.66 <= r1_vector[i] && r1_vector[i] < 0.98) {
            r1_bin = 4;
        }
        else if (0.98 <= r1_vector[i] && r1_vector[i] <= 1.30) {
            r1_bin = 5;
        }

    // theta_1 is divided equally into 12 bins ranging from 0 to 2*PI

        if (0 <= theta_1_vector[i] && theta_1_vector[i] < CV_PI / 6) {
            theta1_bin = 1;
        }
        else if (CV_PI / 6 <= theta_1_vector[i] && theta_1_vector[i] < CV_PI / 3) {
            theta1_bin = 2;
        }
        else if (CV_PI / 6 <= theta_1_vector[i] && theta_1_vector[i] < CV_PI / 2) {
            theta1_bin = 3;
        }
        else if (CV_PI / 2 <= theta_1_vector[i] && theta_1_vector[i] < 2 * CV_PI / 3) {
            theta1_bin = 4;
        }
        else if (2 * CV_PI / 3 <= theta_1_vector[i] && theta_1_vector[i] < 5 * CV_PI / 6) {
            theta1_bin = 5;
        }
        else if (5 * CV_PI / 6 <= theta_1_vector[i] && theta_1_vector[i] < CV_PI) {
            theta1_bin = 6;
        }
        else if (CV_PI <= theta_1_vector[i] && theta_1_vector[i] < 7 * CV_PI / 6) {
            theta1_bin = 7;
        }
        else if (7 * CV_PI / 6 <= theta_1_vector[i] && theta_1_vector[i] < 4 * CV_PI / 3) {
            theta1_bin = 8;
        }
        else if (4 * CV_PI / 3 <= theta_1_vector[i] && theta_1_vector[i] < 3 * CV_PI / 2) {
            theta1_bin = 9;
        }
        else if (3 * CV_PI / 2 <= theta_1_vector[i] && theta_1_vector[i] < 5 * CV_PI / 3) {
            theta1_bin = 10;
        }
        else if (5 * CV_PI / 3 <= theta_1_vector[i] && theta_1_vector[i] < 11 * CV_PI / 6) {
            theta1_bin = 11;
        }
        else if (11 * CV_PI / 6 <= theta_1_vector[i] && theta_1_vector[i] <= 2 * CV_PI) {
            theta1_bin = 12;
        }

        key.push_back(r1_bin);
        key.push_back(theta1_bin);
        keys.push_back(key);
        key.clear();
    }   
}



int main(int argc, char** argv)
{
    // Create some values - both vectors have the same size
    vector<float> r1_vec;
    r1_vec.push_back(-0.2);
    r1_vec.push_back(1.2);
    r1_vec.push_back(0.2);
    r1_vec.push_back(0.3);
    r1_vec.push_back(0.35);
    r1_vec.push_back(0.2);
    r1_vec.push_back(0.8);
    r1_vec.push_back(0.8);

    vector<float> theta_vec;
    theta_vec.push_back(1.4);
    theta_vec.push_back(2.4);
    theta_vec.push_back(3.7);
    theta_vec.push_back(2.4);
    theta_vec.push_back(1.5);
    theta_vec.push_back(1.6);
    theta_vec.push_back(2.4);
    theta_vec.push_back(5.8);

    vector<vector<float>> keys;
    getKeys(r1_vec, theta_vec, keys);

    // Print values
    /*for (size_t i = 0; i < keys.size(); i++) {    
            cout << "The keys for line one are: " << keys[i][0] << ", " << keys[i][1]  << endl;
    }*/

}

现在我不知道如何处理theta_1的12个箱子,因为我的箱子不能简单地计算从1到60。我还记得,可能有比构建直方图更好的方法(例如unordered_map,map,bucket_sort或类似的东西)。但因此我需要特定/唯一类型的键。 所以最后我想计算每对键的出现次数(例如[2,12]有10个出现)。
它们的键可能不仅仅是成对,而是三倍或四倍,并存储在vector<vector<float>>中。

2 个答案:

答案 0 :(得分:1)

如何将它存储在地图中呢?然后,您可以通过地图进行交互以获取键和出现。

class Histogram
{
  map<int, int> HistMap; //key is the bin, value is count in bin

  void InsertIntoHMap(int);
  void CheckR1(float);
  void CheckTheta1(float);

 public:
   Histogram() {}
   void FillHistMap(vector<float>&, vector<float>&);
   map<int, int>& GetHMap();
   ~Histogram() {}
 };

 void Histogram::InsertIntoHMap(int bin)
 {
    if(HistMap.find(bin) == HistMap.end()) HistMap.insert({bin, 1});
    else HistMap[bin]++;
 }

 void Histogram::CheckR1(float r1)
 {
   if      (-0.3 <= r1 && r1 < 0.02)  InsertIntoHMap(1);
   else if (0.02 <= r1 && r1 < 0.34)  InsertIntoHMap(2);
   else if (0.34 <= r1 && r1 < 0.66)  InsertIntoHMap(3);
   else if (0.66 <= r1 && r1 < 0.98)  InsertIntoHMap(4);
   else if (0.98 <= r1 && r1 <= 1.30) InsertIntoHMap(5);
 }

 void Histogram::CheckTheta1(float t1)
 {
 // theta_1 is divided equally into 12 bins ranging from 0 to 2*PI

    if      (0 <= t1 && t1 < CV_PI / 6)                   InsertIntoHMap(1);       
    else if (CV_PI / 6 <= t1 && t1 < CV_PI / 3)           InsertIntoHMap(2);    
    else if (CV_PI / 6 <= t1 && t1 < CV_PI / 2)           InsertIntoHMap(3);      
    else if (CV_PI / 2 <= t1 && t1 < 2 * CV_PI / 3)       InsertIntoHMap(4); 
    else if (2 * CV_PI / 3 <= t1 && t1 < 5 * CV_PI / 6)   InsertIntoHMap(5);     
    else if (5 * CV_PI / 6 <= t1 && t1 < CV_PI)           InsertIntoHMap(6);
    else if (CV_PI <= t1 && t1 < 7 * CV_PI / 6)           InsertIntoHMap(7);     
    else if (7 * CV_PI / 6 <= t1 && t1 < 4 * CV_PI / 3)   InsertIntoHMap(8);   
    else if (4 * CV_PI / 3 <= t1 && t1 < 3 * CV_PI / 2)   InsertIntoHMap(9);
    else if (3 * CV_PI / 2 <= t1 && t1 < 5 * CV_PI / 3)   InsertIntoHMap(10);    
    else if (5 * CV_PI / 3 <= t1 && t1 < 11 * CV_PI / 6)  InsertIntoHMap(11);      
    else if (11 * CV_PI / 6 <= t1 && t1 <= 2 * CV_PI)     InsertIntoHMap(12)        
}

 void Histogram::FillHistMap(vector<float>& r1_vector, vector<float>& theta_1_vector)
 {
   for (size_t i = 0; i < r1_vector.size(); i++)
   {
       CheckR1(r1_vector[i]);
       CheckTheta1(theta_1_vector[i]);  
   }
 }

int main()
{
   vector<float> r1_vec;
   r1_vec.push_back(-0.2);
   r1_vec.push_back(1.2);
   r1_vec.push_back(0.2);
   r1_vec.push_back(0.3);
   r1_vec.push_back(0.35);
   r1_vec.push_back(0.2);
   r1_vec.push_back(0.8);
   r1_vec.push_back(0.8);

   vector<float> theta_vec;
   theta_vec.push_back(1.4);
   theta_vec.push_back(2.4);
   theta_vec.push_back(3.7);
   theta_vec.push_back(2.4);
   theta_vec.push_back(1.5);
   theta_vec.push_back(1.6);
   theta_vec.push_back(2.4);
   theta_vec.push_back(5.8);

    Histogram H;
    H.FillHistMap(r1_vec, theta_vec);

}

答案 1 :(得分:0)

类似的东西怎么样

#include <map>
#include <random>
#include <iostream>

struct histogram
{
  histogram(const std::initializer_list<double>& edges)
  {
    for (auto e : edges) _bins[e] = 0;
  }
  histogram(size_t n, double low, double high)
  {
    double x  = low;
    double dx = (high-low) / n;
    while (x <= high) { _bins[x] = 0; x += dx; }
  }
  void fill(double val)
  {
    if (val < _bins.begin()->first || val > _bins.rbegin()->first) 
      return;

    std::prev(_bins.upper_bound(val))->second++;
  }
  void print(std::ostream& o) const
  {
    for (auto b1 = _bins.begin(), b2 = std::next(b1) ;
     b2 != _bins.end(); ++b1, ++b2) 
      o << b1->first << "\t- " << b2->first << ":\t"
    << std::string(b1->second,'*')
    << std::endl;
  }
  std::map<double,size_t> _bins;
};
  
int main()
{
  std::default_random_engine       rnd(12345);
  std::normal_distribution<double> norm(0,1);
    
  histogram h1(6,-3,3);
  histogram h2{-3,-2,-1,0,1,2,3};
  
  for (size_t i = 0; i < 100; i++) {
    auto x = norm(rnd);
    h1.fill(x);
    h2.fill(x);
  }

  std::cout << "h1: " << std::endl;
  h1.print(std::cout);

  std::cout << "h2: " << std::endl;
  h2.print(std::cout);
  
  return 0;
}

这使用 std::map<K,V>::lower_bound 来查找 bin。剩下的主要是糖。