使用NumPy填充形状/轮廓

时间:2017-01-29 20:55:33

标签: python numpy matrix

我想填写满足某些属性的numpy矩阵的一部分(可能使用掩码)。即,它是某种形状的矩阵表示,例如,square将是:

square =   [0,0,0,0,0;
            0,1,1,1,0;
            0,1,0,1,0;
            0,1,1,1,0]

变为:

s_filled = [0,0,0,0,0;
            0,1,1,1,0;
            0,1,1,1,0;
            0,1,1,1,0]

和圈子:

circle =   [0,0,0,0,0,0;
            0,0,1,1,0,0;
            0,1,0,0,1,0;
            0,0,1,1,0,0]

并成为:

c_filled = [0,0,0,0,0,0;
            0,0,1,1,0,0;
            0,1,1,1,1,0;
            0,0,1,1,0,0]

这是否可以仅使用numpy而不使用其他外部库? 我想将此函数/算法应用于300x300形状。

非常感谢!

2 个答案:

答案 0 :(得分:3)

使用np.maximum.accumulate非常简单,因为我们可以沿着从左到右,然后从右到左的行使用它一次,并通过减法简单地得到非零的公共区域。这对凸形状很有效。

因此,实现将是 -

def fill_contours(arr):
    return np.maximum.accumulate(arr,1) & \
           np.maximum.accumulate(arr[:,::-1],1)[:,::-1]

以下是在任意形状上运行的示例 -

In [176]: arbitrary
Out[176]: 
array([[0, 0, 1, 0, 0, 0, 0],
       [0, 1, 0, 1, 0, 0, 0],
       [1, 0, 0, 0, 1, 0, 0],
       [0, 1, 0, 0, 1, 0, 0],
       [0, 1, 0, 0, 1, 0, 0],
       [0, 0, 1, 0, 0, 1, 0],
       [0, 1, 0, 0, 1, 0, 0],
       [0, 1, 1, 1, 0, 0, 0]])

In [177]: fill_contours(arbitrary)
Out[177]: 
array([[0, 0, 1, 0, 0, 0, 0],
       [0, 1, 1, 1, 0, 0, 0],
       [1, 1, 1, 1, 1, 0, 0],
       [0, 1, 1, 1, 1, 0, 0],
       [0, 1, 1, 1, 1, 0, 0],
       [0, 0, 1, 1, 1, 1, 0],
       [0, 1, 1, 1, 1, 0, 0],
       [0, 1, 1, 1, 0, 0, 0]])

答案 1 :(得分:1)

这是@Divakar的一些修复方法,用于修复某些边缘情况下的凹面填充。

原始解决方案无法解决这种情况,因为它不会跳过垂直轴上的元素。

例如:

# check out index (7, 2), the result should be 0.0

a = np.array([[0, 0, 1, 0, 0, 0, 0],
              [0, 1, 0, 1, 0, 0, 0],
              [1, 0, 0, 0, 1, 0, 0],
              [0, 1, 0, 0, 1, 0, 0],
              [0, 1, 0, 0, 1, 0, 0],
              [0, 0, 1, 0, 0, 1, 0],
              [0, 0, 1, 0, 1, 0, 0],
              [0, 1, 0, 1, 0, 0, 0]])

fill_contours(a)
"""
original_result
 0.0  0.0  1.0  0.0  0.0  0.0  0.0 
 0.0  1.0  1.0  1.0  0.0  0.0  0.0 
 1.0  1.0  1.0  1.0  1.0  0.0  0.0 
 0.0  1.0  1.0  1.0  1.0  0.0  0.0 
 0.0  1.0  1.0  1.0  1.0  0.0  0.0 
 0.0  0.0  1.0  1.0  1.0  1.0  0.0 
 0.0  0.0  1.0  1.0  1.0  0.0  0.0 
 0.0  1.0  1.0  1.0  0.0  0.0  0.0 
"""

# not apply the fix by considering vertical axis
def fill_contours_fixed(arr):
    return np.maximum.accumulate(arr, 1) &\
           np.maximum.accumulate(arr[:, ::-1], 1)[:, ::-1] &\
           np.maximum.accumulate(arr[::-1, :], 0)[::-1, :] &\
           np.maximum.accumulate(arr, 0)

fill_contours_fixed(a)

"""
fixed_result, (7, 2) is now correct
 0.0  0.0  1.0  0.0  0.0  0.0  0.0 
 0.0  1.0  1.0  1.0  0.0  0.0  0.0 
 1.0  1.0  1.0  1.0  1.0  0.0  0.0 
 0.0  1.0  1.0  1.0  1.0  0.0  0.0 
 0.0  1.0  1.0  1.0  1.0  0.0  0.0 
 0.0  0.0  1.0  1.0  1.0  1.0  0.0 
 0.0  0.0  1.0  1.0  1.0  0.0  0.0 
 0.0  1.0  0.0  1.0  0.0  0.0  0.0  
"""
相关问题