0
votes

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.

1
what do you mean by uniform histogram? you want to convert the image si it has uniform histogram or you just want to combine the sub-image histograms to the whole image histogram without computing it again? - Spektre
In the code provided there is a spatial histogram implementation for non-uniform histograms. I want to compress sub-image histograms(keeping only the 59 bins). - Jose Ramon
That is whole another question ... will reedit answer in a moment but it will be only my first insight to that paper (do not have the will to read it thoroughly) - Spektre
I am looking at Berak's code here answers.opencv.org/question/33988/… and trying to understand how it works. - Jose Ramon
Edited answer ... have no clue why color 58 is distributed as is ... but that i smost likely unused color just to improve texture features ... - Spektre

1 Answers

1
votes

[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 manner (instead of the increment part of coarse)