python - 基于numpy中的内核提取子数组

标签 python arrays numpy

我想知道是否有一种有效的方法可以从更大的 numpy 数组中获取子数组。

我拥有的是 np.where 的应用程序。我“手动”迭代 xy 作为偏移量,并将带有内核的 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/

相关文章:

python - 为什么 TensorFlow matmul() 比 NumPy multiply() 慢得多?

python - 如何使用 opencv python 解决 theta 迷宫?

python - 2D 可变迭代器/生成器

python - 使用 Xpath 单击页面上的所有元素会导致 ElementNotVisibleException

java - 从各种 EditText 字段获取文本

python - 在python中将指数形式的数字转换为十进制形式

javascript - 尝试从数组中获取随机图像,取而代之的是所有相同的图像

javascript - 转换 JavaScript 二维数组

python - 如何通过在 python 中读取 csv 来检查特定列中值的大小

python - 位置参数和关键字参数的求值顺序