【问题标题】:Why does the local_binary_pattern function in scikit-image provide same value for different patterns?为什么 scikit-image 中的 local_binary_pattern 函数为不同的模式提供相同的值?
【发布时间】:2016-12-24 23:16:00
【问题描述】:

我正在使用 scikit-image 包中的 local_binary_pattern 函数。我想计算半径 1 内 8 个邻居的旋转不变均匀 LBP。这是我的 Python 代码:

import numpy as np
from skimage.feature import local_binary_pattern

image = np.array([[150, 137, 137, 146, 146, 148],
                  [145, 144, 144, 144, 142, 144],
                  [149, 144, 144, 143, 153, 147],
                  [145, 144, 147, 150, 145, 150],
                  [146, 146, 139, 148, 144, 148],
                  [129, 139, 142, 150, 146, 140]]).astype(np.uint8)

lbp = local_binary_pattern(image, 8, 1, "uniform")

print("image =")
print(image)
print("lbp =")
print(lbp)

这是输出

image =
[[150 137 137 146 146 148]
 [145 144 144 144 142 144]
 [149 144 144 143 153 147]
 [145 144 147 150 145 150]
 [146 146 139 148 144 148]
 [129 139 142 150 146 140]]
lbp =
[[ 0.  5.  5.  1.  9.  0.]
 [ 9.  6.  9.  9.  8.  9.]
 [ 0.  8.  6.  8.  0.  3.]
 [ 9.  7.  1.  0.  7.  0.]
 [ 1.  1.  8.  9.  7.  1.]
 [ 3.  4.  9.  0.  2.  3.]]

让我感到困惑的是lbp 中的某些相同值不对应于相同的统一模式。比如lbp[1, 1]lbp[2, 2]都是6,但是image[1, 1]的LBP是:

1 0 0
1 x 1
1 1 1

image[2, 2] 的 LBP 是:

1 1 1
1 x 0
1 1 1

根据lbp 中的值,我假设local_binary_pattern 函数使用“大于或等于”来与邻居进行比较。

image[1, 1]image[2, 2] 的 LBP 都是统一的。但是image[1, 1]image[2, 2] 怎么会有相同的 LBP 值呢?

【问题讨论】:

    标签: python numpy feature-extraction scikit-image lbph-algorithm


    【解决方案1】:

    为了提高对 LBP 描述符旋转的鲁棒性,正方形邻域被圆形邻域所取代。在由八个像素形成的圆形邻域中,对角线上的四个邻域与像素中心不重合。这些邻居的强度值通常通过双线性插值计算。下图以图形方式解释了为什么您的示例图像中的一些 LBP3×3 模式与 LBP8,1 模式不同。

    代码

    w_cen  =  (1-1/np.sqrt(2))**2  # Weights
    w_diag  =  (1/np.sqrt(2))**2
    w_orto  =  (1-1/np.sqrt(2))*(1/np.sqrt(2))
    
    def bilinear_interpoplation(i_cen, i_diag, i_hor, i_ver):
        return i_cen*w_cen + i_diag*w_diag + i_hor*w_orto + i_ver*w_orto
    
    def circular_neighbourhood(x):
        [I7, I6, I5] = x[0, :]
        [I0, Ic, I4] = x[1, :]
        [I1, I2, I3] = x[2, :]
        I7i = bilinear_interpolation(Ic, I7, I0, I6)
        I5i = bilinear_interpolation(Ic, I5, I4, I6)
        I3i = bilinear_interpolation(Ic, I3, I4, I2)
        I1i = bilinear_interpolation(Ic, I1, I0, I2)
        interpolated = np.array([[I7i, I6, I5i], 
                                 [ I0, Ic,  I4], 
                                 [I1i, I2, I3i]])
        return interpolated
    
    def binary_pattern(x):
        return np.where(x >= x[1, 1], 1, 0)
    
    def display_lbps(patch):
        interpolated = circular_neighbourhood(patch)
        print('Patch =')
        print(patch)
        print('LBP of patch =')
        print(binary_pattern(patch))
        print('Interpolated patch =')
        print(interpolated)
        print('LBP of interpolated patch =')
        print(binary_pattern(interpolated))
    
    display_lbps(image[0:3, 0:3])
    display_lbps(image[1:4, 1:4])
    

    【讨论】:

      【解决方案2】:

      旋转不变的 LBP 不直接使用邻居的像素值,而是使用圆上插值的值(用于旋转不变性)。见https://github.com/scikit-image/scikit-image/blob/master/skimage/feature/_texture.pyx#L156

      另见原始 LBP 论文http://vision.stanford.edu/teaching/cs231b_spring1415/papers/lbp.pdf,其中提到“不下降的邻居的灰度值 通过插值估计恰好位于像素中心的像素。”

      【讨论】:

      • 非常感谢您的回答。但是根据论文中的图1,半径1内的8个邻居不应该是8个相邻像素吗?
      • 半径为 1 的点的位置确实在 8 个邻居内,但不在对角邻居像素的中心,因此需要插值。
      • 啊,我明白了。非常感谢您的回答!
      猜你喜欢
      • 1970-01-01
      • 2015-11-13
      • 2014-05-20
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-03-17
      • 2014-10-25
      • 1970-01-01
      相关资源
      最近更新 更多