Python 相交多个2D np阵列以确定空间上相邻的区域

Python 相交多个2D np阵列以确定空间上相邻的区域,python,numpy,multidimensional-array,Python,Numpy,Multidimensional Array,这一问题的背景与以下方面有关。选择的答案提供了一个很好的解决方案。然而,我想补充一点,还有一个细微差别 这些数组没有使用上面给出的数组,而是突出显示了一个条件,即前面的一组解决方案不能以我希望的方式处理。新阵列包括: import numpy as np asp = np.array([2,1,8,2,5,4,6,4,3,3,3,3,2,1,8,2]).reshape((4,4)) #aspect slp = np.array([11,11,12,11,12,11,12,10,9,9,9,1

这一问题的背景与以下方面有关。选择的答案提供了一个很好的解决方案。然而,我想补充一点,还有一个细微差别

这些数组没有使用上面给出的数组,而是突出显示了一个条件,即前面的一组解决方案不能以我希望的方式处理。新阵列包括:

import numpy as np

asp = np.array([2,1,8,2,5,4,6,4,3,3,3,3,2,1,8,2]).reshape((4,4))  #aspect
slp = np.array([11,11,12,11,12,11,12,10,9,9,9,10,11,10,11,11]).reshape((4,4))  #slope
elv = np.array([16,15,15,16,17,15,15,15,15,15,14,14,16,15,16,16]).reshape((4,4)) #elevation
以前的解决方案在高程、坡度和坡向相同的地方指定了唯一的分区编号,而不管唯一分区在空间上是否相邻。下图试图显示此结果(请参见左下角2个数组中的上半部分)。所需的结果类似于图像左下角的下部阵列。例如,请注意,每个角单元都具有相同的高程、坡度和坡向,但在空间上不连续,因此应为其指定唯一的分区ID。“空间连续”定义为具有相同高程、坡度和坡向的2个(或更多)相邻(相邻或对角)单元。下图中以红色突出显示的单元格描述了这一点

在以前的解决方案中,没有考虑到结果区域的空间连续性,对我来说最有意义的是@Stephen Rauch。他的解决方案是(除其他外):


计算区域后,可以对区域进行泛洪填充。我最初的想法是在唯一性计算之后执行此操作,但考虑到您只对连续性感兴趣,请使用原始数据并完全跳过第一个分区步骤。以下实现不是超级高效的。我相信可以采取一些措施来优化它:

from collections import deque
import numpy as np

asp = np.array([[ 2, 1, 8, 2],
                [ 5, 4, 6, 4],
                [ 3, 3, 3, 3],
                [ 2, 1, 8, 2]])  #aspect
slp = np.array([[11,11,12,11],
                [12,11,12,10],
                [ 9, 9, 9,10],
                [11,10,11,11]])  #slope
elv = np.array([[16,15,15,16],
                [17,15,15,15],
                [15,15,14,14],
                [16,15,16,16]]) #elevation

criteria = np.stack((asp, slp, elv))

def floodfill(n, start):
    def check(r, c):
        return result[r, c] == 0 and np.array_equal(crit, criteria[:, r, c])

    stack = deque([start])
    crit = criteria [(slice(None), *start)]
    while stack:
        r, c = stack.popleft()
        if result[r, c]: continue
        result[r, c] = n
        if r > 0 and check(r - 1, c):
            stack.append((r - 1, c))
        if r < result.shape[0] - 1 and check(r + 1, c):
            stack.append((r + 1, c))
        if c > 0 and check(r, c - 1):
            stack.append((r, c - 1))
        if c < result.shape[1] - 1 and check(r, c + 1):
            stack.append((r, c + 1))


result = np.zeros_like(asp)
count = 1
it = np.nditer(result, flags=['multi_index'])
for x in it:
    if x == 0:
        floodfill(count, it.multi_index)
        count += 1

print(result)

你可以按顺序填充各个区域。谷歌搜索“floodfill numpy”让我找到了(),这让我又向前迈进了一步。谢谢你的术语提示@MadPhysicast
from collections import deque
import numpy as np

asp = np.array([[ 2, 1, 8, 2],
                [ 5, 4, 6, 4],
                [ 3, 3, 3, 3],
                [ 2, 1, 8, 2]])  #aspect
slp = np.array([[11,11,12,11],
                [12,11,12,10],
                [ 9, 9, 9,10],
                [11,10,11,11]])  #slope
elv = np.array([[16,15,15,16],
                [17,15,15,15],
                [15,15,14,14],
                [16,15,16,16]]) #elevation

criteria = np.stack((asp, slp, elv))

def floodfill(n, start):
    def check(r, c):
        return result[r, c] == 0 and np.array_equal(crit, criteria[:, r, c])

    stack = deque([start])
    crit = criteria [(slice(None), *start)]
    while stack:
        r, c = stack.popleft()
        if result[r, c]: continue
        result[r, c] = n
        if r > 0 and check(r - 1, c):
            stack.append((r - 1, c))
        if r < result.shape[0] - 1 and check(r + 1, c):
            stack.append((r + 1, c))
        if c > 0 and check(r, c - 1):
            stack.append((r, c - 1))
        if c < result.shape[1] - 1 and check(r, c + 1):
            stack.append((r, c + 1))


result = np.zeros_like(asp)
count = 1
it = np.nditer(result, flags=['multi_index'])
for x in it:
    if x == 0:
        floodfill(count, it.multi_index)
        count += 1

print(result)
[[ 1  2  3  4]
 [ 5  6  7  8]
 [ 9  9 10 11]
 [12 13 14 15]]