用于识别对象的变量面积阈值 - python

0 投票
1 回答
640 浏览
提问于 2025-04-18 16:34

我有一个数组,这个数组里包含了一系列形状的大小和位置的信息:数组中为零的地方没有形状,而非零的地方则有形状。不同的形状之间用零隔开,所以如果你把数组里的每个点都画出来,就能看到各种形状的地图。希望这样解释能让你明白,如果不明白的话,这里有一个包含四个不同形状的示例数组:

np.array([[0, 0, 0, 1, 0, 0, 0],
          [0, 0, 0, 0, 0, 0, 0],
          [1, 1, 0, 0, 1, 0, 0],
          [1, 1, 0, 0, 0, 1, 1],
          [0, 0, 0, 0, 0, 1, 1],
          [3, 5, 2, 0, 0, 0, 0]])

我需要计算并识别这些形状,但我只想包括那些面积超过某个阈值的形状。我希望这个面积阈值是场中最大形状面积的1/15。(在上面的例子中,最大面积是5。)

我的问题是:我该如何用Python找到场中最大形状的面积,而不需要逐个识别每个形状呢?

编辑

为了更清楚地说明我所说的“形状”,以下代码会绘制出数组的图像,显示出四个不同的物体:

import numpy as np
import matplotlib.pyplot as plt

a = np.array([[0, 0, 0, 1, 0, 0, 0],
              [0, 0, 0, 0, 0, 0, 0],
              [1, 1, 0, 0, 1, 0, 0],
              [1, 1, 0, 0, 0, 1, 1],
              [0, 0, 0, 0, 0, 1, 1],
              [1, 1, 1, 0, 0, 0, 0]])
ind = np.nonzero(arr)
x = ind[0]
y = ind[1]
plt.imshow(arr)
plt.show()

1 个回答

1

你可以使用 scipy.ndimage.label 这个工具来找到你数组中相连的非零区域,然后用 scipy.ndimage.sum 来计算每个区域的面积:

from scipy import ndimage

labels, nshapes = ndimage.label(a)
areas = ndimage.sum(a, labels=labels, index=range(1, nshapes))

idx = np.argmax(areas)
biggest_shape = labels == (idx + 1)

在你的例子中,恰好有两个“形状”的面积是相同的:

from matplotlib import pyplot as plt

fig, (ax1, ax2, ax3) = plt.subplots(1, 3)

ax1.imshow(a, cmap=plt.cm.jet)
ax2.imshow(labels, cmap=plt.cm.jet)
ax3.imshow(biggest_shape, cmap=plt.cm.jet)

enter image description here

更新

传给 scipy.ndimage.labelstructure 参数决定了哪些相邻的元素被认为是“连接”的(具体可以查看上面链接的文档)。如果你想让对角线相邻的元素也被视为连接,可以传入一个全是1的3x3数组:

labels, nshapes = ndimage.label(a, structure=np.ones((3, 3)))

enter image description here

撰写回答