【问题标题】:NumPy: fill fields surrounding a 1 in an arrayNumPy:填充数组中 1 周围的字段
【发布时间】:2016-10-24 16:22:52
【问题描述】:

假设我有一个如下所示的 4x4 矩阵:

[[0, 0, 0, 0]
 [0, 0, 1, 0]
 [0, 0, 0, 0]
 [0, 0, 0, 0]]

我想编写一个函数,将一个周围的所有 4 个字段都转换为 1。

上面的矩阵会变成:

[[0, 0, 1, 0]
 [0, 1, 1, 1]
 [0, 0, 1, 0]
 [0, 0, 0, 0]]

我知道使用 if 语句可以做到这一点,但我真的想优化我的代码。

矩阵只包含 0 和 1。如果 1 在矩阵的边缘,则 1 不应该环绕,即如果最左边的字段是 1,最右边的字段仍然保持在 0。另外,我使用的是 Python 3.5

有没有更数学或更简洁的方法来做到这一点?

【问题讨论】:

  • 如果有2怎么办?如果相邻字段已经是1 怎么办? 1 只有一个吗?它可以在“边缘”吗?那么,应该把它包起来吗?
  • 刚刚编辑了原帖。非常感谢您的评论
  • 所以,对于边界元素,我们不会有 4 个邻居,而是 2 或 3 个邻居。那么,我们只会在那些中填写 1 吗?
  • 是的,完全正确。我知道这听起来很奇怪,但是解释这个任务的背景故事需要很长时间并且是无关紧要的。如果你愿意,我当然可以给你解释

标签: python arrays numpy matrix


【解决方案1】:

这看起来像二元膨胀。 SciPy 中有一个函数可以有效地实现这一点:

>>> from scipy.ndimage import binary_dilation
>>> x
array([[0, 0, 0, 0],
       [0, 0, 1, 0],
       [0, 0, 0, 0],
       [0, 0, 0, 0]])

>>> binary_dilation(x).astype(int)
array([[0, 0, 1, 0],
       [0, 1, 1, 1],
       [0, 0, 1, 0],
       [0, 0, 0, 0]])

边缘处的 1 将按照您指定的方式处理(即不换行)。

有关更多选项和参数,请参阅documentation

【讨论】:

    【解决方案2】:

    FWIW,这是一种仅使用 Numpy 的方法。我们用零的行和列填充原始数据,然后将填充数组的按位或偏移副本放在一起。

    import numpy as np
    
    def fill(data):
        rows, cols = data.shape
        padded = np.pad(data, 1, 'constant', constant_values=0)
        result = np.copy(data)
        for r, c in ((0, 1), (1, 0), (1, 2), (2, 1)):
            result |= padded[r:r+rows, c:c+cols]
        return result
    
    data = np.asarray(
        [
            [0, 0, 0, 0],
            [0, 0, 1, 0],
            [0, 0, 0, 0],
            [0, 0, 0, 0],
        ], dtype='uint8')
    print(data, '\n')
    
    result = fill(data)
    print(result)
    

    输出

    [[0 0 0 0]
     [0 0 1 0]
     [0 0 0 0]
     [0 0 0 0]] 
    
    [[0 0 1 0]
     [0 1 1 1]
     [0 0 1 0]
     [0 0 0 0]]
    

    【讨论】:

    • 非常感谢。出于性能原因,我将使用此任务的 scipy 版本,但很高兴了解该功能背后的理论
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2022-12-10
    • 2022-01-23
    • 2018-05-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-11-06
    相关资源
    最近更新 更多