从3d数组中提取2d补丁

时间:2018-02-09 15:24:43

标签: python numpy scikit-learn

scikit-learn的extract_patches_2d可用于将2D图像重塑为一组补丁。 extract_patches是使用NumPy的as_strided

的通用形式
import numpy as np
from sklearn.feature_extraction import image

ex = np.arange(3 * 3).reshape(3, 3)
image.extract_patches_2d(ex, patch_size=(2, 2))
[[[0 1]
  [3 4]]

 [[1 2]
  [4 5]]

 [[3 4]
  [6 7]]

 [[4 5]
  [7 8]]]

我有一个三维数组a,想从每个“最里面的”2d数组中提取2d补丁,然后找到每个2d补丁的(轴不可知)均值。

a = np.arange(2 * 3 * 3).reshape(2, 3, 3)

在这种情况下,我实际上想先在每个(3,3)内部数组上调用extract_patches_2d

patches = np.array([image.extract_patches_2d(i, patch_size=(2, 2)) for i in a])

然后找到每个最里面的2d数组(每个补丁)的平均值:

means = patches.reshape(*patches.shape[:-2], -1).mean(axis=-1)
print(means)
[[  2.   3.   5.   6.]
 [ 11.  12.  14.  15.]]

我如何对此进行矢量化并摆脱上面的for循环?这里重要的是means的第一维的大小等于a第一维的大小。

1 个答案:

答案 0 :(得分:1)

您可以使用scikit-image as view_as_windowspatches作为view添加到输入数组中 -

from skimage.util.shape import view_as_windows

size = 2 # patch size
patches = view_as_windows(a, (1,size,size))[...,0,:,:]

这为我们提供了一个5D数组作为patches,我们可以在最后两个轴上使用mean减少3D输出 -

out = patches.mean((-2,-1))

如果最终输出需要2D,请重新整形以合并最后两个轴 -

out.reshape(a.shape[0],-1)

这也可以使用sklearn extract_patches

def inner_means(arr_3d, patch_size):
    """Axis-agnostic mean of each 2d patch.

    Maintains the first dimension of `arr_3d`.

    patch_size: tuple
        Same syntax as the parameter passed to extract_patches_2d
    """
    shape = (1,) + patch_size
    patches = image.extract_patches(arr_3d, shape)[..., 0, :, :].mean((-2, -1))
    return patches.reshape(*patches.shape[:-2], -1)


a = np.arange(2 * 3 * 3).reshape(2, 3, 3)
    print(inner_means(a, patch_size=(2, 2)))

[[  2.   3.   5.   6.]
 [ 11.  12.  14.  15.]]

或者,要直接获得块状平均值,我们可以使用Scipy中的其中一个卷积工具。使用fftconvolve -

from scipy.signal import fftconvolve

out = fftconvolve(a, np.ones((1,size,size)),mode='valid')/size**2

或者在没有分割的情况下使用scipy.signal.convolvescipy.ndimage.filters.uniform_filter