我有一个带有一组唯一ID补丁/区域的栅格,我已将其转换为二维Python numpy数组。我想计算所有区域之间的成对欧几里德距离,以获得分隔每个光栅补丁的最近边缘的最小距离。由于阵列最初是光栅,因此解决方案需要考虑跨越单元的对角线距离(我总是可以通过乘以光栅分辨率将单元格中测量的任何距离转换回米)。
我已根据this answer to a related question中的建议尝试了来自cdist
的{{1}}功能,但到目前为止,我还是无法使用可用的文档解决我的问题。作为最终结果,理想情况下,我将以"从ID,ID,距离"的形式具有3×X阵列,包括所有可能的区域组合之间的距离。
这是一个类似于我输入数据的样本数据集:
scipy.spatial.distance
答案 0 :(得分:2)
可以使用以下代码
计算图像标记区域之间的距离import itertools
from scipy.spatial.distance import cdist
# making sure that IDs are integer
example_array = np.asarray(example_array, dtype=np.int)
# we assume that IDs start from 1, so we have n-1 unique IDs between 1 and n
n = example_array.max()
indexes = []
for k in range(1, n):
tmp = np.nonzero(example_array == k)
tmp = np.asarray(tmp).T
indexes.append(tmp)
# calculating the distance matrix
distance_matrix = np.zeros((n-1, n-1), dtype=np.float)
for i, j in itertools.combinations(range(n-1), 2):
# use squared Euclidean distance (more efficient), and take the square root only of the single element we are interested in.
d2 = cdist(indexes[i], indexes[j], metric='sqeuclidean')
distance_matrix[i, j] = distance_matrix[j, i] = d2.min()**0.5
# mapping the distance matrix to labeled IDs (could be improved/extended)
labels_i, labels_j = np.meshgrid( range(1, n), range(1, n))
results = np.dstack((labels_i, labels_j, distance_matrix)).reshape((-1, 3))
print(distance_matrix)
print(results)
这假定为整数ID,如果不是这样,则需要扩展。例如,对于上面的测试数据,计算的距离矩阵是
# From 1 2 3 4 5 # To
[[ 0. 4.12310563 4. 9.05538514 5. ] # 1
[ 4.12310563 0. 3.16227766 10.81665383 8.24621125] # 2
[ 4. 3.16227766 0. 4.24264069 2. ] # 3
[ 9.05538514 10.81665383 4.24264069 0. 3.16227766] # 4
[ 5. 8.24621125 2. 3.16227766 0. ]] # 5
虽然可以找到完整输出here。请注意,这需要距离每个像素中心的Eucledian距离。例如,区域1和3之间的距离是2.0,而它们被1个像素分开。
这是一种蛮力方法,我们计算不同区域像素之间的所有成对距离。这应该足以满足大多数应用。尽管如此,如果您需要更好的性能,请查看scipy.spatial.cKDTree
,与cdist
相比,它可以更有效地计算两个区域之间的最小距离。