65.9K
CodeProject is changing. Read more.
Home

Local Binary Pattern

emptyStarIconemptyStarIconemptyStarIconemptyStarIconemptyStarIcon

0/5 (0 vote)

Jan 19, 2014

CPOL

3 min read

viewsIcon

20162

In this article, we will look at the concept of Local Binary Pattern and computation of LBP image.

Introduction

  • In this article, we will look at the concept of Local Binary Pattern and computation of LBP image.
  • 2D surface texture is characterized by spatial pattern and intensity/contrast.
  • Spatial Pattern is affected by rotation, scale changes, hence for a good texture description we require a rotation and scale invariant descriptor.
  • Local binary pattern binarizes the local neighborhood of each pixel and builds a histogram on these binary neighborhood patterns.
  • Let P be the number of neighborhood pixels and R the distance from the center pixel $l_c$ and $l_p$ be neighborhood pixel.
  • A $LBP_{P,R}$ number characterizes the local texture by assigning the binomial factor $2^P$ for each sign $sgn(l_p-l_c)$ \[ LBP_{P,R} = \sum_{p=0}^{P-1} sgn(l_p - l_c) 2^p \]
  • $l_p$ for $p={0\ldots P-1}$ are a set of equally spaced pixels on a circle of radius $R$.
  • $LBP_{P,R}$ features has $2^P$ possible values.For P=8 we have a binary feature vector of length $256$.
  • Patterns are classified as uniform and non uniform.
  • Uniform patterns have single contiguous regions of 0 and 1 while non uniform patterns do not. For example, 01100000 is a uniform pattern while 01010000 is an example of non uniform pattern
  • We can see that there are 9 possible uniform pattern values
    0 0 0 0 0 0 0 0
    1 0 0 0 0 0 0 0
    1 1 0 0 0 0 0 0
    1 1 1 0 0 0 0 0
    1 1 1 1 0 0 0 0
    1 1 1 1 1 0 0 0
    1 1 1 1 1 1 0 0
    1 1 1 1 1 1 1 0
    1 1 1 1 1 1 1 1
  • Now consider the effect of rotation on the feature vector.
  • Rotating the image results in circular shift of values of feature vector.
  • To incorporate rotational invariance, we need to assign all possible rotations of a feature vector to a single LBP value. For example, all the below patterns
    1 0 0 0 0 0 0 0
    0 1 0 0 0 0 0 0
    0 0 1 0 0 0 0 0
    0 0 0 1 0 0 0 0
    0 0 0 0 1 0 0 0
    0 0 0 0 0 1 0 0
    0 0 0 0 0 0 1 0
    0 0 0 0 0 0 0 1
    \\ will be assigned to a single value.
  • In the present article however, we are not considering rotational invariant features
  • Let us consider the implementation details of LBP
  • If we only consider a 3x3 neighborhood, we need to threshold the rectangular region about
  • Another method would be to divide image into square blocks of size BxB. Instead of central pixel value, we consider the mean value of pixels in the central block.
  • Similarly, instead of considering the single pixel value in the neighborhood, we would consider the mean value of pixels in the block.
  • All the pixels in the block are encoded with the same binary value 0 or 1.
  • To compute mean value over rectangular regions of image, integral images are used.
  • The output of lbp images for block size 1,2 and 8 is showing in figure f1
    LBP Images
    f1
  • We can see that as block size increases, quantization effects can be seen and the information in the encoded image cannot be recognized.

     <![CDATA[       
                     #include "ImgFeatures/integralImage.h" 
                     class LBPFeatures 
                     { 
                     public:     LBPFeatures(){};     
                     Mat image;     
                     vector<uchar> features;     
                     Mat mask;     
                     IntegralImage ix; //function to compute LBP image with block size 1     
                     void compute(Mat image,Mat &dst)     
                     {         
                     uchar *ptr=image.data;         
                     image.copyTo(dst);         
                     uchar *optr=dst.data;         
                     int width=image.cols;         
                     int height=image.rows;          
                     for(int i=1;i<height-1;i++) 
                     code|="((int)ptr[(j-1)+(i-1)*width]" 
                     code="0;" 
                     center="(int)ptr[j+i*width];" 
                     j="0;j<width-1;j++)">=center)<<7 ;                 
                     code|=((int)ptr[j+(i-1)*width] >=center)<<6 ;                 
                     code|=((int)ptr[(j+1)+(i-1)*width] >=center)<<5 ;                 
                     code|=((int)ptr[(j+1)+(i)*width] >=center)<<4 ;                 
                     code|=((int)ptr[(j+1)+(i+1)*width] >=center)<<3 ;                 
                     code|=((int)ptr[j+(i+1)*width] >=center)<<2 ;                 
                     code|=((int)ptr[j-1+(i+1)*width] >=center)<<1 ;                 
                     code|=((int)ptr[j-1+(i)*width] >=center)<<0 ;                 
                     optr[j+i*width]=code;             
                     }         
                     }      
                     }      //computing integral image for block     
                     void computeBlock(Mat image,Mat & dst,int block=2)     
                     {  //computing integral image         
                     ix.compute(image);         
                     image.copyTo(dst);         
                     dst.setTo(cv::Scalar::all(0));         
                     int width=image.cols;         
                     int height=image.rows;         
                     for(int i=block;i<height-block;i=i+block) 
                     code|="(meanv" code="0;" 
                     j="block;j<width-block;j=j+block)" 
                     val="(int)ix.calcMean(r1);" r1="Rect(x,y,block,block);" 
                     x="i;" y="j;" k="0;k<8;k++)" 
                     meanv="ix.calcMean(r);" 
                     r="Rect(j,i,block,block);">= val)<<(7-k);                  
                     }                 
                     Mat roi=dst(r);                 //setting value of all pixel in output                 
                     //image to the encoded value for visualization                 
                     roi.setTo(cv::Scalar::all(code));             
                     }         
                     }       
                     }  
                     }; 
  • The code for the same can be found in the git repo for OpenVisionLibrary https://github.com/pi19404/OpenVision/ in the following files ImgFeatures/lbpfeatures.hpp and lbpFeatures.cpp.