NumPy 2D数组:获取所有连接且共享相同值的条目的索引

3
我有一个2D的numpy数组,其填充了从0到N的整数值,如何获取所有直接相连且共享相同值的条目的索引。
补充说明:大部分条目都是零,可以忽略!
示例输入数组:
[ 0 0 0 0 0 ]
[ 1 1 0 1 1 ]
[ 0 1 0 1 1 ]
[ 1 0 0 0 0 ]
[ 2 2 2 2 2 ]

期望的输出索引:

1: [ [1 0] [1 1] [2 1] [3 0] ] # first 1 cluster
   [ [1 3] [1 4] [2 3] [2 4] ] # second 1 cluster

2: [ [4 0] [4 1] [4 2] [4 3] [4 4] ] # only 2 cluster

输出数组的格式并不重要,我只需要能够分离值集群并且能够访问单个索引的地方。
我最初考虑的是:
N = numberClusters
x = myArray

for c in range(N):
   for i in np.where(x==c):
         # fill output array with i

但是这样会忽略具有相同值的簇之间的分离。

连接意味着“在同一行上”吗? - Jacquot
我指的“相连”是指它们在x、y或对角线坐标上“接触”彼此。请看我如何将“1”聚类的示例,希望这能让它更清晰明了。 - gustavz
1
寻找实现“连通组件标记算法”的代码。 - MBo
1个回答

4
您可以使用skimage.measure.label(如果需要,可使用pip install scikit-image进行安装)来完成此操作:
import numpy as np
from skimage import measure

# Setup some data
np.random.seed(42)
img = np.random.choice([0, 1, 2], (5, 5), [0.7, 0.2, 0.1])
# [[2 0 2 2 0]
#  [0 2 1 2 2]
#  [2 2 0 2 1]
#  [0 1 1 1 1]
#  [0 0 1 1 0]]

# Label each region, considering only directly adjacent pixels connected
img_labeled = measure.label(img, connectivity=1)
# [[1 0 2 2 0]
#  [0 3 4 2 2]
#  [3 3 0 2 5]
#  [0 5 5 5 5]
#  [0 0 5 5 0]]

# Get the indices for each region, excluding zeros
idx = [np.where(img_labeled == label)
       for label in np.unique(img_labeled)
       if label]
# [(array([0]), array([0])),
#  (array([0, 0, 1, 1, 2]), array([2, 3, 3, 4, 3])),
#  (array([1, 2, 2]), array([1, 0, 1])),
#  (array([1]), array([2])),
#  (array([2, 3, 3, 3, 3, 4, 4]), array([4, 1, 2, 3, 4, 2, 3]))]

# Get the bounding boxes of each region (ignoring zeros)
bboxes = [area.bbox for area in measure.regionprops(img_labeled)]
# [(0, 0, 1, 1),
#  (0, 2, 3, 5),
#  (1, 0, 3, 2),
#  (1, 2, 2, 3),
#  (2, 1, 5, 5)]

可以使用非常实用的函数skimage.measure.regionprops找到边界框,它包含有关区域的丰富信息。对于边界框,它返回一个元组(min_row, min_col, max_row, max_col),其中属于边界框的像素在半开区间[min_row; max_row)[min_col; max_col)中。


让我们在聊天中继续这个讨论 - gustavz
@GustavZ 是哪个标签?是原始数组中的值吗?你可以使用[img[i][0] for i in idx]来获取它。如果你想要由标记给出的标签,你可以使用[area.label for area in measure.regionprops(img_labeled)] - Graipher
@GustavZ 请看我的上面的评论:[area.label for area in measure.regionprops(img_labeled)] - Graipher
你的意思是 [area.label for area in measure.regionprops(img_labeled)] 吗?这个做法和 skimage 生成的标签有所不同。但我想要的是:我的原始 image 是一个分割地图,其中所有像素都是类标签,在计算每个聚类的框之后,我还想知道每个聚类的标签... 如果你已经回答过这个问题,请原谅,但我看不出在哪里。 - gustavz
没事了,我搞定了。使用 area.coords 我可以访问到正确的像素 :) 谢谢! - gustavz
显示剩余4条评论

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