LBP简介(附opencv代码)

来源:互联网 发布:春晚 知乎 编辑:程序博客网 时间:2024/05/20 09:09

LBP(local binary pattern)是一种用来描述图像局部纹理特征的算子。原始的LBP于1994年提出,它反映内容是每个像素与周围像素的关系。后被不断的改进和优化,分别提出了LBP旋转不变模式、LBP均匀模式等。

一:原始的LBP

   给出一个简单的案例计算LBP:如下图,周围8个像素点比中间点像素值大(或者相等)的记为1,小的记为0,这样就得到二值图,然后按顺时针方向得到二进制串10001111

这样中间点的像素值就用241来代替。注意这里的计算LBP的顺序并没有硬性要求,只是一个量化公式,在同一处理中保持相同的顺序即可。

下面给出LBP的计算公式:



二、旋转不变的LBP模式<LBPROT>

原始的LBP不具有旋转不变性,这样我们就提出了旋转不变的LBP模式。旋转不变的LBP计算公式如下:


这样计算出来的LBP共有36种,分布情况如下面两幅图:


其中白点代表1,黑点代表0。


三:均匀LBP模式

旋转LBP模式同样存在缺陷,大量的实验证明LBP模式的36种情况在一幅图像中分布出现的频率差异较大,得到的效果并不是很好。因此人们提出了均匀LBP模式即uniform LBP。

均匀模式就是一个二进制序列从01或是从10的变过不超过2次(这个二进制序列首尾相连)。比如:10100000的变化次数为3次所以不是一个uniform pattern。所有的8位二进制数中共有58(变化次数为0的有2种,变化次数为1的有0种,变化次数为2的有56种)个uniform pattern.为什么要提出这么个uniform LBP呢,因为研究者发现他们计算出来的大部分值都在这58种之中可达到90%以上,所以他们把值分为59类,58个uniform pattern为一类,其它的所有值为第59类。59=(2+0+56)+1,这样直方图从原来的256维变成59维。起到了降维的作用

 计算公式:


应用:

在模式识别如判断两幅图片的相似性时,我们可以统计这两幅图像的LBP特征的直方图。这样,在原始的LBP模式中,统计的直方图可以当做一个256维的向量。直接这样判断,很多时候会因为“位置没有对准”而产生很大的误差。大量研究表明,此时我们可以将一幅图片划分为若干的子区域,对每个子区域内的每个像素点都提取LBP特征,然后,在每个子区域内建立LBP特征的统计直方图。如此一来,每个子区域,就可以用一个统计直方图来进行描述;整个图片就由若干个统计直方图组成。比如将一幅图像划分为10*10个区域,这样得到向量的维数就是256*10*10。而针对uniform LBP,此时向量的维数就是59*10*10, 从而达到降维的目的。

目前,LBP局部纹理提取算子,已经成功应用在指纹识别、字符识别、人脸识别、车牌识别等领域。


Code:

原始的LBP:

[cpp] view plaincopy在CODE上查看代码片派生到我的代码片
  1. void LBP(Mat &image, Mat &result)  
  2. {  
  3.     for(int y = 1; y < image.rows-1; y ++)  
  4.     {  
  5.         for(int x = 1; x < image.cols-1; x++)  
  6.         {  
  7.             uchar neighbor[8] = {0};  
  8.             neighbor[0] = image.at<uchar>(y-1, x-1);  
  9.             neighbor[1] = image.at<uchar>(y-1, x);  
  10.             neighbor[2] = image.at<uchar>(y-1, x+1);  
  11.             neighbor[3] = image.at<uchar>(y, x+1);  
  12.             neighbor[4] = image.at<uchar>(y+1, x+1);  
  13.             neighbor[5] = image.at<uchar>(y+1, x);  
  14.             neighbor[6] = image.at<uchar>(y+1, x-1);  
  15.             neighbor[7] = image.at<uchar>(y, x-1);  
  16.             uchar center = image.at<uchar>(y, x);  
  17.             uchar temp = 0;  
  18.             for(int k = 0; k < 8; k++)  
  19.             {  
  20.                 temp += (neighbor[k] >= center)* (1<<k);  // 计算LBP的值  
  21.             }  
  22.             result.at<uchar>(y,x) = temp;   
  23.         }  
  24.     }  
  25. }  
  26.   
  27. int main()  
  28. {  
  29.     Mat image = imread("F:\\lena.png", 0);  
  30.     if(!image.data)  
  31.     {  
  32.         cout << "Fail to load image" << endl;  
  33.         return 0;  
  34.     }  
  35.     Mat result;  
  36.     result.create(Size(image.cols, image.rows), image.type());  
  37.     LBP(image, result);  
  38.     namedWindow("result", 0);  
  39.     imshow("result", result);  
  40.     waitKey(0);  
  41.     return 0;  
  42. }  
uniform LBP:

[cpp] view plaincopy在CODE上查看代码片派生到我的代码片
  1. // 计算跳变次数  
  2. int getHopCount(int i)  
  3. {  
  4.     int a[8] = {0};  
  5.     int cnt = 0;  
  6.     int k = 7;  
  7.     while(i)  
  8.     {  
  9.         a[k] = i&1;  
  10.         i = i >> 1;  
  11.         --k;  
  12.     }  
  13.     for(k = 0; k < 7; k++)  
  14.     {  
  15.         if(a[k] != a[k+1])  
  16.         {  
  17.             ++cnt;  
  18.         }  
  19.     }  
  20.     if(a[0] != a[7])  
  21.     {  
  22.         ++cnt;  
  23.     }  
  24.     return cnt;  
  25. }  
  26.   
  27. // 降维数组 由256->59  
  28. void lbp59table(uchar *table)  
  29. {  
  30.     memset(table, 0, 256);  
  31.     uchar temp = 1;  
  32.     for(int i = 0; i < 256; i++)  
  33.     {  
  34.         if(getHopCount(i) <= 2)    // 跳变次数<=2 的为非0值  
  35.         {  
  36.             table[i] = temp;  
  37.             temp ++;  
  38.         }  
  39.     }  
  40. }  
  41.   
  42. void uniformLBP(Mat &image, Mat &result, uchar *table)  
  43. {  
  44.     for(int y = 1; y < image.rows-1; y ++)  
  45.     {  
  46.         for(int x = 1; x < image.cols-1; x++)  
  47.         {  
  48.             uchar neighbor[8] = {0};  
  49.             neighbor[0] = image.at<uchar>(y-1, x-1);  
  50.             neighbor[1] = image.at<uchar>(y-1, x);  
  51.             neighbor[2] = image.at<uchar>(y-1, x+1);  
  52.             neighbor[3] = image.at<uchar>(y, x+1);  
  53.             neighbor[4] = image.at<uchar>(y+1, x+1);  
  54.             neighbor[5] = image.at<uchar>(y+1, x);  
  55.             neighbor[6] = image.at<uchar>(y+1, x-1);  
  56.             neighbor[7] = image.at<uchar>(y, x-1);  
  57.             uchar center = image.at<uchar>(y, x);  
  58.             uchar temp = 0;  
  59.             for(int k = 0; k < 8; k++)  
  60.             {  
  61.                 temp += (neighbor[k] >= center)* (1<<k);  // 计算LBP的值  
  62.             }  
  63.             result.at<uchar>(y,x) = table[temp];   //  降为59维空间  
  64.         }  
  65.     }  
  66. }  
  67.   
  68. int main()  
  69. {  
  70.     uchar table[256];  
  71.     lbp59table(table);  
  72.     Mat image = imread("F:\\lena.png", 0);  
  73.     if(!image.data)  
  74.     {  
  75.         cout << "Fail to load image" << endl;  
  76.         return 0;  
  77.     }  
  78.     Mat result;  
  79.     result.create(Size(image.cols, image.rows), image.type());  
  80.     uniformLBP(image, result, table);  
  81.   
  82.     namedWindow("uniformResult", 0);  
  83.     imshow("uniformResult", result);  
  84.   
  85.     waitKey(0);  
  86.     return 0;  
  87.       
  88. }  

Result:

原图:

原始LBP:


uniform LBP:


参考文献:文章:Multiresolution Gray-Scale and Rotation Invariant Texture Classificationwith Local Binary Patterns 

作者:小村长  出处:http://blog.csdn.net/lu597203933 欢迎转载或分享,但请务必声明文章出处。 (新浪微博:小村长zack, 欢迎交流!)
原创粉丝点击