LBP原理与OpenCV实现

版权声明:本文为博主原创文章,转载请注明出处。 https://blog.csdn.net/chaipp0607/article/details/78161986

LBP简介

LBP(Local Binary Pattern)算法是一种描述图像特征像素点与各个像素点之间的灰度关系的局部特征的非参数算法,同时也是一张高效的纹理描述算法,纹理是物体表面的自然特性,它描述图像像素点与图像领域之间的灰度空间的分布关系,不会因为光照强弱而改变图像的视觉变化。LBP算法首次提出于1994年,主要是使用8邻域位置的局部关系,具有灰度不变性;随后在2002年提出了其改进版《Multiresolution gray-scale and rotation invariant texture classification with local binary patterns》 Timo Ojala, Matti PietikaÈ inen,2002,主要引入了圆形模式、旋转不变性、和等价模式,所以在下面我们将按照如下顺序介绍LBP特征:灰度不变性的基本LBP,灰度不变性的圆形LBP,旋转不变性的LBP,等价LBP,最后再继续进行我们上一次HOG+KNN的实验,用LBP特征提取+KNN算法实现手写数字识别问题。


灰度不变性基本LBP算法

基本的LBP算法一般被定义为一个 的纹理单元,如图1,其中间的像素点灰度值为 ,其他相邻的8个像素点灰度值分别为 ,以该纹理单位的中心像素点的灰度值为阈值,若其余相邻的8个像素点的灰度值大于中心像素点灰度值的阈值,则该像素点的编码值为1,小于阈值的时候取编码值为0。

对于一个3X3 的纹理单元,LBP的计算过程为:

为了得到各个像素点的编码值,则为每个![这里写图片描述] S(pi−pc)S(pi−pc) S \left ( p_{i}-p_{c} \right ) 分配权值 2^i,然后将编码值连接成一个二进制值然后再转化成一个十进制的值,然后用现在的十进制值代替原来中心点的阈值,再对这个十进制进行计算,计算出的结果就是LBP算法的值,计算公式为:

下面给出一个lbp算法的例子:

该纹理单元的中心灰度值(阈值)为85,其余8个相邻的灰度值分别为:90、74、63、134、91、83、99、103、90。根据这个阈值计算的定理进行计算,通过阈值计算后,根据图中箭头所指的方向可以得到一个局部二进制的模式,即:LBP模式=1101001,且LBP=217,。通过以上LBP算法的计算例子可以看出LBP值仅由中心像素点灰度值和相邻八个像素点的灰度值决定,LBP特征即表示了其中心像素点的特征,其值的计算还需要和周围的像素点计算完成,所以,LBP特征与周围有很大的关系,它包含了图像点,又包含了边缘和局部的特征分布信息。


灰度不变性圆形LBP算法

从上面的计算我们可以看出,基本的LBP算法的计算仅包含其相邻的八个像素点,半径小,覆盖范围很小,这种方式的表达能力相对较小,所以,Ojala等人提出一种改进的方法,将原来的 的方形九个像素点的计算模式,改成了任一点即半径的圆形模式,这样表达方式就不受限制了,而且原始的正方形领域的像素点空间被圆形领域所代替。这种圆形领域的算法的半径R可以任意的改变,且半径R的像素点个数也不固定。改进后的LBP算法通常用符号 LBPp,bLBPp,b LBP_{p,b} 表达,R为圆形半径,P代表在该圆形范畴内的P个不同像素点。 下图为几种常见的不同半径和不同像素点的LBP算法的示意图:

为了对LBP算子进行表示,用函数E表示为中心像素和相邻像素点的联合分布函数:

一个中心像素点周围的其它像素点

的坐标

可以表示成:

其中主要注意的是,坐标计算出来之后,可能不是整数,此时一般的解决方法是采用双线性内插值求得该像素点的灰度 。 在求出每个周围像素的像素值之后,就可以使用与基本LBP算法一样的方法实现剩下的工作了。圆形LBP算法与基本LBP算法基本原理相同,但是它的表达方式更灵活,有很好的鲁棒性,表示范围与表达能力更强。


旋转不变性LBP算法

通过上面的介绍,我们不难发现1和2两种LBP算法是具有灰度不变性的,在2002年的论文的,除了灰度不变性,作者又为LBP引入了旋转不变性与等价模式,它是怎么实现的呢? 通过上面的介绍我们知道,对于一个选定的P,LBP算法将产生2^P个不同的输出值,比如P=8时,值就有256个,这256个模式中每拿出一个都围绕中心点转动,那么在多次转动的过程中,会产生多种不同的结果,而这些结果中值最小的那个模式就是选择不变的二值模式了。比如:

在上面的图中说明的是,图中的这8种模式,都有相同的旋转不变模式,就是十进制为15的那个值,即00001111。那么对256种模式都做这种旋转,得到最小的数作为这种模式的旋转不变模式,旋转不变模式一共有36种,如下图所示:

那么为什么最后又36种呢?我们写一段暴力枚举的代码试一试就好了:

#include <iostream>
#include <string> 
#include <math.h>
using namespace std;

int ConversiontoDecimal(string input)
{
    int Decimal=0;
    for (int i=0;i<8;i++)
    {
        int n = input[i]-'0';
        Decimal = Decimal+n*pow(2.0,i);
    }
    return Decimal;
}
string ConversiontoBinary(int n)
{
    string s;  
    for(int a = n; a ;a = a/2)  
        s=s+(a%2?'1':'0');  
    reverse(s.begin(),s.end());  
    for (int i = s.size();i<=7;i++)
        s = "0"+s;
    return s;
}
int FindMin(string input)
{
    int MinValue = 257;
    for(int i =0;i<8;i++)
    {
        string str1 =input.substr(0,7);
        string str2 = input.substr(7,1);
        input = str2+str1;
        int Decimal_Value = ConversiontoDecimal(input);
        //cout<<Decimal_Value<<endl;
        if(Decimal_Value<MinValue)
            MinValue = Decimal_Value;
    }
    return MinValue;
}
int main()
{
    int Hash[256];
    memset(Hash,0,sizeof(Hash));
    for (int i =0;i<256;i++)
    {
       string Binary =ConversiontoBinary(i);
       //cout<<Binary<<endl; 
       int Min_Value = FindMin(Binary);
       if (Hash[Min_Value]==0)
           Hash[Min_Value]=1; 
    }
    int NumofModle =0;
    for (int i =0;i<256;i++)
        NumofModle +=Hash[i];
    cout<<NumofModle<<endl;
}

其中0-255的数字每一个转成二进制后分别转8次,求出最小的十进制数,作为哈希表的索引,最后哈希表中1的个数就是旋转不变的模式种类,最后打印结果为36。


等价LBP算法

所谓等价模式是通过记录跳变方式来进一步降低LBP特征维数,“等价模式”定义为:当某个LBP所对应的循环二进制数从0到1或从1到0最多有两次跳变时,该类型保留;跳变次数超过2次时,直接不要。等价模式就做了这件事,把P=8时的256种灰度不变性模式压缩为58种,把把P=8时的36种旋转不变性模式压缩为9种。下面我们看一下58和9是怎么来的: 首先256压缩为58: 当P=8时,P(P-1)+2=58。其中P(P-1)为跳变2次的情况,而2位跳变为0次的情况,并没有一种情况是发生了一次跳变。 其次36压缩为9: 直接贴一下论文的原话吧,注意上面那张36种模式图,其中00000000与11111111是跳变为0的情况,除了这两个,图中第一列的其他7个都是跳变为2,最后剩下的27个跳变都超过了2,直接丢弃,所以2+7=9。


LBP +KNN实现手写数字识别

在上一次HOG特征的文章中,我们设计了一个小实验,现在我们还是用上次准备的数据,根据LBP特征提取算法+KNN分类器实现一个手写数字识别的问题,在这之前需要说明一点的是,上面的内容中我们一直在阐述各种LBP算法,那么LBP的特征到底如何构建呢? 在图中构建不重叠cell单元,并在每一个cell中构建灰度直方图特征,最后把每个cell的灰度直方图特征做串接组合,构建出整张图的特征,在这里就可以解释为什么等价模式可以降维了,我们还是拿P=8举例,假设一张图构建了160个cell,那么各个LBP算法的特征维数为: 灰度不变LBP: 256*160 旋转不变LBP: 36*160 等价灰度不变LBP: 58*160 等价旋转不变LBP: 9*160 最后我们选择等价旋转不变模式(Num_cell=25)跑个实验,并贴出上次实验的结果:

在上面的实验中,由于数据图只有20*20,单元尺寸为4时,单元个数只有25个,所以在等价旋转不变LBP算法中,特征维度只有9*25,等价模式本来为了降维而生,但是本身就不高的维度降维后,丢失了很多特征信息,这可能是LBP(9)只有86.7%的准确率的重要原因。总结一下,上面的实验结果只是一个很简单的验证,并不能说明LBP(9)算法不好,因为分类结果是特征、分类器、数据特点等等因素共同决定的,讲道理,没有不好的算法,只有合适与不合适!

PS: 1. 数据准备和KNN的部分在上一篇HOG特征中已提及,为节省篇幅不再重复 2. 整个代码有大概500行左右,为了节省篇幅,不贴代码啦,如果大家感兴趣点击这里查看。

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

扫码关注云+社区

领取腾讯云代金券