Ask Your Question

Revision history [back]

click to hide/show revision 1
initial version

the idea behind the 'uniform' lbph is to compress the histogram from 256 items to 59 (faster/less memory) and at the same time achieving a bit more robustness against noise.

// const Mat_<uchar> used for convenient () operator indexing
uchar lbp(const Mat_<uchar> & img, int x, int y)
{
    static int uniform[256] = { // hardcoded 8-neighbour case
        0,1,2,3,4,58,5,6,7,58,58,58,8,58,9,10,11,58,58,58,58,58,58,58,12,58,58,58,13,58,
        14,15,16,58,58,58,58,58,58,58,58,58,58,58,58,58,58,58,17,58,58,58,58,58,58,58,18,
        58,58,58,19,58,20,21,22,58,58,58,58,58,58,58,58,58,58,58,58,58,58,58,58,58,58,58,
        58,58,58,58,58,58,58,58,58,58,58,58,23,58,58,58,58,58,58,58,58,58,58,58,58,58,
        58,58,24,58,58,58,58,58,58,58,25,58,58,58,26,58,27,28,29,30,58,31,58,58,58,32,58,
        58,58,58,58,58,58,33,58,58,58,58,58,58,58,58,58,58,58,58,58,58,58,34,58,58,58,58,
        58,58,58,58,58,58,58,58,58,58,58,58,58,58,58,58,58,58,58,58,58,58,58,58,58,58,
        58,35,36,37,58,38,58,58,58,39,58,58,58,58,58,58,58,40,58,58,58,58,58,58,58,58,58,
        58,58,58,58,58,58,41,42,43,58,44,58,58,58,45,58,58,58,58,58,58,58,46,47,48,58,49,
        58,58,58,50,51,52,58,53,54,55,56,57
    };
    // this is pretty much the same what you already got..
    uchar v = 0;
    uchar c = img(y,x);
    v += (img(y-1,x  ) > c) << 0;
    v += (img(y-1,x+1) > c) << 1;
    v += (img(y  ,x+1) > c) << 2;
    v += (img(y+1,x+1) > c) << 3;
    v += (img(y+1,x  ) > c) << 4;
    v += (img(y+1,x-1) > c) << 5;
    v += (img(y  ,x-1) > c) << 6;
    v += (img(y-1,x-1) > c) << 7;
    return uniform[v]; // just replace the lbp value with a lookup
}


void uniformLbpHist(const Mat & img_gray, Mat & hist)
{
    // 59 bins, bin 58 is the noise/non-uniform slot:
    hist = Mat::zeros(59,1,CV_32F);

    Mat_<uchar>img(img_gray);

    for(int i=1;i<height-1;i++)
    {
        for(int j=1;j<width-1;j++)
        {
            uchar uv = lbp(img, j,i);
            hist[ uv ] ++; // incr. the resp. histogram bin
        }
    }
}

the idea behind the 'uniform' lbph is to compress the histogram from 256 items to 59 (faster/less memory) and at the same time achieving a bit more robustness against noise.

// const Mat_<uchar> used here for convenient () operator indexing
uchar lbp(const Mat_<uchar> & img, int x, int y)
{
    static int uchar uniform[256] = { // hardcoded 8-neighbour case
        0,1,2,3,4,58,5,6,7,58,58,58,8,58,9,10,11,58,58,58,58,58,58,58,12,58,58,58,13,58,
        14,15,16,58,58,58,58,58,58,58,58,58,58,58,58,58,58,58,17,58,58,58,58,58,58,58,18,
        58,58,58,19,58,20,21,22,58,58,58,58,58,58,58,58,58,58,58,58,58,58,58,58,58,58,58,
        58,58,58,58,58,58,58,58,58,58,58,58,23,58,58,58,58,58,58,58,58,58,58,58,58,58,
        58,58,24,58,58,58,58,58,58,58,25,58,58,58,26,58,27,28,29,30,58,31,58,58,58,32,58,
        58,58,58,58,58,58,33,58,58,58,58,58,58,58,58,58,58,58,58,58,58,58,34,58,58,58,58,
        58,58,58,58,58,58,58,58,58,58,58,58,58,58,58,58,58,58,58,58,58,58,58,58,58,58,
        58,35,36,37,58,38,58,58,58,39,58,58,58,58,58,58,58,40,58,58,58,58,58,58,58,58,58,
        58,58,58,58,58,58,41,42,43,58,44,58,58,58,45,58,58,58,58,58,58,58,46,47,48,58,49,
        58,58,58,50,51,52,58,53,54,55,56,57
    };
    // this is pretty much the same what you already got..
    uchar v = 0;
    uchar c = img(y,x);
    v += (img(y-1,x  ) > c) << 0;
    v += (img(y-1,x+1) > c) << 1;
    v += (img(y  ,x+1) > c) << 2;
    v += (img(y+1,x+1) > c) << 3;
    v += (img(y+1,x  ) > c) << 4;
    v += (img(y+1,x-1) > c) << 5;
    v += (img(y  ,x-1) > c) << 6;
    v += (img(y-1,x-1) > c) << 7;
    return uniform[v]; // just replace the lbp value with a lookup
}


void uniformLbpHist(const Mat & img_gray, Mat & hist)
{
    // 59 bins, bin 58 is the noise/non-uniform slot:
    hist = Mat::zeros(59,1,CV_32F);

    Mat_<uchar>img(img_gray);

    for(int i=1;i<height-1;i++)
    {
        for(int j=1;j<width-1;j++)
        {
            uchar uv = lbp(img, j,i);
            hist[ uv ] ++; // incr. the resp. histogram bin
        }
    }
}

the idea behind the 'uniform' lbph is to compress the histogram from 256 items to 59 (faster/less memory) and at the same time achieving a bit more robustness against noise.

//
// Mat_<uchar> used here for convenient () operator indexing
//
uchar lbp(const Mat_<uchar> & img, int x, int y)
{
    static uchar uniform[256] = { // hardcoded 8-neighbour case
        0,1,2,3,4,58,5,6,7,58,58,58,8,58,9,10,11,58,58,58,58,58,58,58,12,58,58,58,13,58,
        14,15,16,58,58,58,58,58,58,58,58,58,58,58,58,58,58,58,17,58,58,58,58,58,58,58,18,
        58,58,58,19,58,20,21,22,58,58,58,58,58,58,58,58,58,58,58,58,58,58,58,58,58,58,58,
        58,58,58,58,58,58,58,58,58,58,58,58,23,58,58,58,58,58,58,58,58,58,58,58,58,58,
        58,58,24,58,58,58,58,58,58,58,25,58,58,58,26,58,27,28,29,30,58,31,58,58,58,32,58,
        58,58,58,58,58,58,33,58,58,58,58,58,58,58,58,58,58,58,58,58,58,58,34,58,58,58,58,
        58,58,58,58,58,58,58,58,58,58,58,58,58,58,58,58,58,58,58,58,58,58,58,58,58,58,
        58,35,36,37,58,38,58,58,58,39,58,58,58,58,58,58,58,40,58,58,58,58,58,58,58,58,58,
        58,58,58,58,58,58,41,42,43,58,44,58,58,58,45,58,58,58,58,58,58,58,46,47,48,58,49,
        58,58,58,50,51,52,58,53,54,55,56,57
    };
    // this is pretty much the same what you already got..
    uchar v = 0;
    uchar c = img(y,x);
    v += (img(y-1,x  ) > c) << 0;
    v += (img(y-1,x+1) > c) << 1;
    v += (img(y  ,x+1) > c) << 2;
    v += (img(y+1,x+1) > c) << 3;
    v += (img(y+1,x  ) > c) << 4;
    v += (img(y+1,x-1) > c) << 5;
    v += (img(y  ,x-1) > c) << 6;
    v += (img(y-1,x-1) > c) << 7;
    return uniform[v]; // just replace the lbp value with a lookup
v;
}

 //
// you would usually apply this to small patches of an image and concatenate the histograms
//
void uniformLbpHist(const Mat & img_gray, Mat & hist)
{
    static uchar uniform[256] = { // hardcoded 8-neighbour case
        0,1,2,3,4,58,5,6,7,58,58,58,8,58,9,10,11,58,58,58,58,58,58,58,12,58,58,58,13,58,
        14,15,16,58,58,58,58,58,58,58,58,58,58,58,58,58,58,58,17,58,58,58,58,58,58,58,18,
        58,58,58,19,58,20,21,22,58,58,58,58,58,58,58,58,58,58,58,58,58,58,58,58,58,58,58,
        58,58,58,58,58,58,58,58,58,58,58,58,23,58,58,58,58,58,58,58,58,58,58,58,58,58,
        58,58,24,58,58,58,58,58,58,58,25,58,58,58,26,58,27,28,29,30,58,31,58,58,58,32,58,
        58,58,58,58,58,58,33,58,58,58,58,58,58,58,58,58,58,58,58,58,58,58,34,58,58,58,58,
        58,58,58,58,58,58,58,58,58,58,58,58,58,58,58,58,58,58,58,58,58,58,58,58,58,58,
        58,35,36,37,58,38,58,58,58,39,58,58,58,58,58,58,58,40,58,58,58,58,58,58,58,58,58,
        58,58,58,58,58,58,41,42,43,58,44,58,58,58,45,58,58,58,58,58,58,58,46,47,48,58,49,
        58,58,58,50,51,52,58,53,54,55,56,57
    };
    // 59 bins, bin 58 is the noise/non-uniform slot:
    hist = Mat::zeros(59,1,CV_32F);

    Mat_<uchar>img(img_gray);

    for(int i=1;i<height-1;i++)
    {
        for(int j=1;j<width-1;j++)
        {
            uchar uv = lbp(img, j,i);
            hist[ uv uniform[uv] ] ++; // incr. the resp. histogram bin
        }
    }
}

the idea behind the 'uniform' lbph is to compress the histogram from 256 items to 59 (faster/less memory) and at the same time achieving a bit more robustness against noise.

//
// Mat_<uchar> used here for convenient () operator indexing
//
uchar lbp(const Mat_<uchar> & img, int x, int y)
{
    // this is pretty much the same what you already got..
    uchar v = 0;
    uchar c = img(y,x);
    v += (img(y-1,x  ) > c) << 0;
    v += (img(y-1,x+1) > c) << 1;
    v += (img(y  ,x+1) > c) << 2;
    v += (img(y+1,x+1) > c) << 3;
    v += (img(y+1,x  ) > c) << 4;
    v += (img(y+1,x-1) > c) << 5;
    v += (img(y  ,x-1) > c) << 6;
    v += (img(y-1,x-1) > c) << 7;
    return v;
}
 

your code above tries to build an lbp image first, i'm going to skip that, and calculate the histogram directly from the (uniform) lbp values.

//
// you would usually apply this to small patches of an image and concatenate the histograms
//
void uniformLbpHist(const Mat & img_gray, Mat & hist)
{
    static uchar uniform[256] = { // hardcoded 8-neighbour case
        0,1,2,3,4,58,5,6,7,58,58,58,8,58,9,10,11,58,58,58,58,58,58,58,12,58,58,58,13,58,
        14,15,16,58,58,58,58,58,58,58,58,58,58,58,58,58,58,58,17,58,58,58,58,58,58,58,18,
        58,58,58,19,58,20,21,22,58,58,58,58,58,58,58,58,58,58,58,58,58,58,58,58,58,58,58,
        58,58,58,58,58,58,58,58,58,58,58,58,23,58,58,58,58,58,58,58,58,58,58,58,58,58,
        58,58,24,58,58,58,58,58,58,58,25,58,58,58,26,58,27,28,29,30,58,31,58,58,58,32,58,
        58,58,58,58,58,58,33,58,58,58,58,58,58,58,58,58,58,58,58,58,58,58,34,58,58,58,58,
        58,58,58,58,58,58,58,58,58,58,58,58,58,58,58,58,58,58,58,58,58,58,58,58,58,58,
        58,35,36,37,58,38,58,58,58,39,58,58,58,58,58,58,58,40,58,58,58,58,58,58,58,58,58,
        58,58,58,58,58,58,41,42,43,58,44,58,58,58,45,58,58,58,58,58,58,58,46,47,48,58,49,
        58,58,58,50,51,52,58,53,54,55,56,57
    };
    // 59 bins, bin 58 is the noise/non-uniform slot:
    hist = Mat::zeros(59,1,CV_32F);

    Mat_<uchar>img(img_gray);

    for(int i=1;i<height-1;i++)
    {
        for(int j=1;j<width-1;j++)
        {
            uchar uv = lbp(img, j,i);
            hist[ uniform[uv] ] ++; // incr. the resp. histogram bin
        }
    }
}