Local Binary Pattern
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
\\ will be assigned to a single value.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 - 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 - 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.