Python 获取二维数组中相邻区域的边界路径

Python 获取二维数组中相邻区域的边界路径,python,numpy,multidimensional-array,ndimage,Python,Numpy,Multidimensional Array,Ndimage,假设我有这样一个数组: 将numpy导入为np arr=np.array([ [1, 1, 3, 3, 1], [1, 3, 3, 1, 1], [4, 4, 3, 1, 1], [4, 4, 1, 1, 1] ]) 有4个不同的区域:左上1s、3s、4s和右1s 如何获得每个区域边界的路径?区域顶点的坐标,按顺序排列 例如,对于左上角的1,它是(0,0)、(0,2)、(1,2)、(1,1)、(2,1)、(2,0) (我最终希望得到类似于从0开始,0.Right 2.Down 1.Right-

假设我有这样一个数组:

将numpy导入为np
arr=np.array([
[1, 1, 3, 3, 1],
[1, 3, 3, 1, 1],
[4, 4, 3, 1, 1],
[4, 4, 1, 1, 1]
])
有4个不同的区域:左上1s、3s、4s和右1s

如何获得每个区域边界的路径?区域顶点的坐标,按顺序排列

例如,对于左上角的1,它是
(0,0)、(0,2)、(1,2)、(1,1)、(2,1)、(2,0)

(我最终希望得到类似于
从0开始,0.Right 2.Down 1.Right-1.Down 1.Right-1.Down-2.
,但它很容易转换,因为它只是相邻顶点之间的差异)

我可以使用
scipy.ndimage.label
将其拆分为多个区域:

来自scipy.ndimage导入标签
区域={}
#region_值是区域中的数字
对于np.unique(arr)中的区域_值:
已标记,n_区域=标签(arr==区域值)
区域[区域\u值]=[标记==范围(1,n\u区域+1)中的i的i]
看起来更像这样:

{1:[
排列([
[真,真,假,假,假],
[真,假,假,假,假],
[假,假,假,假,假],
[假,假,假,假,假]
],dtype=bool),#左上1s区域
排列([
[假,假,假,假,真],
[假,假,假,真,真],
[假,假,假,真,真],
[假,假,真,真,真]
],dtype=bool)#右1s区域
],
3: [
排列([
[假,假,真,真,假],
[假,真,真,假,假],
[假,假,真,假,假],
[假,假,假,假,假]
],dtype=bool)#3s区域
],
4: [
排列([
[假,假,假,假,假],
[假,假,假,假,假],
[真,真,假,假,假],
[真,真,假,假,假]
],dtype=bool)#4s区域
]
}

那么我如何将其转换为路径呢?

伪代码的想法是执行以下操作:

scan multi-dim array horizontally and then vertically until you find True value (for second array it is (0,4))
output that as a start coord
since you have been scanning as determined above your first move will be to go right.
repeat until you come back:
    move one block in the direction you are facing.
    you are now at coord x,y
    check values of ul=(x-1, y-1), ur=(x-1, y), ll=(x, y-1), lr=(x,y)
    # if any of above is out of bounds, set it as False
    if ul is the only True:
         if previous move right:
             next move is up
         else:
             next move is left
         output previous move
         move by one
   ..similarly for other single True cells..
   elif ul and ur only True or ul and ll only True or ll and lr only True or ur and lr only True:
        repeat previous move
   elif ul and lr only True:
        if previous move left:
            next move down
        elif previous move right:
            next move up
        elif preivous move down:
            next move left:
        else:
            next move right
        output previous move
        move one
   elif ul, ur, ll only Trues:
        if previous move left:
            next move down
        else:
            next move right
        output previous move, move by one
   ...similarly for other 3 True combos...
finds True val at 0,4
start at 0,4
only lower-right cell is True, so moves right to 0,5 (previous move is None, so no output)
now only lower-left cell is True, so moves down to 1,5 (previous move right 1 is output)
now both left cells are True, so repeat move (moves down to 2,5)
..repeat until hit 4,5..
only upper-left cell is True, so move left (output down 4)
both upper cells are true, repeat move (move left to 3,4)
both upper cells are true, repeat move (move left to 2,4)
upper right cell only true, so move up (output right -3)
..keep going until back at 0,4..
对于第二个阵列,它将执行以下操作:

scan multi-dim array horizontally and then vertically until you find True value (for second array it is (0,4))
output that as a start coord
since you have been scanning as determined above your first move will be to go right.
repeat until you come back:
    move one block in the direction you are facing.
    you are now at coord x,y
    check values of ul=(x-1, y-1), ur=(x-1, y), ll=(x, y-1), lr=(x,y)
    # if any of above is out of bounds, set it as False
    if ul is the only True:
         if previous move right:
             next move is up
         else:
             next move is left
         output previous move
         move by one
   ..similarly for other single True cells..
   elif ul and ur only True or ul and ll only True or ll and lr only True or ur and lr only True:
        repeat previous move
   elif ul and lr only True:
        if previous move left:
            next move down
        elif previous move right:
            next move up
        elif preivous move down:
            next move left:
        else:
            next move right
        output previous move
        move one
   elif ul, ur, ll only Trues:
        if previous move left:
            next move down
        else:
            next move right
        output previous move, move by one
   ...similarly for other 3 True combos...
finds True val at 0,4
start at 0,4
only lower-right cell is True, so moves right to 0,5 (previous move is None, so no output)
now only lower-left cell is True, so moves down to 1,5 (previous move right 1 is output)
now both left cells are True, so repeat move (moves down to 2,5)
..repeat until hit 4,5..
only upper-left cell is True, so move left (output down 4)
both upper cells are true, repeat move (move left to 3,4)
both upper cells are true, repeat move (move left to 2,4)
upper right cell only true, so move up (output right -3)
..keep going until back at 0,4..
尝试可视化所有可能的coord相邻单元组合,这将使您对可能的流有一个直观的想法。
还要注意的是,使用这种方法应该不可能遍历所有4个邻居都为False的坐标。

只是一个随机想法。使用现有等高线代码: