将圆盘形掩模应用于NumPy阵列中的多个位置

时间:2016-05-03 13:24:43

标签: python arrays numpy scipy vectorization

我有一个问题类似于这里提出的问题:How to apply a disc shaped mask to a numpy array?。但是,我想创建一个具有多个循环扇区的掩码(数字是可变的),而不是屏蔽单个循环扇区。这些面具都具有相同的半径,但不同的中心。这些中心的坐标存储在numpy 2d数组中。例如:

maskcenters = array([[1, 1],
   [7, 2],
   [2, 8]])

现在围绕一个中心创建一个圆形遮罩(半径2),我可以简单地使用Bi Rico给出的解决方案:

import numpy as np

a, b = maskcenters[0]
n = 10
r = 2

y,x = np.ogrid[-a:n-a, -b:n-b]
mask = x*x + y*y <= r*r

其中 a b 代表蒙版的中心; n 要掩盖的数组大小;和 r 半径。

这会产生如下掩码:

#output
array([[ True,  True,  True, False, False, False, False, False, False],
   [ True,  True,  True,  True, False, False, False, False, False],
   [ True,  True,  True, False, False, False, False, False, False],
   [False,  True, False, False, False, False, False, False, False],
   [False, False, False, False, False, False, False, False, False],
   [False, False, False, False, False, False, False, False, False],
   [False, False, False, False, False, False, False, False, False],
   [False, False, False, False, False, False, False, False, False],
   [False, False, False, False, False, False, False, False, False]], dtype=bool)

但是,我有一个可变数量的中心,我想围绕它创建面具。我知道如何使用for循环创建多个圆形蒙版,但这会减慢代码速度。使用10x10阵列中的示例掩码中心,我的最佳结果是:

#output
array([[ True,  True,  True, False, False, False, False, False,  True],
   [ True,  True,  True,  True, False, False, False,  True,  True],
   [ True,  True,  True, False, False, False,  True,  True,  True],
   [False,  True, False, False, False, False, False,  True,  True],
   [False, False, False, False, False, False, False, False,  True],
   [False, False,  True, False, False, False, False, False, False],
   [False,  True,  True,  True, False, False, False, False, False],
   [ True,  True,  True,  True,  True, False, False, False, False],
   [False,  True,  True,  True, False, False, False, False, False]], dtype=bool)

知道如何在不使用循环的情况下创建此蒙版吗?

1 个答案:

答案 0 :(得分:2)

您可以将scipy's binary_dilation与磁盘形状的内核一起使用,如此 -

# Define inputs
maskcenters = np.array([
   [1, 1],
   [7, 2],
   [2, 8]])

out_shp = (10,10) # Output array shape
r = 2 # Radius of circles

# Get a disk kernel
X,Y = [np.arange(-r,r+1)]*2
disk_mask = X[:,None]**2 + Y**2 <= r*r

# Initialize output array and set the maskcenters as 1s 
out = np.zeros(out_shp,dtype=bool)
out[maskcenters[:,0],maskcenters[:,1]] = 1

# Use binary dilation to get the desired output
out = binary_dilation(out,disk_mask)

输出 -

In [64]: print out
[[ True  True  True False False False False False  True False]
 [ True  True  True  True False False False  True  True  True]
 [ True  True  True False False False  True  True  True  True]
 [False  True False False False False False  True  True  True]
 [False False False False False False False False  True False]
 [False False  True False False False False False False False]
 [False  True  True  True False False False False False False]
 [ True  True  True  True  True False False False False False]
 [False  True  True  True False False False False False False]
 [False False  True False False False False False False False]]

这是使用simple indexing -

的另一种方法
X,Y = [np.arange(-r,r+1)]*2
disk_mask = X[:,None]**2 + Y**2 <= r*r
Ridx,Cidx = np.where(disk_mask)

out = np.zeros(out_shp,dtype=bool)

absidxR = maskcenters[:,None,0] + Ridx-r
absidxC = maskcenters[:,None,1] + Cidx-r

valid_mask = (absidxR >=0) & (absidxR <out_shp[0]) & \
             (absidxC >=0) & (absidxC <out_shp[1])

out[absidxR[valid_mask],absidxC[valid_mask]] = 1