Click here to Skip to main content
15,888,527 members
Articles / LBP

Uniform LBP Features and Spatial Histogram Computation

Rate me:
Please Sign up or sign in to vote.
5.00/5 (2 votes)
8 May 2014CPOL3 min read 16K   2  
Uniform LBP Features and Spatial Histogram computation

Introduction

In the earlier article, we had seen that we had computed a LBP image. Each pixel in this image still can take $2^8$ possible values. The idea of uniform LBP is to perform lossy encoding so that we eliminate some irrelevant data and retain useful information which takes on 58 possible values. In this article, we will look at Uniform LBP and computation of Spatial Histogram of LBP which can be used as a feature for image description.

  • Uniform LBP features are considered as one which has only 2 contiguous regions corresponding to 0's and 1's, while non uniform LBP have more than 1 contiguous regions corresponding to 0's and 1's.
  • This we need a mapping from which assign each on $2^8$ possible codes to one of 58 encoded uniform LBP values.
  • All the non uniform codes are assigned to a single values.
  • The uniform LBPs can be viewed as corners, line, ramp gradient
  • The non uniform LBPs are assumed to be irrelevant and can be ignored.
  • A uniform binary pattern can be identified by performing a bit wise traversal and checking if number of bit transitions are at most 2 .
  • This is done by first circular right/left shifting the given code and performing XOR operation with the original code.
  • Since we need to only consider 8 bit numbers, we need perform circular shift and masking MSB for integers.
    C++
    1    int rightshift(int num, int shift)
    2    {
    3        //right shift the number to right
    4    //left shift numbers and mask the MSB for 8 bit number
    5        return (num >> shift) | ((num << (8 - shift)&0xFF));
    6    }
  • Now number of bit operations is simply the number of set bits in the result.
  • The code for this can be as follows:
    C++
    01    int countSetBits(int code)
    02    {
    03      int count=0;
    04      while(code!=0)
    05      {
    06      if(code&&0x01)
    07      count++;
    08      code=code>>1;
    09      }
    10      return count;
    11    }
    12    bool checkUniform(int code)
    13    {
    14      int b = rightshift(code,1);
    15      int c = code ^ b;
    16      int count=countSetBits(c);
    17      if (count <=2)
    18      return true;
    19      else
    20      return false;
    21    }
  • The method to count bits is a naive way and since we are using 8 bit words, it will take 8 iterations of the for loop.
  • Brian Kernighan's method performs this by going through as many iterations as set bits:
    C++
    01    int countSetBits(int code)
    02    {
    03      int count=0;
    04      int v=code;
    05      for(count=0;v;count++)
    06      {
    07      v&=v-1; //clears the LSB
    08      }
    09      return count;
    10    }
  • The result can be precomputed for possible input code to determine if a LBP is a uniform code or not.
  • The next task is to map the LBP codes to one of 58 uniform codes.
  • The encoding will be done along the rows as per the below figure:

    Image 1

    LBP Patterns
  • Since we know the possible input codes beforehand, we can prepare a lookup table beforehand to check if there is a uniform code or not
  • Now if it is a uniform code, we need to map it to one of possible 58 codes.
  • To do this, we move from all numbers from $0-2^8$, check if they are uniform and assign them to a one of 58 possible codes.
  • However we can see then:
    C++
    01    //3x3 neighborhood will have 8 neighborhood pixels
    02    //all non uniform codes are assigned to 59
    03    void initUniform()
    04    {
    05        lookup.resize(255);
    06        int index=0;
    07        for(int i=0;i<=255;i++)
    08        {
    09            bool status=checkUniform(i);
    10            if(status==true)
    11            {
    12                lookup[i]=index;               
    13                index++;
    14            }
    15            else
    16            {
    17                lookup[i]=59;
    18            }
    19        }20         
    21    }
  • Thus we modify the existing lbp image code to return only uniform lbp coded as destination lbp image by performing a simple lookup operations.
  • Now, the next task is to compute a spatial histogram, the histogram may be computed over the entire image or dividing the image into grids:
    C++
    01    ocv::Histogram hist; //class for computing histogram
    02     
    03        vector<float> spatialHistogram(Mat lbpImage,Size grid)
    04       {               
    05       //feature vector
    06           vector<float> histogram;
    07        
    08           histogram.resize(grid.width*grid.height*59);
    09           int width=lbpImage.cols/grid.width;
    10           int height=lbpImage.rows/grid.height;
    11       int cnt=0;
    12           //#pragma omp parallel for
    13           for(int i=0;i<grid.height;i++)
    14           {
    15               for(int j=0;j<grid.width;j++)
    16               {
    17                   Mat cell=lbpImage(Rect(j*width,i*height,width,height));
    18                   Mat cell_hist=computeHistogram(cell);
    19                   Mat tmp_feature;
    20                   //reshape the feature vector into 1 row
    21                   cell_hist.reshape(1,1).convertTo(tmp_feature,CV_32FC1);
    22                   float * ptr=tmp_feature.ptr<float>(0);
    23                   for(int k=0;k<tmp_feature.cols;k++)
    24                   {
    25               //if no LBP feature is found assing it a small value
    26               if(ptr[k]==0)
    27               ptr[k]=1/58;
    28               //update the histogram vector
    29                       histogram[cnt*59+k]=ptr[k];
    30                   }
    31                   cnt++;
    32               }
    33           }
    34     
    35           return histogram;
    36       }
  • The LBP spatial histogram can be used as a texture descriptor.
  • However the LBP image is a gradient image in some sense, it encodes information about different types of gradients.
  • The LBP pattern can be used to identify isolated corners or flat region (all 0 or 1).
  • The LBP pattern can be used to identify corner a continuous run of 0 or 1 of length (5-8 and its rotated version).
  • The LBP pattern can be used to identify a edge a continuous run of 0 or 1(length 4 and rotated version).
  • The LBP pattern can be used to identify horizontal or vertical edge (vertical/horizontal run of 0 and 1).
  • The LBP pattern can be used to identify a line end (1000000 and its rotated version).
  • The LBP pattern with 2 continuous 1'2 can be considered as a horizontal or vertical line.

Code

References

  • Description of interest regions with local binary patterns by Heikkil, Pietik? & Schmid
  • Rotation invariant image description with local binary pattern histogram fourier features. by Ahonen T. and Matas J. and He C & Pietik?inen M.
  • Multiresolution gray-scale and rotation invariant texture classification with Local Binary Patterns by Ojala

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
Student IIT Bombay
India India
This member has not yet provided a Biography. Assume it's interesting and varied, and probably something to do with programming.

Comments and Discussions

 
-- There are no messages in this forum --