c ++中的统一直方图实现

时间:2014-11-20 12:16:03

标签: c++ histogram

我使用bytefish的代码来计算图像的局部二值模式(LBP)空间均匀直方图。我正在使用spatial_histogram函数来计算局部图像块的直方图。每个计算的补丁的大小为256,因此最终的Mat hist文件大小为1x(n * 256)。我想要了解的是如何将直方图实现转换为统一的直方图实现。实现的直方图代码如下:

void lbp::histogram_(const Mat& src, Mat& hist, int numPatterns) {
hist = Mat::zeros(1, numPatterns, CV_32SC1);
for(int i = 0; i < src.rows; i++) {
    for(int j = 0; j < src.cols; j++) {
        int bin = src.at<_Tp>(i,j);
        hist.at<int>(0,bin) += 1;
    }
}

统一过程基于以下文章(针对本地二进制模式) here。 如果二进制模式包含从0到1的最多两个按位转换,或者当位模式被认为是圆形时,则本地二进制模式称为均匀。

1 个答案:

答案 0 :(得分:1)

[edit2]色彩还原

这很简单,只需通过表格uniform[256]进行重新加工就与统一直方图无关!!!

  1. 为每种可能的颜色创建翻译(重新着色)表

    对于8位灰度,它是256色,例如:

    BYTE table[256] = {
            0,1,2,3,4,58,5,6,7,58,58,58,8,58,9,10,11,58,58,58,58,58,58,58,12,58,58,58,13,58,
            14,15,16,58,58,58,58,58,58,58,58,58,58,58,58,58,58,58,17,58,58,58,58,58,58,58,18,
            58,58,58,19,58,20,21,22,58,58,58,58,58,58,58,58,58,58,58,58,58,58,58,58,58,58,58,
            58,58,58,58,58,58,58,58,58,58,58,58,23,58,58,58,58,58,58,58,58,58,58,58,58,58,
            58,58,24,58,58,58,58,58,58,58,25,58,58,58,26,58,27,28,29,30,58,31,58,58,58,32,58,
            58,58,58,58,58,58,33,58,58,58,58,58,58,58,58,58,58,58,58,58,58,58,34,58,58,58,58,
            58,58,58,58,58,58,58,58,58,58,58,58,58,58,58,58,58,58,58,58,58,58,58,58,58,58,
            58,35,36,37,58,38,58,58,58,39,58,58,58,58,58,58,58,40,58,58,58,58,58,58,58,58,58,
            58,58,58,58,58,58,41,42,43,58,44,58,58,58,45,58,58,58,58,58,58,58,46,47,48,58,49,
            58,58,58,50,51,52,58,53,54,55,56,57 };
    

    您也可以像table[i]=(58*i)/255;一样进行线性分布计算,但我建议它更像基于直方图示例的重新着色:

    //hist[256] - already computed classic histogram
    //table[59] - wanted recolor table
    void compute_table(int *table,int *hist)
     {
     int i,c,threshold=1;
     for (c=-1,i=0;i<256;i++)
      if (hist[i]>threshold) { c++; table[i]=c; }
       else table[i]=58;
     }
    

    按区域大小或颜色计数等设置阈值......

  2. 重新着色

    color_59=table[color_256];重新着色源图像或仅在用于直方图计算之前更改颜色值

  3. 就是这样。

    [edit1] LBP

    我认为计算 LBP 的直方图不是一个好主意

    1. 我会为您使用的子图像区域计算minmax颜色
    2. 然后将颜色转换为二进制

      if (color>=(max+min)/2) color=1; else color=0;
      
    3. 现在转移+或它们以形成 LBP 向量

      4x4 LBP示例:

                LBP =color[0][0];
       LBP<<=1; LBP|=color[0][1]; 
       LBP<<=1; LBP|=color[0][2]; 
       ...
       LBP<<=1; LBP|=color[3][3];
      

      您可以直接在步骤#2

    4. 中执行#3 步骤

      [原始答案] - 现已过时

      直方图是不同颜色(阴影)的概率/发生/计数

      • 统一直方图意味着每种颜色在整个图像中具有几乎相同的计数/面积
      • by bins我假设你的意思是不同的颜色而不是子图像

      组合子直方图

      只需将它们组合在一起或使用单个hist数组初始化一次,然后只需求它就可以得到它:

      ??? hist=Mat::zeros(1, numPatterns, CV_32SC1);
      
      void lbp::histogram_(const Mat& src, Mat& hist, int numPatterns, bool init) {
      if (init) hist = Mat::zeros(1, numPatterns, CV_32SC1);
      for(int i = 0; i < src.rows; i++) {
          for(int j = 0; j < src.cols; j++) {
              int bin = src.at<_Tp>(i,j);
              hist.at<int>(0,bin) += 1;
          }
      }
      

      第一个补丁调用将init设置为true,其余所有补丁设置为false。 numPatterns是最大使用颜色+ 1或最大可能颜色数(不是不同颜色数)

      如果您想只保存使用的颜色

      然后你还需要记住颜色。 int hist[][2],hists=0;或者使用一些动态列表模板,因为hist计算会改变(会慢得多)。

      1. 采取颜色
      2. 测试它是否在hist[i][0]==color

        如果是,则递增其计数器hist[i][1]++;
        如果没有添加新颜色hist[hists][0]=color; hist[hists][1]=1; hists++;

      3. 只有当使用的颜色少于可能颜色的一半时,才能节省空间。为了提高性能,您可以正常计算hist,然后以相同的方式重新计算到此列表(而不是粗略的增量部分)