在 NumPy 中向量化位置相关函数

Vectorizing a positionally reliant function in NumPy

我了解矢量化的概念,以及当您想要调整每个单独的元素时如何避免使用循环 运行 通过元素,但是我不知道该怎么做这是当我们有一个基于像素相邻值的条件时。

例如,如果我有口罩:

mask = np.array([[0,0,0,0],
                 [1,0,0,0],
                 [0,0,0,1], 
                 [1,0,0,0]])

我想通过评估掩码中的相邻组件来更改元素,如下所示:

if sum(mask[j-1:j+2,i-1:i+2].flatten())>1 and mask[j,i]!=1:
    out[j,i]=1

当我特别需要访问相邻元素时如何向量化操作?

提前致谢。

完整循环:

import numpy as np

mask = np.array([[0,0,0,0], [1,0,0,0], [0,0,0,1],  [1,0,0,0]])
out = np.zeros(mask.shape)
for j in range(len(mask)):
    for i in range(len(mask[0])):
        if sum(mask[j-1:j+2,i-1:i+2].flatten())>1 and mask[j,i]!=1:
            out[j,i]=1

输出:

[[0. 0. 0. 0.]
 [0. 0. 0. 0.]
 [0. 1. 0. 0.]
 [0. 0. 0. 0.]]

这样的'neighborhood sum'操作通常被称为二维卷积。在您的情况下,由于您没有任何权重,因此可以在(IMO 有点不好命名)scipy.ndimage.uniform_filter 中有效地实现它,它可以计算邻域的平均值(总和是 只是平均值乘以大小)。

import numpy as np
from scipy.ndimage import uniform_filter

mask = np.array([[0,0,0,0], [1,0,0,0], [0,0,0,1], [1,0,0,0]])
neighbor_sum = 9 * uniform_filter(mask.astype(np.float32), 3, mode="constant")
neighbor_sum = np.rint(neighbor_sum).astype(int)
out = ((neighbor_sum > 1) & (mask != 1)).astype(int)
print(out)

输出(这与您的示例不同,但手工查看是正确的,假设您不希望边缘环绕):

[[0 0 0 0]
 [0 0 0 0]
 [1 1 0 0]
 [0 0 0 0]]

如果您确实希望边缘环绕(或其他边缘行为),请查看 uniform_filtermode 参数。