确定numpy数组中的相邻区域
Determine adjacent regions in numpy array
我正在寻找以下内容。我有一个标记为区域的 numpy 数组。 numpy 数组表示分割图像。区域是具有相同值的许多相邻单元格。每个地区都有其独特的价值。具有 3 个区域的简化版本如下所示:
x = np.array([[1, 1, 1], [1, 1, 2], [2, 2, 2], [3, 3, 3]], np.int32)
输出:
array([[1, 1, 1],
[1, 1, 2],
[2, 2, 2],
[3, 3, 3]])
在上面的示例中,我们有 3 个独立的区域,每个区域都标有唯一值(在本例中为 1、2、3)。
我想要的是每个单独区域的相邻(相邻)区域的值。所以在这种情况下:
- 区域 1 与区域 2 相邻
- 区域 2 与区域 1 和 3 相邻
- 区域 3 与区域 2 相邻
实现此目标的最优雅、最快速的方法是什么?
非常感谢!
我知道任务是 return 数组中与给定数字(例如 2)相邻的所有不同条目。使用 NumPy 方法实现此目的的一种方法是使用 roll 将给定区域上下左右移动一个单位。对移位的区域进行逻辑或运算,并且对所有符合此条件的不同元素进行 returned。然后它仍然删除该区域本身,因为它不被认为是它自己的邻居。
由于 roll
在两端重新引入了超出数组边界的值(此处不希望如此),因此额外的步骤是将此行或列替换为 False。
import numpy as np
x = np.array([[1, 1, 1], [1, 1, 2], [2, 2, 2], [3, 3, 3]], np.int32)
region = 2 # number of region whose neighbors we want
y = x == region # convert to Boolean
rolled = np.roll(y, 1, axis=0) # shift down
rolled[0, :] = False
z = np.logical_or(y, rolled)
rolled = np.roll(y, -1, axis=0) # shift up
rolled[-1, :] = False
z = np.logical_or(z, rolled)
rolled = np.roll(y, 1, axis=1) # shift right
rolled[:, 0] = False
z = np.logical_or(z, rolled)
rolled = np.roll(y, -1, axis=1) # shift left
rolled[:, -1] = False
z = np.logical_or(z, rolled)
neighbors = set(np.unique(np.extract(z, x))) - set([region])
print(neighbors)
如果区域用小整数标记(理想情况下从 0
到 n
),这些标签可用于索引到结果数组:
n = x.max()
tmp = np.zeros((n+1, n+1), bool)
# check the vertical adjacency
a, b = x[:-1, :], x[1:, :]
tmp[a[a!=b], b[a!=b]] = True
# check the horizontal adjacency
a, b = x[:, :-1], x[:, 1:]
tmp[a[a!=b], b[a!=b]] = True
# register adjacency in both directions (up, down) and (left,right)
result = (tmp | tmp.T)
对于问题中的示例数组:
In [58]: result.astype(int)
Out[58]:
array([[0, 0, 0, 0],
[0, 0, 1, 0],
[0, 1, 0, 1],
[0, 0, 1, 0]])
In [60]: np.column_stack(np.nonzero(result))
Out[60]:
array([[1, 2],
[2, 1],
[2, 3],
[3, 2]])
In [361]: # Assuming labels start from `1`
[np.flatnonzero(row) for row in result[1:]]
Out[361]: [array([2]), array([1, 3]), array([2])]
我正在寻找以下内容。我有一个标记为区域的 numpy 数组。 numpy 数组表示分割图像。区域是具有相同值的许多相邻单元格。每个地区都有其独特的价值。具有 3 个区域的简化版本如下所示:
x = np.array([[1, 1, 1], [1, 1, 2], [2, 2, 2], [3, 3, 3]], np.int32)
输出:
array([[1, 1, 1],
[1, 1, 2],
[2, 2, 2],
[3, 3, 3]])
在上面的示例中,我们有 3 个独立的区域,每个区域都标有唯一值(在本例中为 1、2、3)。
我想要的是每个单独区域的相邻(相邻)区域的值。所以在这种情况下:
- 区域 1 与区域 2 相邻
- 区域 2 与区域 1 和 3 相邻
- 区域 3 与区域 2 相邻
实现此目标的最优雅、最快速的方法是什么?
非常感谢!
我知道任务是 return 数组中与给定数字(例如 2)相邻的所有不同条目。使用 NumPy 方法实现此目的的一种方法是使用 roll 将给定区域上下左右移动一个单位。对移位的区域进行逻辑或运算,并且对所有符合此条件的不同元素进行 returned。然后它仍然删除该区域本身,因为它不被认为是它自己的邻居。
由于 roll
在两端重新引入了超出数组边界的值(此处不希望如此),因此额外的步骤是将此行或列替换为 False。
import numpy as np
x = np.array([[1, 1, 1], [1, 1, 2], [2, 2, 2], [3, 3, 3]], np.int32)
region = 2 # number of region whose neighbors we want
y = x == region # convert to Boolean
rolled = np.roll(y, 1, axis=0) # shift down
rolled[0, :] = False
z = np.logical_or(y, rolled)
rolled = np.roll(y, -1, axis=0) # shift up
rolled[-1, :] = False
z = np.logical_or(z, rolled)
rolled = np.roll(y, 1, axis=1) # shift right
rolled[:, 0] = False
z = np.logical_or(z, rolled)
rolled = np.roll(y, -1, axis=1) # shift left
rolled[:, -1] = False
z = np.logical_or(z, rolled)
neighbors = set(np.unique(np.extract(z, x))) - set([region])
print(neighbors)
如果区域用小整数标记(理想情况下从 0
到 n
),这些标签可用于索引到结果数组:
n = x.max()
tmp = np.zeros((n+1, n+1), bool)
# check the vertical adjacency
a, b = x[:-1, :], x[1:, :]
tmp[a[a!=b], b[a!=b]] = True
# check the horizontal adjacency
a, b = x[:, :-1], x[:, 1:]
tmp[a[a!=b], b[a!=b]] = True
# register adjacency in both directions (up, down) and (left,right)
result = (tmp | tmp.T)
对于问题中的示例数组:
In [58]: result.astype(int)
Out[58]:
array([[0, 0, 0, 0],
[0, 0, 1, 0],
[0, 1, 0, 1],
[0, 0, 1, 0]])
In [60]: np.column_stack(np.nonzero(result))
Out[60]:
array([[1, 2],
[2, 1],
[2, 3],
[3, 2]])
In [361]: # Assuming labels start from `1`
[np.flatnonzero(row) for row in result[1:]]
Out[361]: [array([2]), array([1, 3]), array([2])]