首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >Python中用于GLCM计算的滑动窗口

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

Stack Overflow用户
提问于 2017-02-25 17:48:52
回答 1查看 3.7K关注 0票数 5

我试图用GLCM算法在卫星图像中进行纹理分析。科学工具包-图像文档是非常有帮助的,但对于GLCM的计算,我们需要一个窗口的大小在图像上循环。这在Python中太慢了。我在堆栈溢出上发现了许多关于滑动窗口的帖子,但是计算需要永远的时间。我有一个例子如下所示,它可以工作,但要花费很长时间。我想这一定是一种天真的做法。

代码语言:javascript
运行
复制
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图像的结果有4d维,而scikit图像view_as_windows方法只接受2d数组。这是我的尝试

代码语言:javascript
运行
复制
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?

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2017-03-14 19:31:44

您要执行的特征提取是一项计算机密集型任务。我已经加速了你的方法,只计算了整个图像的共现映射一次,而不是在滑动窗口的重叠位置上一次又一次地计算共现映射。

共现映射是与原始图像相同大小的图像堆栈,其中每个像素的强度级别被整数替换,整数编码两个强度的共现,即该像素处的Ii和偏移像素处的Ij。共现地图有尽可能多的层,我们认为偏移(即所有可能的距离-角度对)。通过保留共现映射,您不需要从零开始在滑动窗口的每个位置计算GLCM,因为您可以重用以前计算的共现映射,以获得每个距离角对的邻接矩阵( GLCMs)。这种方法为您提供了显著的速度增益。

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

代码语言:javascript
运行
复制
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

演示

以下结果对应于来自陆地卫星图像的(250, 200)像素裁剪。我考虑了两个距离,四个角度,和两个GLCM性质。这将为每个像素生成一个16维特征向量.注意,滑动窗口是平方的,它的侧面是2*win + 1像素(在这个测试中使用了win = 19值)。这个示例运行大约需要6分钟,比“永远”要短得多;-)

代码语言:javascript
运行
复制
In [331]: img.shape
Out[331]: (250L, 200L)

In [332]: img.dtype
Out[332]: dtype('uint8')

In [333]: d = (1, 2)

In [334]: theta = (0, np.pi/4, np.pi/2, 3*np.pi/4)

In [335]: props = ('contrast', 'homogeneity')

In [336]: levels = 256

In [337]: win = 19

In [338]: %time feature_map = haralick_features(img, win, d, theta, levels, props)
Wall time: 5min 53s    

In [339]: feature_map.shape
Out[339]: (250L, 200L, 16L)

In [340]: feature_map[0, 0, :]    
Out[340]:  
array([ 10.3314,   0.3477,  25.1499,   0.2738,  25.1499,   0.2738,
        25.1499,   0.2738,  23.5043,   0.2755,  43.5523,   0.1882,
        43.5523,   0.1882,  43.5523,   0.1882])

In [341]: io.imshow(img)
Out[341]: <matplotlib.image.AxesImage at 0xce4d160>

票数 6
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/42459493

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档