【问题标题】:Extract indices of a NumPy array提取 NumPy 数组的索引
【发布时间】:2015-06-13 06:48:01
【问题描述】:

我有一个仅包含 0 和 1 元素的 NumPy 数组,如下所示:

import numpy as np
data = np.array([[1, 1 , 0 , 0 , 0 , 0 , 1 , 0],
                 [1, 1 , 1 , 1 , 1 , 1 , 1 , 0],
                 [1, 1 , 1 , 1 , 1 , 1 , 1 , 0],
                 [0, 0 , 1 , 1 , **1** , 1 , 1 , 0],
                 [0, 0 , 1 , 1 , 1 , 1 , 1 , 1],
                 [1, 1 , 1 , 1 , 1 , 1 , 1 , 0],
                 [1, 1 , 0 , 0 , 0 , 0 , 0 , 0]])

我必须找出元素 1 的索引,它在每个方向上都被 1 in 2 x 2 像素包围。

预期答案的位置以粗体显示。

我正在寻找更简单、更快捷的方法。

【问题讨论】:

    标签: performance numpy scipy scikit-learn scikit-image


    【解决方案1】:

    你可以使用一些signal processing -

    import numpy as np
    from scipy import signal
    
    # Input
    data = np.array([[1, 1 , 0 , 0 , 0 , 0 , 1 , 0],
                     [1, 1 , 1 , 1 , 1 , 1 , 1 , 0],
                     [1, 1 , 1 , 1 , 1 , 1 , 1 , 0],
                     [0, 0 , 1 , 1 , 1 , 1 , 1 , 0],
                     [0, 0 , 1 , 1 , 1 , 1 , 1 , 1],
                     [1, 1 , 1 , 1 , 1 , 1 , 1 , 0],
                     [1, 1 , 0 , 0 , 0 , 0 , 0 , 0]])
    
    # Extent of the search           
    extent = 2;
    
    # Kernel to be used with 2D convolution                 
    kernel = np.ones((2*extent+1,2*extent+1))
    
    # Perform 2D convolution with input data and kernel 
    filt_out = signal.convolve2d(data, kernel, boundary='symm', mode='same')
    
    # Find where the convolution resulted in a perfect score, 
    # i.e is equal to the number of elements in kernel
    R,C = np.where( filt_out == kernel.size )
    

    输出 -

    In [66]: print(R,C)
    [3] [4]
    

    本节列出了一种替代方法,使用 ndimage 执行与前一种方法相同的卷积,保持其余步骤相同。这是获取卷积输出的代码filt_out -

    import scipy.ndimage
    filt_out = scipy.ndimage.convolve(data,kernel)
    

    【讨论】:

    • 感谢您的尝试。我投了赞成票。但是,我正在考虑使用 scipy.ndimage 来做这件事。你能建议我另一种方法吗?
    • 喜欢maximum_filter、minimum_filter?
    • @EricBal 我认为 max 或 min 过滤器在这里不起作用,但这些过滤器会在该窗口中寻找最大值。我们想要的是该窗口内的所有元素都是ones。所以我们需要的是对窗口内的所有元素求和,所以卷积适合这里。
    • @EricBal 添加了ndimage 的替代方法,这可能更容易理解?
    • 那么,filt_out == np.sum(kernel.ravel()) 是什么意思?
    【解决方案2】:

    basic morphological operation 很容易:

    import numpy as np
    from scipy.ndimage.morphology import binary_erosion
    
    
    data = np.array([[1, 1 , 0 , 0 , 0 , 0 , 1 , 0],
                     [1, 1 , 1 , 1 , 1 , 1 , 1 , 0],
                     [1, 1 , 1 , 1 , 1 , 1 , 1 , 0],
                     [0, 0 , 1 , 1 , 1 , 1 , 1 , 0],
                     [0, 0 , 1 , 1 , 1 , 1 , 1 , 1],
                     [1, 1 , 1 , 1 , 1 , 1 , 1 , 0],
                     [1, 1 , 0 , 0 , 0 , 0 , 0 , 0]])
    
    expected = np.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 , 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]])
    
    # otherwise known as np.ones((5, 5))
    structuring_element = np.array([[1, 1, 1, 1, 1],
                                    [1, 1, 1, 1, 1],
                                    [1, 1, 1, 1, 1],
                                    [1, 1, 1, 1, 1],
                                    [1, 1, 1, 1, 1]])
    
    # will be of dtype np.bool but you can convert with .astype(np.int)
    # if you really need
    result = binary_erosion(data, structuring_element)
    
    print(result)
    
    print(np.allclose(result, expected))
    

    【讨论】:

      猜你喜欢
      • 2018-10-22
      • 1970-01-01
      • 2015-05-22
      • 2017-03-29
      • 1970-01-01
      • 1970-01-01
      • 2011-10-23
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多