【问题标题】:Extract indices of a 2D binary array提取二维二进制数组的索引
【发布时间】:2015-09-06 23:41:34
【问题描述】:

我有一个由 0 和 1 组成的 numpy 数组(数据)。

import numpy as np

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

我想提取“1”被相邻的由 1 组成的 5*5 元素包围的索引。

预期的索引用星号表示,即 (3,3)。 布尔数组形式的答案也可以。

[[False False False False False False]
 [False 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]]

我试过了

from scipy.ndimage.morphology import binary_erosion


kernel = np.ones((5,5))

result = binary_erosion(data, kernel)
print result

[[False False False False False False]
 [False False False False False False]
 [False False  True False False False]
 [False False  True False False False]
 [False False False False False False]
 [False False False False False False]]

它产生了两个“真”位置,但我只想要一个在 (3,3)。

怎么做?

编辑:链接问题中显示的解决方案也给出了意想不到的答案。

【问题讨论】:

  • 标记为True 的第二个元素也被1s 的5x5 框包围...你为什么不喜欢它?
  • @6502 这是因为从第一个 True 已经占用的位置开始计算 1。我想避免重复这样的......
  • @Divakar 不,我在提问之前看到了这个问题,但是该问题中显示的解决方案也给出了我在问题中所坚持的意外答案。

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


【解决方案1】:

另一种类似于@rth 的方法

由于您的数据由10 组成,您可以将其放入int 数组中并使用uniform_filter 来实现相同的目的:

>>> mask = uniform_filter(data, 5, mode='constant')
>>> mask
array([[0, 0, 0, 0, 0, 0],
       [0, 0, 0, 0, 0, 0],
       [0, 0, 1, 0, 0, 0],
       [0, 0, 1, 0, 0, 0],
       [0, 0, 0, 0, 0, 0],
       [0, 0, 0, 0, 0, 0]])

未被1包围的均值小于1,并四舍五入为0,因为它是一个整数数组。

要获得第一个索引,您可以执行以下操作:

>>> y, x = np.where(mask)
>>> y[0], x[0]
(2, 2)

【讨论】:

    【解决方案2】:

    除了binary_erosion,您可以使用scipy.ndimage.generic_filter 来实现此目的,

    from scipy.ndimage import generic_filter
    generic_filter(data, np.all, size=(5,5), mode='constant', cval=0).astype(np.bool)
    

    但是你会得到与上面相同的结果,

    array([[0, 0, 0, 0, 0, 0],
           [0, 0, 0, 0, 0, 0],
           [0, 0, 1, 0, 0, 0],
           [0, 0, 1, 0, 0, 0],
           [0, 0, 0, 0, 0, 0],
           [0, 0, 0, 0, 0, 0]])  # using 1, 0 instead of True, False for readability
    

    因为它是您问题的正确答案。示例矩阵中的 6 行是对称的,使用给定的内核,结果中将有 2 个对称的 True 元素。

    如果您想避免这种情况,您可以使用非对称内核大小:size=(6,5),尽管这会在第 3 行而不是第 2 行中产生一个真正的元素。这可以通过手动填充 kernel 数组来解决使用binary_erosion 时为零。

    【讨论】:

    • 感谢您的解释。是不是只能从左上角读取 5 列和 5 行的数据;那么如果所有元素都是1,提取它的中间索引等等..?
    • 嗯,scipy.ndimage 适用于像素,它根本没有“中像素或中索引”的概念。当然可以这样做,例如通过ndimage.zoom 执行binary_erosion 来增加分辨率,然后返回到初始分辨率。仍然因为,您的原始数组是上下对称的,您必须以某种方式打破这种对称性才能仅获得 1 个像素。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2019-08-31
    • 1970-01-01
    • 2023-03-07
    • 1970-01-01
    • 1970-01-01
    • 2018-06-25
    • 2020-07-30
    相关资源
    最近更新 更多