广播相同形状的多维数组索引

时间:2019-12-04 03:13:32

标签: numpy

我有一个mask数组,它代表一个二维二进制图像。假设它很简单:

mask = np.zeros((9, 9), dtype=np.uint8)
# 0 0 0 | 0 0 0 | 0 0 0
# 0 0 0 | 0 0 0 | 0 0 0
# 0 0 0 | 0 0 0 | 0 0 0
# ------+-------+------
# 0 0 0 | 0 0 0 | 0 0 0
# 0 0 0 | 0 0 0 | 0 0 0
# 0 0 0 | 0 0 0 | 0 0 0
# ------+-------+------
# 0 0 0 | 0 0 0 | 0 0 0
# 0 0 0 | 0 0 0 | 0 0 0
# 0 0 0 | 0 0 0 | 0 0 0

假设我想翻转ninth左中的元素:

# 0 0 0 | 0 0 0 | 0 0 0
# 0 0 0 | 0 0 0 | 0 0 0
# 0 0 0 | 0 0 0 | 0 0 0
# ------+-------+------
# 1 1 1 | 0 0 0 | 0 0 0
# 1 1 1 | 0 0 0 | 0 0 0
# 1 1 1 | 0 0 0 | 0 0 0
# ------+-------+------
# 0 0 0 | 0 0 0 | 0 0 0
# 0 0 0 | 0 0 0 | 0 0 0
# 0 0 0 | 0 0 0 | 0 0 0

我不正确的方法是这样的:

x = np.arange(mask.shape[0])
y = np.arange(mask.shape[1])
mask[np.logical_and(y >= 3, y < 6), x < 3] = 1
# 0 0 0 | 0 0 0 | 0 0 0
# 0 0 0 | 0 0 0 | 0 0 0
# 0 0 0 | 0 0 0 | 0 0 0
# ------+-------+------
# 1 0 0 | 0 0 0 | 0 0 0
# 0 1 0 | 0 0 0 | 0 0 0
# 0 0 1 | 0 0 0 | 0 0 0
# ------+-------+------
# 0 0 0 | 0 0 0 | 0 0 0
# 0 0 0 | 0 0 0 | 0 0 0
# 0 0 0 | 0 0 0 | 0 0 0

(这是我真正要处理的约束的简化,在这种情况下,它很难表示为mask[:3,3:6] = 1之类的东西。请考虑约束是任意的,例如x % 2 == 0 && y % 3 == 0会。

当两个索引数组的形状相同时,Numpy的行为是将它们成对放置,最终只能选择上面的3个元素,而不是我想要的9个。

如何使用适用于不同轴的约束条件更新正确的元素?鉴于约束是独立的,是否可以仅通过评估我的约束N + M次而不是N * M来做到这一点?

2 个答案:

答案 0 :(得分:1)

根据您的评论,让我们尝试以下更出色的示例:

mask = np.zeros((90,90), dtype=np.uint8)

# criteria
def f(x,y): return ((x-20)**2 < 50) & ((y-20)**2 < 50)

# ranges
x,y = np.arange(90), np.arange(90)

# meshgrid
xx,yy = np.meshgrid(x,y)

zz = f(xx,yy)

# mask
mask[zz] = 1
plt.imshow(mask, cnap='gray')

输出:

enter image description here

答案 1 :(得分:1)

您无法broadcast布尔数组,但可以使用ix_构造等效的数字索引:

In [330]: np.ix_((y>=3)&(y<6), x<3)                                             
Out[330]: 
(array([[3],
        [4],
        [5]]), array([[0, 1, 2]]))

应用:

In [331]: arr = np.zeros((9,9),int)                                             
In [332]: arr[_330] = 1                                                         
In [333]: arr                                                                   
Out[333]: 
array([[0, 0, 0, 0, 0, 0, 0, 0, 0],
       [0, 0, 0, 0, 0, 0, 0, 0, 0],
       [0, 0, 0, 0, 0, 0, 0, 0, 0],
       [1, 1, 1, 0, 0, 0, 0, 0, 0],
       [1, 1, 1, 0, 0, 0, 0, 0, 0],
       [1, 1, 1, 0, 0, 0, 0, 0, 0],
       [0, 0, 0, 0, 0, 0, 0, 0, 0],
       [0, 0, 0, 0, 0, 0, 0, 0, 0],
       [0, 0, 0, 0, 0, 0, 0, 0, 0]])

尝试broadcast的布尔值会直接引发错误(too many indices):

arr[((y>=3)&(y<6))[:,None], x<3]
相关问题