Ask Your Question

local binary pattern with texture classification

asked 2015-05-09 08:21:00 -0500

fredreload gravatar image

So I tried to do local binary pattern and histogram comparison on my texture. I used the local binary program from here ( and tried to compare the histogram difference for two images, but for some reason the match is really high even when the texture differs a lot. I modified the main.cpp just a little bit so that I can get the histogram comparison value to show. Below is my code. As you can see the result turns out to be 94.48% match, so I would like to know what I am doing wrong so I can improve the result. I am using OLBP. The image below shows histogram and result. I would like to compare with histogram but not feature matching.

int main(int argc, const char *argv[]) {
    int deviceId = 0;
    if(argc > 1)
        deviceId = atoi(argv[1]);

    VideoCapture cap(deviceId);

    if(!cap.isOpened()) {
        cerr << "Capture Device ID " << deviceId << "cannot be opened." << endl;
        return -1;

    // initial values
    int radius = 1;
    int neighbors = 8;

    // windows

    // matrices used
    Mat test;
    Mat test1;
    Mat frame; // always references the last frame
    Mat dst; // image after preprocessing
    Mat dst1;
    Mat lbp; // lbp image
    Mat lbp1;

    // just to switch between possible lbp operators
    vector<string> lbp_names;
    lbp_names.push_back("Extended LBP"); // 0
    lbp_names.push_back("Fixed Sampling LBP"); // 1
    lbp_names.push_back("Variance-based LBP"); // 2
    int lbp_operator=1;

    bool running=true;
    while(running) {
        //cap >> frame;
        dst = imread("Hist1.jpg", CV_LOAD_IMAGE_GRAYSCALE); //Load as grayscale
        dst1 = imread("Hist3.jpg", CV_LOAD_IMAGE_GRAYSCALE); //Load as grayscale
        //cvtColor(frame, dst, CV_BGR2GRAY);
        //GaussianBlur(test, dst, Size(7,7), 5, 3, BORDER_CONSTANT); // tiny bit of smoothing is always a good idea
        //GaussianBlur(test1, dst1, Size(7,7), 5, 3, BORDER_CONSTANT); // tiny bit of smoothing is always a good idea
        // comment the following lines for original size
        //resize(frame, frame, Size(), 0.5, 0.5);
        //resize(test,dst,Size(), 0.5, 0.5);
        switch(lbp_operator) {
        case 0:
            lbp::ELBP(test, lbp, radius, neighbors); // use the extended operator
        case 1:
            lbp::OLBP(dst, lbp); // use the original operator
            lbp::OLBP(dst1, lbp1); // use the original operator
        case 2:
            lbp::VARLBP(dst, lbp, radius, neighbors);
        // now to show the patterns a normalization is necessary
        // a simple min-max norm will do the job...
        normalize(lbp, lbp, 0, 255, NORM_MINMAX, CV_8UC1);

        Mat lbp_hist, lbp1_hist;

        int histSize[] = {256};

        float s_ranges[] = { 0, 256 };

    const float* ranges[] = { s_ranges };

    // Use the o-th and 1-st channels
    int channels[] = { 0 };

        calcHist( &lbp, 1, channels, Mat(), lbp_hist, 1, histSize, ranges, true, false );
        normalize( lbp1_hist, lbp1_hist, 0, 1, NORM_MINMAX, -1, Mat() );

        calcHist( &lbp1, 1, channels, Mat(), lbp1_hist, 1, histSize, ranges, true, false );
        normalize( lbp_hist, lbp_hist, 0, 1, NORM_MINMAX, -1, Mat() );

        double base_base = compareHist( lbp_hist, lbp1_hist, 0 );


        imshow("original", lbp);
        imshow("lbp", lbp1);

        char key = (char) waitKey(0);;

        return 0; // success

image description

edit retag flag offensive close merge delete



the L in LBP stands for LOCAL. what you've got so far, is a global binary pattern image.

you're supposed to chop that up into NxN grid patches (e.g. N=8), calculate histograms on each of them seperately, and later concatatenate those to a large 1d feature vector. see here

(oh, and by the way, try to experiment with different comparison types. to my findings, HISTCMP_HELLINGER works best, HISTCMP_CORREL(what yo're using now) worst !)

berak gravatar imageberak ( 2015-05-09 08:32:14 -0500 )edit

I found out I misplaced lbp1 in my normalized function. I am using Kullback-Leibler divergence suggested here ( I will take a look at spatial_histogram, thanks for the lead.

fredreload gravatar imagefredreload ( 2015-05-09 09:58:03 -0500 )edit

i somehow doubt, that kl-divergence will work better. maybe report back your findings ?

10 fold crossvalidation on lfw-deepfunneled:

H_HELL   accuracy : 0.894   time : 95.337
KLDIV    accuracy : 0.737   time : 81.668
berak gravatar imageberak ( 2015-05-09 10:10:10 -0500 )edit

I followed Python code to calculate ELBP and set the radius to 2 with 16 neighborhood which gives a pretty good answer for Kullback-Leibler distance (same image as 0). But using Hellinger with this parameter does not seem to work well.

fredreload gravatar imagefredreload ( 2015-05-10 02:59:11 -0500 )edit

ah, ok. seems like a 2^16 feature vector plays nicer with this kind of distance (but usually you can't allow for gargantuan features like this.)

interesting result anyway, thanks for reporting back !

berak gravatar imageberak ( 2015-05-10 03:05:32 -0500 )edit

I am interested with your code PLEASE send me full code because when I run it , the Images after LBP just appears with me

Iram gravatar imageIram ( 2016-03-30 12:38:22 -0500 )edit

1 answer

Sort by ยป oldest newest most voted

answered 2015-05-11 09:40:34 -0500

fredreload gravatar image

Here's another question. I am looking at the code for spatial_histogram one that's made up of many n*n histograms, but I cannot figure out a few parameters for the function. If someone can help me out it would be cool.

void lbp::spatial_histogram(const Mat& src, Mat& hist, int numPatterns, const Size& window, int overlap)

I have lbp image for src, and empty Mat for hist. I give 16 for numPatterns since I think it is asking for neighbors. Then I set a size for Size dsize = Size(lbp.cols/4, lbp.rows/4); for window, and 0 for overlap but I am not sure what numPatterns, window, and overlap are. What is gridx and gridy?

edit flag offensive delete link more


sounds all correct so far (though you'll end up with a giant 4x4x(2^16) elem vector with 16 neighbours)

gridx gridy are the subdivisions, 4 for both in your case.

berak gravatar imageberak ( 2015-05-11 09:44:51 -0500 )edit<int>(0,y) = histograms[histIdx].at<int>(valIdx); This line keeps giving me error though.

fredreload gravatar imagefredreload ( 2015-05-11 22:03:13 -0500 )edit

Question Tools



Asked: 2015-05-09 08:21:00 -0500

Seen: 4,142 times

Last updated: May 11 '15