Python图像处理的类似于blockproc的函数

5

编辑:这是一张图片,因此所建议的(如何像Matlab的blkproc(blockproc)函数一样高效地处理numpy数组中的块)对我来说并不起作用。

我有以下matlab代码:

fun = @(block_struct) ...
std2(block_struct.data) * ones(size(block_struct.data));

B=blockproc(im2double(Icorrected), [4 4], fun);

我想重新编写我的代码,这次使用Python。我已经安装了Scikit并且正在尝试像这样使用它。

b = np.std(a, axis = 2) 

当然问题在于我没有将std应用于一些块,就像上面那样。
我该怎么做呢?开始循环并尝试为每个X * X块调用函数吗?那么我不会保持它的大小。
有其他更高效的方法吗?

您IP地址为143.198.54.68,由于运营成本限制,当前对于免费用户的使用频率限制为每个IP每72小时10次对话,如需解除限制,请点击左下角设置图标按钮(手机用户先点击左上角菜单按钮)。 - Andy Hayden
@AndyHayden 这是我已经检查过的内容,但考虑到提问的时间和像Scikit这样的库的介绍,我希望有更清晰的解释。 - Rentonie
@AndyHayden 指出的 as_strided 解决方案是你最好的选择。 这里还有另一个使用 as_strided 的解决方案:http://stackoverflow.com/a/26848312/2823755 - wwii
@wwii 我的列表已经按照B[:, :]部分之前所示的格式排列。虽然我无法理解解决方案的其余部分,但还是采用了自己平庸的方法。 - Rentonie
3个回答

1
如果 窗口 没有重叠,您可以重新调整数据以适应您的需要:
查找 9x9 数组的 3x3 窗口的均值。
import numpy as np

>>> a
array([[ 0,  1,  2,  3,  4,  5,  6,  7,  8],
       [ 9, 10, 11, 12, 13, 14, 15, 16, 17],
       [18, 19, 20, 21, 22, 23, 24, 25, 26],
       [27, 28, 29, 30, 31, 32, 33, 34, 35],
       [36, 37, 38, 39, 40, 41, 42, 43, 44],
       [45, 46, 47, 48, 49, 50, 51, 52, 53],
       [54, 55, 56, 57, 58, 59, 60, 61, 62],
       [63, 64, 65, 66, 67, 68, 69, 70, 71],
       [72, 73, 74, 75, 76, 77, 78, 79, 80]])

找到新的形状
>>> window_size = (3,3)
>>> tuple(np.array(a.shape) / window_size) + window_size
(3, 3, 3, 3)
>>> b = a.reshape(3,3,3,3)

在第一和第三个轴上找到平均值。
>>> b.mean(axis = (1,3))
array([[ 10.,  13.,  16.],
       [ 37.,  40.,  43.],
       [ 64.,  67.,  70.]])
>>> 

4x4数组的2x2窗口:

>>> a = np.arange(16).reshape((4,4))
>>> window_size = (2,2)
>>> tuple(np.array(a.shape) / window_size) + window_size
(2, 2, 2, 2)
>>> b = a.reshape(2,2,2,2)
>>> b.mean(axis = (1,3))
array([[  2.5,   4.5],
       [ 10.5,  12.5]])
>>> 

如果窗口大小不能整除数组大小,则无法正常工作。在这种情况下,您需要在窗口中添加一些重叠或者如果您只想要重叠,则可以使用numpy.lib.stride_tricks.as_strided - 可以在Efficient Overlapping Windows with Numpy找到通用的N-D函数。

2D数组的另一个选项是sklearn.feature_extraction.image.extract_patches_2d,ndarray的选项是sklearn.feature_extraction.image.extract_patches。每个都会调整数组的步幅以产生补丁/窗口。


0

我做了以下事情

io.use_plugin('pil', 'imread')
a = io.imread('C:\Users\Dimitrios\Desktop\polimesa\\arizona.jpg')

B = np.zeros((len(a)/2 +1, len(a[0])/2 +1))


for i in xrange(0, len(a), 2):
    for j in xrange(0, len(a[0]), 2):
        x.append(a[i][j])
        if i+1 < len(a):
            x.append(a[i+1][j])
        if j+1 < len(a[0]):
           x.append(a[i][j+1])
        if i+1 < len(a) and j+1 < len(a[0]):
           x.append(a[i+1][j+1])
        B[i/2][j/2] = np.std(x)
        x[:] = []         

我认为这是正确的。通过2进行图像迭代,并将每个相邻节点添加到列表中并计算标准差。

编辑*后来编辑为4x4块。


0
我们可以用以下方式在Python中实现blockproc()
def blockproc(im, block_sz, func):
    h, w = im.shape
    m, n = block_sz
    for x in range(0, h, m):
        for y in range(0, w, n):
            block = im[x:x+m, y:y+n]
            block[:,:] = func(block)
    return im

现在,让我们将其应用于使用局部直方图均衡化实现对比度增强,以低对比度的月球图像(大小为512x512)作为输入,并选择32x32块:

from skimage import data, exposure
img = data.moon()
img = img / img.max()
m, n = 64, 64
img_eq = blockproc(img.copy(), (m, n), exposure.equalize_hist)

显示输入和输出图像:

enter image description here

请注意,该函数对图像进行原地修改,因此应传递输入图像的副本。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接