我想知道是否有一种有效的方法可以从更大的 numpy
数组中获取子数组。
我拥有的是 np.where
的应用程序。我“手动”迭代 x
和 y
作为偏移量,并将带有内核的 where
应用于从具有适当尺寸的较大数组中提取的每个矩形。
但是在numpy
的方法集合中有更直接的方法吗?
import numpy as np
example = np.arange(20).reshape((5, 4))
# e.g. a cross kernel
a_kernel = np.asarray([[0, 1, 0], [1, 1, 1], [0, 1, 0]])
np.where(a_kernel, example[1:4, 1:4], 0)
# returns
# array([[ 0, 6, 0],
# [ 9, 10, 11],
# [ 0, 14, 0]])
def arrays_from_kernel(a, a_kernel):
width, height = a_kernel.shape
y_max, x_max = a.shape
return [np.where(a_kernel, a[y:(y + height), x:(x + width)], 0)
for y in range(y_max - height + 1)
for x in range(x_max - width + 1)]
sub_arrays = arrays_from_kernel(example, a_kernel)
这将返回我需要进一步处理的数组。
# [array([[0, 1, 0],
# [4, 5, 6],
# [0, 9, 0]]),
# array([[ 0, 2, 0],
# [ 5, 6, 7],
# [ 0, 10, 0]]),
# ...
# array([[ 0, 9, 0],
# [12, 13, 14],
# [ 0, 17, 0]]),
# array([[ 0, 10, 0],
# [13, 14, 15],
# [ 0, 18, 0]])]
上下文:类似于 2D 卷积,我想在每个子数组上应用自定义函数(例如平方数的乘积)。
最佳答案
目前,您正在数据上手动推进一个滑动窗口 - 步幅技巧来拯救! (不,这不是我编造的——实际上在 numpy 中有一个名为 stride_tricks
的子模块!)而不是手动将窗口构建到数据中,然后调用 np.where()
在它们上面,如果你有一个数组中的窗口,你可以只调用一次 np.where()
。 Stride 技巧允许您创建这样的数组,而无需复制数据。
让我解释一下。 numpy 中的普通切片创建原始数据的 View 而不是副本。这是通过引用原始数据,但更改用于访问数据的步幅(即在两个元素或两行之间跳转多少,等等)来完成的。步幅技巧允许您比切片和 reshape 更自由地修改这些步幅,因此您可以例如。多次迭代相同的数据,这在这里很有用。
让我演示一下:
import numpy as np
example = np.arange(20).reshape((5, 4))
a_kernel = np.array([[0, 1, 0], [1, 1, 1], [0, 1, 0]])
def sliding_window(data, win_shape, **kwargs):
assert data.ndim == len(win_shape)
shape = tuple(dn - wn + 1 for dn, wn in zip(data.shape, win_shape)) + win_shape
strides = data.strides * 2
return np.lib.stride_tricks.as_strided(data, shape=shape, strides=strides, **kwargs)
def arrays_from_kernel(a, a_kernel):
windows = sliding_window(a, a_kernel.shape)
return np.where(a_kernel, windows, 0)
sub_arrays = arrays_from_kernel(example, a_kernel)
关于python - 基于numpy中的内核提取子数组,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57538406/