LBP简介(转载)

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。

均匀模式就是一个二进制序列从0到1或是从1到0的变过不超过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:

 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:

 1 #include "Stafx.h"
 2 using namespace cv;
 3 using namespace std;
 4 
 5 // 计算跳变次数  
 6 int getHopCount(int i)  
 7 {  
 8     int a[8] = {0};  
 9     int cnt = 0;  
10     int k = 7;
11     /************************************************************************/
12     /* while循环详解:
13       例如i的二进制为000000000000000000000000abcdefgh,经过i&1后a[7]=h;经过i>>1后右移一位
14       变成000000000000000000000000abcdefg,再经过i&1后a[6]=g;经过i>>1后右移一位
15       0000000000000000000000000abcdef,依次类推,则数组a为a[0]=a,a[1]=b,a[2]=c,a[3]=d,a[4]=e,
16       a[5]=f,a[6]=g,a[7]=h
17     */
18     /************************************************************************/
19     while(i)  
20     {  
21         a[k] = i&1;  //取i的二进制的最低位
22         i = i >> 1;  //右移
23         --k;  
24     }
25     //a[0]~a[7]组成环形,只要相邻两个不同就加1
26     for(k = 0; k < 7; k++)  
27     {  
28         if(a[k] != a[k+1])  
29         {  
30             ++cnt;  
31         }  
32     }  
33     if(a[0] != a[7])  
34     {  
35         ++cnt;  
36     }  
37     return cnt;  
38 }  
39 
40 // 降维数组 由256->59  
41 void lbp59table(uchar *table)  
42 {  
43     memset(table, 0, 256);  
44     uchar temp = 1;  
45     for(int i = 0; i < 256; i++)  
46     {  
47         if(getHopCount(i) <= 2)    // 跳变次数<=2 的为非0值  
48         {  
49             table[i] = temp;    //划分为多少类,类标签从小到大排列,好比一个映射表,搜索索引值
50             temp ++;  
51         }  
52     }  
53 }  
54 
55 void uniformLBP(Mat &image, Mat &result, uchar *table)  
56 {  
57     for(int y = 1; y < image.rows-1; y ++)  
58     {  
59         for(int x = 1; x < image.cols-1; x++)  
60         {  
61             uchar neighbor[8] = {0};  
62             neighbor[0] = image.at<uchar>(y-1, x-1);  
63             neighbor[1] = image.at<uchar>(y-1, x);  
64             neighbor[2] = image.at<uchar>(y-1, x+1);  
65             neighbor[3] = image.at<uchar>(y, x+1);  
66             neighbor[4] = image.at<uchar>(y+1, x+1);  
67             neighbor[5] = image.at<uchar>(y+1, x);  
68             neighbor[6] = image.at<uchar>(y+1, x-1);  
69             neighbor[7] = image.at<uchar>(y, x-1);  
70             uchar center = image.at<uchar>(y, x);  
71             uchar temp = 0;  
72             for(int k = 0; k < 8; k++)  
73             {  
74                 //1<<k表示2^k次幂
75                 temp += (neighbor[k] >= center)* (1<<k);  // 计算LBP的值  
76             }  
77             result.at<uchar>(y,x) = table[temp];   //  降为59维空间  
78         }  
79     }  
80 }  
81 
82 int main()  
83 {  
84     uchar table[256];  
85     lbp59table(table);  
86     Mat image = imread("lena.png", 0);  
87     if(!image.data)  
88     {  
89         cout << "Fail to load image" << endl;  
90         return 0;  
91     }  
92     Mat result;  
93     result.create(Size(image.cols, image.rows), image.type());  
94     uniformLBP(image, result, table);  
95     namedWindow("uniformResult", 0);  
96     imshow("uniformResult", result);  
97     waitKey(0);  
98     return 0;  
99 }  

 unform lBP

 3 #include "Stafx.h"
 4 
 5 //提取局部纹理特征均匀LBP算子
 6 
 7 int gethopcount(int i) //判断环形二进制字符串两位的变化次数
 8 {
 9     int a[8]={0};
10     int temp=0;         //变换次数
11     int k=7;
12     while (i)
13     {
14         a[k]=i&1;  //取二进制最低位
15         i=i>>1;    //右移
16         k--;
17     }
18     for (int j=0;j<7;j++)  //判断下标0~7
19     {
20         if (a[j]!=a[j+1]) temp++;
21     }
22     //判断下标0和7
23     if (a[0]!=a[7]) temp++;
24     return temp;
25 }
26 //实现降维操作256->59
27 void lbp59table(uchar* table)
28 {
29     memset(table,0,256);
30     uchar temp=1;
31     for (int i=0;i<256;i++)
32     {
33         if (gethopcount(i)<=2)
34         {
35             table[i]=temp; 
36             temp++;
37         }
38     }
39 }
40 //均匀LBP算法
41 void uniformLBP(IplImage* src,IplImage* result, uchar* table)
42 {
43     cvCopy(src,result);  //注意到cvCopy与cvCloneImage的区别
44     /************************************************************************/
45     /* cvCopy必须先要创建内存空间,才能使用
46        而cvCloneImage会自动开辟内存空间,并返回指向该内存空间的指针
47        如果在这里使用result=cvCloneImage(src);则main函数中显示的result是无图像
48        说明这两个地址所指向的空间内存不一样。
49     */
50     /************************************************************************/
51     for (int i=1;i<src->width-1;i++)
52         for (int j=1;j<src->height-1;j++)
53         {
54             uchar neighbor[8]={0};
55             neighbor[0]=CV_IMAGE_ELEM(src,uchar,j-1,i-1);
56             neighbor[1]=CV_IMAGE_ELEM(src,uchar,j-1,i);
57             neighbor[2]=CV_IMAGE_ELEM(src,uchar,j-1,i+1);
58             neighbor[3]=CV_IMAGE_ELEM(src,uchar,j,i+1);
59             neighbor[4]=CV_IMAGE_ELEM(src,uchar,j+1,i+1);
60             neighbor[5]=CV_IMAGE_ELEM(src,uchar,j+1,i);
61             neighbor[6]=CV_IMAGE_ELEM(src,uchar,j+1,i-1);
62             neighbor[7]=CV_IMAGE_ELEM(src,uchar,j,i-1);
63             uchar central=CV_IMAGE_ELEM(src,uchar,j,i);
64             uchar temp=0;
65             for (int k=0;k<8;k++)
66             {
67                 temp+=(neighbor[k]>=central)*(1<<k); //1<<k表示2^k次幂
68             }
69             uchar*ptr=(uchar*) (result->imageData+j*result->widthStep+i);
70             *ptr=table[temp];
71         };
72 }
73 void main()
74 {
75     uchar table[256];
76     lbp59table(table);  //由256维降成59维
77     IplImage* src=cvLoadImage("lena.png",CV_LOAD_IMAGE_GRAYSCALE);
78     IplImage* result=cvCreateImage(cvGetSize(src),IPL_DEPTH_8U,1);
79     uniformLBP(src,result,table);
80     cvShowImage("1",result);
81     cvWaitKey();
82     cvReleaseImage(&src);
83     cvReleaseImage(&result);
84 }

 

转载于:https://www.cnblogs.com/gzy-zju-edu/articles/4168021.html

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值