Python实现LBP纹理提取

慈云数据 2024-04-27 技术支持 37 0

1、什么是LBP纹理特征?

LBP(Local Binary Patterns,局部二值模式)是提取局部特征作为判别依据的,一种有效的纹理描述算子,度量和提取图像局部的纹理信息。它具有旋转不变性和灰度不变性等显著的优点,对光照具有不变性。由T. Ojala, M.Pietikäinen, 和D. Harwood 在1994年提出用于纹理特征提取

LBP特征基本描述:

LBP的基本思想是定义于像素的8邻域中(3x3的窗口), 以中心像素的灰度值为阈值, 将周围8 个像素的值与其比较, 如果周围的像素值小于中心像素的灰度值, 该像素位置就被标记为0, 否则标记为1。这样3x3的邻域内的八个点经过比较,顺时针能够产生8位二进制数(通常转换为十进制,即LBP码,共256种),每个像素得到一个二进制组合, 即得到该窗口中心像素点的LBP值,并用这个值来反映该区域的纹理信息,如下图。

LBP算法的核心思想,是以某个像素点为中心,与其邻域像素点共同计算。所以光照变化很难改变中心像素点的灰度值与周围8个像素的大小关系。因为光照是一种区域性质的变化,而不是单像素性质的变化。

LBP特征改进描述:

1)圆形LBP算子:

基本的 LBP算子的最大缺陷在于它只覆盖了一个3 ∗ 3 3*33∗3固定范围内的小区域,这显然不能满足不同尺寸纹理的需要。为了适应不同尺寸的纹理特征,达到灰度和旋转不变性的要求。Ojala将 3×3邻域扩展到任意邻域,并用圆形邻域代替了正方形邻域。改进后的 LBP 算子允许在半径为 R的圆形邻域内有任意多个像素点。从而得到了半径为R的圆形区域内含有P个采样点的LBP算子,如下图。

2)LBP旋转不变模式算子:

为保证图像旋转时LBP不变,提出了LBP旋转不变算法。即不断旋转圆形邻域得到一系列初始定义的 LBP值,取其最小值作为该邻域的 LBP 值。这样就出现了多个位置模式对应同一个LBP值的情况,但这其实保证了图像旋转以后还是同一个值。如下图,8种模式都对应的一个LBP(00001111),8种模式可以看做一个图旋转个不同的角度(黑色0,白色1)。

3)LBP等价算子:

由上可知LBP会产生很多不同的模式,比如半径5,20个采样点,就有可能产生 2^{20} 种二进制模式,这对图像整体纹理描述很不方便。即使在纹理分类或人脸识别时采用的是LBP模式的统计直方图来进行的,但数据量过大将不合适,且直方图表示过于稀疏。所以需要对LBP模式进行降维,使得利用更少的数据就可以表达很好的图像纹理信息。

Ojala提出了(Uniform Pattern)进行降维,利用LBP算子中0,1改变的次数来进行归类,定义从0到1或从1到0最多有两次突变时,该LBP对应的称为一个等价模式,而等价模式以为的都归为混合模式。这样等价模式的总数为2+2(p-1)+(p-1)(p-2)/2种,其中p为采样点数。0次突变2种,1次突变2(p-1)种,两次突变(p-1)(p-2)/2种。

2、基于python的LBP实现

  • 首先将检测窗口划分为16×16的小区域(cell);
  • 对于每个cell中的一个像素,将相邻的8个像素的灰度值与其进行比较,若周围像素值大于中心像素值,则该像素点的位置被标记为1,否则为0。这样,3*3邻域内的8个点经比较可产生8位二进制数,即得到该窗口中心像素点的LBP值;
  • 然后计算每个cell的直方图,即每个数字(假定是十进制数LBP值)出现的频率;然后对该直方图进行归一化处理。
  • 最后将得到的每个cell的统计直方图进行连接成为一个特征向量,也就是整幅图的LBP纹理特征向量;

    然后便可利用SVM或者其他机器学习算法进行分类了。参考一些博客中的代码实现效果如下:

    from skimage.feature import local_binary_pattern
    import matplotlib.pyplot as plt
    import numpy as np
    from PIL import Image
    img = np.array(Image.open("./111.tif"))
    # lbp是像素矩阵
    n_point, radius = 8, 3
    lbp = local_binary_pattern(img, n_point, radius, 'default')
    max_bins = int(lbp.max() + 1)  # .max()取lbp中最大的数
    # test_hist是某个灰度级的个数即y坐标。-是横坐标。
    test_hist, _ = np.histogram(lbp, normed=True, bins=max_bins, range=(0, max_bins))
    plt.figure(figsize=(10, 4.5))
    plt.imshow(lbp,cmap='gray')
    plt.show()
    plt.pause(10)

    local_binary_pattern参数详解:

    local_binary_pattern(image, P, R, method='default')

    参数(调参)

    image:(N,M)阵列灰度图像。(只能是灰度图)

    P:int圆对称邻居设置点的数量(角度空间的量化)。

    R:float圆的半径(操作员空间分辨率)。

    method:{‘default’,‘ror’,‘uniform’,‘var’}确定模式的方法(调参使用)

    •     'default':原始的局部二值模式,它是灰度但不是旋转不变的。
    •     'ror':扩展灰度和旋转不变的默认实现。
    •     'uniform':改进的旋转不变性和均匀的模式以及角度空间的更精细的量化,灰度和旋转不变。
    •     'nri_uniform':非旋转不变的均匀图案变体,它只是灰度不变的R199。
    •     'var':局部对比度的旋转不变方差度量,图像纹理是旋转但不是灰度不变的。

      返回值:输出:(N,M)阵列LBP图像

      np.histogram()解释:

      np.histogram()是一个生成直方图的函数
      histogram(a,bins=10,range=None,weights=None,density=False);
       
      a是待统计数据的数组;
       
      bins指定统计的区间个数;
       
      range是一个长度为2的元组,表示统计范围的最小值和最大值,默认值None,表示范围由数据的范围决定
       
      weights为数组的每个元素指定了权值,histogram()会对区间中数组所对应的权值进行求和
       
      density为True时,返回每个区间的概率密度;为False,返回每个区间中元素的个数
       
      a = np.random.rand(100)
      hist,bins = np.histogram(a,bins=5,range=(0,1))
      print(hist)
      print(bins)
      # 输出
      # [19 30 15 16 20]
      # [ 0.   0.3  0.4  0.6  0.9 1. ]
微信扫一扫加客服

微信扫一扫加客服

点击启动AI问答
Draggable Icon