用于GLCM计算的Python中的滑动窗口

时间:2017-02-25 17:48:52

标签: python image-processing scikit-image glcm

我正在尝试使用GLCM算法在卫星图像中进行纹理分析。 scikit-image文档对此非常有帮助,但对于GLCM计算,我们需要在图像上循环一个窗口大小。这在Python中太慢了。我在stackoverflow上发现了许多关于滑动窗口的帖子,但计算需要永远。我有一个如下所示的例子,它可以工作,但需要永远。我想这一定是一种天真的做法

image = np.pad(image, int(win/2), mode='reflect') 
row, cols = image.shape
feature_map = np.zeros((M, N))

for m in xrange(0, row):
    for n in xrange(0, cols):
        window = image[m:m+win, n:n+win]
        glcm = greycomatrix(window, d, theta, levels)
        contrast = greycoprops(glcm, 'contrast')
        feature_map[m,n] = contrast 

我遇到了skimage.util.view_as_windows方法,这对我来说可能是一个很好的解决方案。我的问题是,当我尝试计算GLCM时,我得到一个错误,上面写着:

  

ValueError:参数image必须是二维数组

这是因为GLCM图像的结果具有4维,而scikit-image view_as_windows方法仅接受2d数组。这是我的尝试

win_w=40
win_h=40

features = np.zeros(image.shape, dtype='uint8')
target = features[win_h//2:-win_h//2+1, win_w//2:-win_w//2+1]
windowed = view_as_windows(image, (win_h, win_w))

GLCM = greycomatrix(windowed, [1], [0, np.pi/4, np.pi/2, 3*np.pi/4], symmetric=True, normed=True)
haralick = greycoprops(GLCM, 'ASM')

有没有人知道如何使用skimage.util.view_as_windows方法计算GLCM?

1 个答案:

答案 0 :(得分:2)

您尝试执行的功能提取是一项计算机密集型任务。我通过仅为整个图像计算一次共现地图来加速你的方法,而不是在滑动窗口的重叠位置上反复计算共现图。

共生图是与原始图像大小相同的图像堆栈,其中 - 对于每个像素 - 强度等级被编码两个强度共同出现的整数代替,即{{1在那个像素处,Ii在偏移像素处。共现图具有与我们考虑的偏移一样多的层(即所有可能的距离 - 角度对)。通过保留共生图,您不需要从头开始在滑动窗口的每个位置计算GLCM,因为您可以重复使用先前计算的共现图来获得邻接矩阵(GLCM)每个距离 - 角度对。这种方法为您提供了显着的速度增益。

我提出的解决方案依赖于以下功能:

Ij

<强>样本

以下结果对应于Landsat图像中的import numpy as np from skimage import io from scipy import stats from skimage.feature import greycoprops def offset(length, angle): """Return the offset in pixels for a given length and angle""" dv = length * np.sign(-np.sin(angle)).astype(np.int32) dh = length * np.sign(np.cos(angle)).astype(np.int32) return dv, dh def crop(img, center, win): """Return a square crop of img centered at center (side = 2*win + 1)""" row, col = center side = 2*win + 1 first_row = row - win first_col = col - win last_row = first_row + side last_col = first_col + side return img[first_row: last_row, first_col: last_col] def cooc_maps(img, center, win, d=[1], theta=[0], levels=256): """ Return a set of co-occurrence maps for different d and theta in a square crop centered at center (side = 2*w + 1) """ shape = (2*win + 1, 2*win + 1, len(d), len(theta)) cooc = np.zeros(shape=shape, dtype=np.int32) row, col = center Ii = crop(img, (row, col), win) for d_index, length in enumerate(d): for a_index, angle in enumerate(theta): dv, dh = offset(length, angle) Ij = crop(img, center=(row + dv, col + dh), win=win) cooc[:, :, d_index, a_index] = encode_cooccurrence(Ii, Ij, levels) return cooc def encode_cooccurrence(x, y, levels=256): """Return the code corresponding to co-occurrence of intensities x and y""" return x*levels + y def decode_cooccurrence(code, levels=256): """Return the intensities x, y corresponding to code""" return code//levels, np.mod(code, levels) def compute_glcms(cooccurrence_maps, levels=256): """Compute the cooccurrence frequencies of the cooccurrence maps""" Nr, Na = cooccurrence_maps.shape[2:] glcms = np.zeros(shape=(levels, levels, Nr, Na), dtype=np.float64) for r in range(Nr): for a in range(Na): table = stats.itemfreq(cooccurrence_maps[:, :, r, a]) codes = table[:, 0] freqs = table[:, 1]/float(table[:, 1].sum()) i, j = decode_cooccurrence(codes, levels=levels) glcms[i, j, r, a] = freqs return glcms def compute_props(glcms, props=('contrast',)): """Return a feature vector corresponding to a set of GLCM""" Nr, Na = glcms.shape[2:] features = np.zeros(shape=(Nr, Na, len(props))) for index, prop_name in enumerate(props): features[:, :, index] = greycoprops(glcms, prop_name) return features.ravel() def haralick_features(img, win, d, theta, levels, props): """Return a map of Haralick features (one feature vector per pixel)""" rows, cols = img.shape margin = win + max(d) arr = np.pad(img, margin, mode='reflect') n_features = len(d) * len(theta) * len(props) feature_map = np.zeros(shape=(rows, cols, n_features), dtype=np.float64) for m in xrange(rows): for n in xrange(cols): coocs = cooc_maps(arr, (m + margin, n + margin), win, d, theta, levels) glcms = compute_glcms(coocs, levels) feature_map[m, n, :] = compute_props(glcms, props) return feature_map 像素裁剪。我考虑了两个距离,四个角度和两个GLCM属性。这导致每个像素的16维特征向量。请注意,滑动窗口是平方的,其边是(250, 200)像素(在此测试中使用的值为2*win + 1)。这个样本运行大约需要6分钟,这比#34;永远&#34; ; - )

win = 19

satellite image