首页 文章

Python:采用非矩形区域的GLCM

提问于
浏览
1

我一直在使用滑雪图像的SLIC实现来分割超像素中的图像 . 我想使用GLCM从这些超像素中提取其他特征以解决分类问题 . 这些超像素不是矩形 . 在MATLAB中,您可以将像素设置为NaN,算法将忽略它们(link) . 我可以使用它在超像素周围制作边界框,然后将未使用的像素设置为NaN .

但是,skimage中的greycomatrix函数与MATLAB实现完全不同 . 将像素设置为NaN时,函数会在断言时失败,以检查所有值是否都大于0 .

是否有可用于非矩形ROI的Python实现?

2 回答

  • 2

    虽然 mahotas 也是一个优秀的计算机视觉库,但是没有必要停止使用 skimage 来做到这一点 .

    正如@Tonechas指出的那样,必要的是将那些NaN值设置为整数,因为 np.nan 的类型为 floatgreycomatrix 函数需要一个整数数组 .

    最简单的选择是将那些 NaN 's to zero but, if you already have zero values in your pixels and don'想要混合它们,你可以选择任何其他常量 . 之后,您所要做的就是从GLCM中过滤出所选择的值(再次,通常为零) .

    要理解这意味着什么,让我们看看 skimage 告诉我们greycomatrix function的输出:

    4-D ndarray [...]值P [i,j,d,theta]是灰度级j出现在距离d处并且与灰度级i成角度θ的次数 . 如果normed为False,则输出为uint32类型,否则为float64 . 尺寸为:水平x水平x距离数x角度数 .

    换句话说,数组的前两个维度定义了一个矩阵,告诉我们两个不同的值有多少次相隔一定距离 . 请注意,GLCM确保 not 保持输入数组的形状 . 那些行和列告诉我们值是如何相关的 .

    知道了这一点,很容易过滤掉ROI之外的值(想象我们将NaN设置为零):

    glcm = greycomatrix(img, [1], [0])  # Calculate the GLCM "one pixel to the right"
    filt_glcm = glcm[1:, 1:, :, :]           # Filter out the first row and column
    

    现在,您可以轻松计算过滤后的GLCM的Haralick属性 . 例如:

    greycoprops(filt_glcm, prop='contrast')
    
  • 1

    问题是您必须将整数数组传递给 greycomatrix ,但 np.nan 的类型为 float (有关详细信息,请查看this thread) . 因此,您无法将ROI外的像素编码为 NaN .

    处理非矩形ROI的近似解决方法是将ROI外的像素设置为 0 并使用mahotas库中的函数 haralick . 此函数返回从四个不同GLCM中提取的13个Haralick特征,对应于四个2-D方向和距离参数的特定值 .

    从文档:

    ignore_zeros可用于使函数忽略任何零值像素(作为背景) .

    总之,您需要屏蔽那些超出ROI的像素,并在调用 haralick 时将 ignore_zeros 设置为 True .


    DEMO

    首先,让我们生成一些模拟数据:

    In [213]: import numpy as np
    
    In [214]: shape = (3, 4)
    
    In [215]: levels = 8
    
    In [216]: np.random.seed(2017)
    
    In [217]: x = np.random.randint(0, levels, size=shape)
    
    In [218]: x
    Out[218]: 
    array([[3, 1, 6, 5],
           [2, 0, 2, 2],
           [3, 7, 7, 7]])
    

    然后我们必须从图像中移除所有零,因为在该方法中,零强度级别被保留用于ROI之外的像素 . 值得指出的是,将强度 01 合并为单一强度 1 会在结果中引入不准确性 .

    In [219]: x[x == 0] = 1
    
    In [220]: x
    Out[220]: 
    array([[3, 1, 6, 5],
           [2, 1, 2, 2],
           [3, 7, 7, 7]])
    

    下一步包括为ROI外部的像素定义遮罩(在此玩具示例中,图像的四个角)并将这些像素设置为 0 .

    In [221]: non_roi = np.zeros(shape=shape, dtype=np.bool)
    
    In [222]: non_roi[np.ix_([0, -1], [0, -1])] = True
    
    In [223]: non_roi
    Out[223]: 
    array([[ True, False, False,  True],
           [False, False, False, False],
           [ True, False, False,  True]], dtype=bool)
    
    In [224]: x[non_roi] = 0
    
    In [225]: x
    Out[225]: 
    array([[0, 1, 6, 0],
           [2, 1, 2, 2],
           [0, 7, 7, 0]])
    

    我们现在可以从GLCM的非矩形ROI中执行特征提取:

    In [226]: import mahotas.features.texture as mht
    
    In [227]: features = mht.haralick(x, ignore_zeros=True)
    
    In [228]: features.size
    Out[228]: 52
    
    In [229]: features.ravel()
    Out[229]: array([ 0.18      ,  5.4       ,  0.5254833 , ...,  0.81127812,
           -0.68810414,  0.96300727])
    

    检查共生矩阵的外观可能很有用 . 例如,“像素到右边”GLCM将是:

    In [230]: mht.cooccurence(x, 0)
    Out[230]: 
    array([[0, 1, 0, ..., 0, 1, 2],
           [1, 0, 2, ..., 0, 1, 0],
           [0, 2, 2, ..., 0, 0, 0],
           ..., 
           [0, 0, 0, ..., 0, 0, 0],
           [1, 1, 0, ..., 0, 0, 0],
           [2, 0, 0, ..., 0, 0, 2]])
    

相关问题