我假设您的矩阵是二进制的,其中非零值表示提取的段,而零值是您不关心的值。 measure 模块中的 scikit-image label 函数可能很有趣:http://scikit-image.org/docs/dev/api/skimage.measure.html#skimage.measure.label
它本质上是执行连通分量分析,并用一个整数标记所有单独闭合的分量。不过,您需要注意如何指定连接性。有 4 连通性和 8 连通性,前者仅使用北、南、东和西方向找到连通区域,而 8 连通性使用所有 8 个方向(北、南、东、西、东北、东南、西北、西南)。您将使用 connectivity 选项并为 4 连接指定 1 并为 8 连接指定 2。
但是,默认连接将是完全连接,因此对于 2D 情况,它将是 2 选项。我怀疑你会是这样。矩阵中为零的任何 blob 都将被标记为零。事不宜迟,这是一个非常简单的可重现示例:
In [1]: from skimage.measure import label
In [2]: import numpy as np
In [3]: x = np.zeros((8,8))
In [4]: x[0:4,0:4] = 1
In [5]: x[6:8,6:8] = 1
In [6]: x
Out[6]:
array([[ 1., 1., 1., 1., 0., 0., 0., 0.],
[ 1., 1., 1., 1., 0., 0., 0., 0.],
[ 1., 1., 1., 1., 0., 0., 0., 0.],
[ 1., 1., 1., 1., 0., 0., 0., 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.],
[ 0., 0., 0., 0., 0., 0., 1., 1.]])
In [7]: label(x)
Out[7]:
array([[1, 1, 1, 1, 0, 0, 0, 0],
[1, 1, 1, 1, 0, 0, 0, 0],
[1, 1, 1, 1, 0, 0, 0, 0],
[1, 1, 1, 1, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 2, 2],
[0, 0, 0, 0, 0, 0, 2, 2]], dtype=int64)
我们可以看到我在左上角和右下角创建了两个独立的岛。运行label 函数后,它会返回一个标签矩阵,用于标识属于彼此的像素区域。具有相同 ID 的像素表示属于同一区域。
为了向您展示连接是如何发挥作用的,这里有另一个简单的示例:
In [1]: import numpy as np
In [2]: from skimage.measure import label
In [3]: y = np.array([[0,1,0,0],[1,1,1,0],[0,1,0,1]])
In [4]: y
Out[4]:
array([[0, 1, 0, 0],
[1, 1, 1, 0],
[0, 1, 0, 1]])
In [5]: label(y, connectivity=1)
Out[5]:
array([[0, 1, 0, 0],
[1, 1, 1, 0],
[0, 1, 0, 2]], dtype=int64)
In [6]: label(y)
Out[6]:
array([[0, 1, 0, 0],
[1, 1, 1, 0],
[0, 1, 0, 1]], dtype=int64)
输入在左上角有一个十字图案,在右下角有一个单独的非零值。如果我们使用 4-connectivity,右下角会被归类为不同的标签,但如果我们使用默认的连接(full),每个像素都会被归类为相同的标签。