【问题标题】:Applying a disc shaped mask to several locations in a NumPy array将圆盘形掩码应用于 NumPy 数组中的多个位置
【发布时间】:2016-08-28 13:51:04
【问题描述】:

我有一个与此处提出的问题类似的问题:How to apply a disc shaped mask to a numpy array?。但是,我不想屏蔽单个圆形扇区,而是创建一个具有多个圆形扇区的蒙版(数字是可变的)。这些面具都具有相同的半径,但不同的中心。这些中心的坐标存储在一个 numpy 二维数组中。例如:

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

其中ab代表蒙版的中心; 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)

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

【问题讨论】:

    标签: python arrays numpy scipy vectorization


    【解决方案1】:

    您可以将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
    

    【讨论】:

    • 非常感谢,这是完美的!
    • 除了这个方法比遍历我所有的中心点来创建蒙版更耗时。可能是因为我的面具的形状是 1400x1400。最初大约需要 0.35 秒,使用这种方法大约需要 10 秒(0.35 可能看起来很低,但我必须创建很多蒙版)。
    • @WilmarvanOmmeren 通常你要处理多少maskcenters 点?如果它是一个小数字,那么循环解决方案可能更合适。
    • 好吧,我仍在使用一个子集来测试我的算法。知道我有大约 15000 个点,而使用完整的数据集我可能会有数百万个点(有趣的事实:这些点代表我研究区域中的树中心)。
    • @WilmarvanOmmeren 添加了另一种方法。看看有没有更好的?
    猜你喜欢
    • 2012-01-28
    • 2021-07-01
    • 2012-07-17
    • 2017-12-05
    • 2014-12-16
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多