如何有效地提取numpy中的子数组?

Rom*_*man 2 python arrays optimization numpy

我有一个以 3D numpy 数组形式给出的图像(宽度、高度和颜色作为尺寸)。现在我想提取给定形状的所有可能的子图像。例如,原始图像的宽度和高度分别为300和200像素,我想提取宽度和高度分别等于10和20像素的所有子图像。此外,我希望将每个子图像作为一维数组(为此我需要指定特定的像素顺序)。

我通过以下方式解决问题:

for col0 in range(w_max - max_shift):
    x3s_new = [x + col0 for x in x3s]
    for row0 in range(h_max - max_shift):

        vec_1 = []
        for col_shift, row_shift in px_inds:
            col = col0 + col_shift
            row = row0 + row_shift
            vec_1 += [ia[row, col, 0], ia[row, col, 1], ia[row, col, 2]]

        y3s_new = [y + row0 for y in y3s]
        vec_2 = list(ia[y3s_new, x3s_new, z3s])
Run Code Online (Sandbox Code Playgroud)

在上面的代码中,我对表示图像的“矩阵”的列和行进行了循环。然后,我将每个像素(由其列和行给出)视为子图像的左上角并提取子图像。

和是以一维数组vec_1vec_2列表)形式给出的所需子图像。它们是相同的,我只是想测试哪种方法更快。令人惊讶的是,生成的时间vec_2vec_1. 然而,根据我对问题的回答,预计会更快。那么,为什么它不更快呢?

最后,我还想知道是否有更快的替代方法来循环遍历图像矩阵的所有列和行。

总而言之,我的问题是:如何以更快的方式实现我所需要的?目前,我需要大约 5 分钟来“处理”一张图像,这对于我的目的来说是不可接受的。

rth*_*rth 5

您应该使用 Numpy 切片。

给定一个 3D numpy array M,您可以选择它的一个子数组,例如,

M_selection = M[i_min:i_max, j_min:j_max, k_min:k_max]
Run Code Online (Sandbox Code Playgroud)

或者,显式定义切片,

sl_i = slice(i_min, i_max)
sl_j = slice(j_min, j_max)
sl_k = slice(k_min, k_max)
M_selection = M[sl_i, sl_j, sl_k]
Run Code Online (Sandbox Code Playgroud)

其中(i_min, i_max)等是子数组的边界。

有关更多详细信息,请参阅高级 Numpy 索引文档。