Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles / All-Topics

Local Binary Pattern

0.00/5 (No votes)
19 Jan 2014CPOL3 min read 20.2K  
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.

    C++
    <![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.

License

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