计算NumPy数组的周长

6

我想计算给定 numpy 数组结构的周长。周长指的是 numpy 数组中结构的确切周长。该结构可能包括孔洞。

我的当前方法大致如下:

import numpy   
a = numpy.zeros((6,6), dtype=numpy.int)
a[1:5, 1:5] = 1;a[3,3] = 0
# Way 1
s = ndimage.generate_binary_structure(2,1)
c = ndimage.binary_dilation(a,s).astype(a.dtype)
b = c - a  
numpy.sum(b) # The result, however the hole is calculated as 1, although there are 4 edges

# Way 2
b = ndimage.distance_transform_cdt(a == 0,metric='taxicab') == 1 
b = b.astype(int)
numpy.sum(b) # same as above

enter image description here

如您所见,它显示了所有相邻的单元格,但它们的总和并不等于区块的周长。在示例数组中,孔被计算为1,尽管它实际上有4个边缘。对于不同形状的更大的孔,也存在类似的问题。
我以前曾提出过类似的问题,但是所有提供的解决方案最终都无法得到正确的输出值。 有人有办法解决这个问题吗? 请勿使用除numpy、scipy和基本包之外的其他软件包。

1
在这个例子中,你期望得到什么值? - Eric
一个整数值。在上面的测试数据集中,最终的值应该是20,因为有20条边。 - Curlew
3个回答

6

计算内部和边缘的边数(假设为二进制图像):

n_interior = abs(diff(a, axis=0)).sum() + abs(diff(a, axis=1)).sum()
n_boundary = a[0,:].sum() + a[:,0].sum() + a[-1,:].sum() + a[:,-1].sum()
perimeter = n_interior + n_boundary

如果图像已经被正确地进行了零填充,您可以省略n_boundary。

4
你是说,在这个图像中,分开蓝色和红色瓷砖的长度为1的边的总数吗?在上面的图片中,这个数字将是28。在你给代码的例子中(它略有不同,没有四个角与其余边界瓷砖不同),它将是20。 如果这是你想计算的内容,你可以这样做: numpy.sum(a [:, 1:]!= a [:,:-1]) + numpy.sum(a [1:,:]!= a [:-1,:])

图像是绘制出的结果数组(b)。 - Curlew
好的,可以了!我选择你的解决方案,因为它更小更快。 - Curlew

0
我添加我的答案是因为现有的答案存在同样的问题: 如果一个像素既与上方的像素不同又与左侧的像素不同,那么如果你这样做,它会被计算两次:
numpy.sum(a[:,1:] != a[:,:-1]) + numpy.sum(a[1:,:] != a[:-1,:])

可以通过在求和之前使用逐元素或来解决这个问题:

np.logical_or(
    (a[:,1:] != a[:,:-1])[1:,:], 
    (a[1:,:] != a[:-1,:])[:,1:]).sum()

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