Jose Ramon Jose Ramon - 2 months ago 18
C++ Question

Uniform histogram implementation in c++

I using the code of bytefish in order to calculate Local Binary Patterns (LBP) spatial uniform histograms for an image. I am using the the spatial_histogram function which calculates the histogram of local patches of image. Every calculated patch has size 256 so the final Mat hist file size is 1x(n*256). What I am trying to understand is how can I convert that histogram implementation to uniform histogram implementation. Implemented histogram code is the following:

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;
}
}


Uniform process is based on the following paper ( for local binary patterns) here.
A local binary pattern is called uniform if the binary pattern contains at most two bitwise transitions from 0 to 1 or vice versa when the bit pattern is considered circular.

Answer

[edit2] color reduction

  • that is easy it is just recoloring by the table uniform[256] has nothing to do with uniform histograms !!!

    1. create translation(recoloring) table for each possible color

      • for 8-bit gray-scale it is 256 colors
      • for example

        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 };
        
      • you can also compute it programaticaly like table[i]=(58*i)/255; for linear distribution

      • but I suggest it is more like this:

        recolor based on histogram example

        //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;
         }
        
      • set the threshold by area size or color count or whatever ...

    2. recolor color

      • color_59=table[color_256];
      • either recolor source image
      • or just change color value before used in histogram computation

That is all.

[edit1] LBP

  • I do not think is a good idea to compute histogram for LBP at all
    1. I would compute min and max color for sub image region you work with
    2. then convert colors to binary
      • if (color>=(max+min)/2) color=1; else color=0;
    3. now shift or them to form the LBP vector
      • 4x4 LBP example:
      • LBP =color[0][0];
      • LBP<<=1; LBP|=color[0][1];
      • LBP<<=1; LBP|=color[0][2];
      • ...
      • LBP<<=1; LBP|=color[3][3];
      • you can do the step 3 directly in step 2

[original answer] - now obsolete

Histogram is the probability/occurrence/count of distinct color(shade)

  • uniform histogram means that each colors have almost the same count/area in the whole image
  • by bins I assume you mean distinct colors not the sub-images

To combine sub-histogram

  • just add them together
  • or use single hist array init it once and then just sum to it as you have something like:

    ??? 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;
        }
    }
    
  • set init to true for the first patch call and false for all the rest

  • numPatterns is the max used color+1 or max possible colors count (not the distinct colors count)

If you want save only used colors

  • then you need to remember also the color;
  • int hist[][2],hists=0; or use some dynamic list template for that
  • the hist computation will change (will be much slower)

    1. take color
    2. test if it is in hist[i][0]==color
      • if yes increment its counter hist[i][1]++;
      • if not add new color hist[hists][0]=color; hist[hists][1]=1; hists++;
  • this will save space only if used colors are less then half of the possible ones

  • to improve performance you can compute hist normally
  • and recompute to this list after that in the same maner (instead of the increment part of coarse)