在 2D numpy 网格中查找相邻元素
Find adjacent elements in a 2D numpy grid
所以我有一个 2D Numpy 数组,看起来像这样:
[[1,1,1,2,2],
[1,1,1,2,2],
[1,2,2,2,2]]
数组中的每个数字代表一个区域。我想生成一个布尔数组,在相邻元素不完全相等的位置上显示 True
,即在区域边界上。所以结果应该是这样的:
[[False, False, True, False],
...etc
我知道一个简单的双循环可以解决问题,但我需要更快的东西。
一般来说,您正在寻找边缘检测滤镜。
处理此问题的方法不止一种,但基本思想是将 [-1, 1]
或 [-1, 0, 1]
等简单过滤器与数据进行卷积。 scipy.ndimage
和 scikit-image 是开始的好地方。请记住,处理一般情况的方法不止一种。
但是,如果您想要最简单的情况,您可以使用基本的 numpy 操作:
import numpy as np
x = np.array([[1,1,1,2,2],
[1,1,1,2,2],
[1,2,2,2,2]])
edges = np.abs(np.diff(x, axis=1)) > 0
这产生:
array([[False, False, True, False],
[False, False, True, False],
[ True, False, False, False]], dtype=bool)
如果您希望输出与输入具有相同的形状,您有几个不同的选择。您可以用左侧或右侧边缘值填充输入数组:
# Pad the right-hand side with the edge values
# Use [(0, 0), (1, 0)] to pad the left instead.
xpad = np.pad(x, [(0, 0), (0, 1)], mode='edge')
edges = np.abs(np.diff(xpad, axis=1)) > 0
这会产生:
array([[False, False, True, False, False],
[False, False, True, False, False],
[ True, False, False, False, False]], dtype=bool)
在这种特定情况下,您可以使用 np.gradient
而不是填充数组。 gradient
将在边缘使用不同的算法以确保保持数组大小:
dy, dx = np.gradient(x)
edges = np.abs(dx) > 0
这会产生稍厚的边框,因为它使用的算法与简单地减去相邻元素略有不同:
array([[False, False, True, True, False],
[False, False, True, True, False],
[ True, True, False, False, False]], dtype=bool)
最后,根据 "double border" 的含义,您可能会尝试使用比简单的单边差异更复杂的边缘过滤器。例如:
In [4]: import scipy.ndimage
In [5]: abs(scipy.ndimage.laplace(x)) > 0
Out[5]:
array([[False, False, True, True, False],
[False, True, True, True, False],
[ True, True, True, False, False]], dtype=bool)
所以我有一个 2D Numpy 数组,看起来像这样:
[[1,1,1,2,2],
[1,1,1,2,2],
[1,2,2,2,2]]
数组中的每个数字代表一个区域。我想生成一个布尔数组,在相邻元素不完全相等的位置上显示 True
,即在区域边界上。所以结果应该是这样的:
[[False, False, True, False],
...etc
我知道一个简单的双循环可以解决问题,但我需要更快的东西。
一般来说,您正在寻找边缘检测滤镜。
处理此问题的方法不止一种,但基本思想是将 [-1, 1]
或 [-1, 0, 1]
等简单过滤器与数据进行卷积。 scipy.ndimage
和 scikit-image 是开始的好地方。请记住,处理一般情况的方法不止一种。
但是,如果您想要最简单的情况,您可以使用基本的 numpy 操作:
import numpy as np
x = np.array([[1,1,1,2,2],
[1,1,1,2,2],
[1,2,2,2,2]])
edges = np.abs(np.diff(x, axis=1)) > 0
这产生:
array([[False, False, True, False],
[False, False, True, False],
[ True, False, False, False]], dtype=bool)
如果您希望输出与输入具有相同的形状,您有几个不同的选择。您可以用左侧或右侧边缘值填充输入数组:
# Pad the right-hand side with the edge values
# Use [(0, 0), (1, 0)] to pad the left instead.
xpad = np.pad(x, [(0, 0), (0, 1)], mode='edge')
edges = np.abs(np.diff(xpad, axis=1)) > 0
这会产生:
array([[False, False, True, False, False],
[False, False, True, False, False],
[ True, False, False, False, False]], dtype=bool)
在这种特定情况下,您可以使用 np.gradient
而不是填充数组。 gradient
将在边缘使用不同的算法以确保保持数组大小:
dy, dx = np.gradient(x)
edges = np.abs(dx) > 0
这会产生稍厚的边框,因为它使用的算法与简单地减去相邻元素略有不同:
array([[False, False, True, True, False],
[False, False, True, True, False],
[ True, True, False, False, False]], dtype=bool)
最后,根据 "double border" 的含义,您可能会尝试使用比简单的单边差异更复杂的边缘过滤器。例如:
In [4]: import scipy.ndimage
In [5]: abs(scipy.ndimage.laplace(x)) > 0
Out[5]:
array([[False, False, True, True, False],
[False, True, True, True, False],
[ True, True, True, False, False]], dtype=bool)