提取numpy数组的边界

11

A成为一个表示掩膜的numpy数组。我想提取与此掩膜对应的边界,即将除边界外的所有内容都设置为零。

例如:

In [22]: A
array([[0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
       [0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
       [0, 0, 1, 1, 1, 1, 1, 1, 0, 0],
       [0, 0, 1, 1, 1, 1, 1, 1, 0, 0],
       [0, 0, 1, 1, 1, 1, 1, 1, 0, 0],
       [0, 0, 1, 1, 1, 1, 1, 1, 0, 0],
       [0, 0, 1, 1, 1, 1, 1, 1, 0, 0],
       [0, 0, 1, 1, 1, 1, 1, 1, 0, 0],
       [0, 0, 1, 1, 1, 1, 1, 1, 0, 0],
       [0, 0, 0, 0, 0, 0, 0, 0, 0, 0]], dtype=int32)
所需输出为:
array([[0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
       [0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
       [0, 0, 1, 1, 1, 1, 1, 1, 0, 0],
       [0, 0, 1, 0, 0, 0, 0, 1, 0, 0],
       [0, 0, 1, 0, 0, 0, 0, 1, 0, 0],
       [0, 0, 1, 0, 0, 0, 0, 1, 0, 0],
       [0, 0, 1, 0, 0, 0, 0, 1, 0, 0],
       [0, 0, 1, 0, 0, 0, 0, 1, 0, 0],
       [0, 0, 1, 1, 1, 1, 1, 1, 0, 0],
       [0, 0, 0, 0, 0, 0, 0, 0, 0, 0]], dtype=int32)

此外,A中的掩码也可以是非线性的。

所以,我的问题是,最有效的方法是什么来获得这个边界呢?

编辑1: 我所说的非线性是什么意思? 考虑一张图像,其中有一个人。对应于此人的掩码是非线性的。


口罩区域是否已知为矩形,并且仅水平或垂直对齐? - Mark Setchell
不是的。掩码也可以是非线性的。我已经更新了问题,说明我所说的非线性边界是什么意思。 - user5806421
当你说“非线性”时,是指边缘不是水平或垂直定向的直线吗? - Mark Setchell
没错。 - user5806421
1个回答

6

获得轮廓的一个技巧是,在反转的掩模上使用3x3的全1数组作为核进行二值膨胀,并查找它与输入之间的公共部分。对于4连通边界,它将是全部由1组成的数组;而对于8连通,则是一个加号形状的1数组 -

from scipy.ndimage.morphology import binary_dilation

k = np.ones((3,3),dtype=int) # for 4-connected
k = np.zeros((3,3),dtype=int); k[1] = 1; k[:,1] = 1 # for 8-connected
out = binary_dilation(a==0, k) & a

示例运行 -

输入数组:

In [384]: a
Out[384]: 
array([[0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
       [0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
       [0, 0, 0, 1, 1, 1, 0, 0, 0, 0],
       [0, 0, 1, 1, 1, 1, 0, 0, 0, 0],
       [0, 0, 1, 1, 1, 1, 0, 0, 0, 0],
       [0, 0, 1, 1, 1, 0, 0, 0, 0, 0],
       [0, 1, 1, 1, 1, 0, 0, 0, 0, 0],
       [0, 1, 1, 1, 0, 0, 0, 0, 0, 0],
       [0, 1, 1, 1, 0, 0, 0, 0, 0, 0],
       [0, 0, 0, 0, 0, 0, 0, 0, 0, 0]])

In [385]: from scipy.ndimage.morphology import binary_dilation

解决4连通问题:
In [386]: k = np.ones((3,3),dtype=int)

In [390]: binary_dilation(a==0, k) & a
Out[390]: 
array([[0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
       [0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
       [0, 0, 0, 1, 1, 1, 0, 0, 0, 0],
       [0, 0, 1, 1, 0, 1, 0, 0, 0, 0],
       [0, 0, 1, 0, 1, 1, 0, 0, 0, 0],
       [0, 0, 1, 0, 1, 0, 0, 0, 0, 0],
       [0, 1, 1, 1, 1, 0, 0, 0, 0, 0],
       [0, 1, 0, 1, 0, 0, 0, 0, 0, 0],
       [0, 1, 1, 1, 0, 0, 0, 0, 0, 0],
       [0, 0, 0, 0, 0, 0, 0, 0, 0, 0]])

解决8连通问题:

In [411]: k = np.zeros((3,3),dtype=int); k[1] = 1; k[:,1] = 1

In [412]: k
Out[412]: 
array([[0, 1, 0],
       [1, 1, 1],
       [0, 1, 0]])

In [413]: binary_dilation(a==0, k) & a
Out[413]: 
array([[0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
       [0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
       [0, 0, 0, 1, 1, 1, 0, 0, 0, 0],
       [0, 0, 1, 0, 0, 1, 0, 0, 0, 0],
       [0, 0, 1, 0, 0, 1, 0, 0, 0, 0],
       [0, 0, 1, 0, 1, 0, 0, 0, 0, 0],
       [0, 1, 0, 0, 1, 0, 0, 0, 0, 0],
       [0, 1, 0, 1, 0, 0, 0, 0, 0, 0],
       [0, 1, 1, 1, 0, 0, 0, 0, 0, 0],
       [0, 0, 0, 0, 0, 0, 0, 0, 0, 0]])

我们也可以使用binary_erosion函数:
from scipy.ndimage.morphology import binary_erosion
out = a-binary_erosion(a,k)

1
太棒了!正是我一直在寻找的。 - user5806421

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接