繁体   English   中英

计算和更改被 1 包围的矩阵中的 0 - Python

[英]Counting and changing the 0s in a matrix that are surrounded by 1s - Python

我正在研究一个粒子系统模拟,其中成千上万的粒子随机游走,直到它们附着到一个不断增长的集群上。 为了可视化这个集群,我将集群粒子位置作为 1 存储在 numpy 数组中,该数组最初充满 0,然后使用matshow function。 0 为白色,1 为黑色。

我注意到在这些模拟中可能会发生以下情况(实际的 arrays 要大得多,1000x1000 或更大):

array([[0., 0., 0., 0., 0., 0., 0., 0., 0., 0.],
       [0., 0., 0., 0., 0., 0., 0., 0., 0., 0.],
       [0., 0., 0., 1., 1., 1., 1., 0., 0., 0.],
       [0., 0., 1., 1., 1., 1., 1., 1., 0., 0.],
       [0., 0., 1., 1., 0., 0., 1., 1., 0., 0.],
       [0., 0., 1., 1., 0., 0., 1., 1., 0., 0.],
       [0., 0., 1., 1., 1., 1., 1., 1., 0., 0.],
       [0., 0., 0., 1., 1., 1., 1., 0., 0., 0.],
       [0., 0., 0., 0., 0., 0., 0., 0., 0., 0.],
       [0., 0., 0., 0., 0., 0., 0., 0., 0., 0.]])

其中粒子(1s)以这样的方式附着,从而形成一个“口袋”(0s)。 在这些星团的图像中,它们显示为小孔。 这是较小集群的样子:

在此处输入图像描述

如果你眯着眼睛,你可以看到我所说的一些“洞”。 这些对应于在相关的 numpy 阵列中完全被 1 包围的 0。

我的问题:我怎样才能写一个 function :

  1. 计算完全被 1 包围的 0 的数量
  2. 将完全被 1 包围的 0 更改为 -1(我有理由希望它们改为 -1)

我第一次编写这样的 function 适用于小型/简单 arrays ,如上面的示例,但无法在模拟中适用于实际集群 arrays:

def holes(matrix):
    num_holes = 0
    for row in range(matrix.shape[0]):
        for col in range(matrix.shape[0]):
            if matrix[row, col] == 0: 
                can_escape = True
                
                path_down = matrix[row, col:]
                path_up = np.flip(matrix[:row+1, col])
                path_right = matrix[row:, col]
                path_left = np.flip(matrix[row, :col+1])
                
                if 1 in path_down[1:] and 1 in path_up[1:] and 1 in path_left[1:] and 1 in path_right[1:]:
                    can_escape = False
                
                if can_escape is False: 
                    matrix[row, col] = -1
                    num_holes += 1
                    
    return num_holes

我认识到这个 function 将无法在这种情况下执行我希望它执行的操作,即发生“裂缝”:

    array([[0., 0., 0., 0., 0., 0., 0., 0., 0., 0.],
           [0., 0., 0., 0., 0., 0., 0., 0., 0., 0.],
           [0., 0., 0., 0., 0., 0., 0., 0., 0., 0.],
           [0., 0., 1., 0., 1., 1., 1., 1., 0., 0.],
           [0., 0., 1., 0., 0., 0., 1., 1., 0., 0.],
           [0., 0., 1., 0., 0., 0., 1., 1., 0., 0.],
           [0., 0., 1., 0., 1., 1., 1., 1., 0., 0.],
           [0., 0., 0., 1., 1., 1., 1., 0., 0., 0.],
           [0., 0., 0., 0., 0., 0., 0., 0., 0., 0.],
           [0., 0., 0., 0., 0., 0., 0., 0., 0., 0.]])

调用我的尝试将给出:

    array([[0., 0., 0., 0., 0., 0., 0., 0., 0., 0.],
           [0., 0., 0., 0., 0., 0., 0., 0., 0., 0.],
           [0., 0., 0., 0., 0., 0., 0., 0., 0., 0.],
           [0., 0., 1., 0., 1., 1., 1., 1., 0., 0.],
           [0., 0., 1., 0., -1., -1., 1., 1., 0., 0.],
           [0., 0., 1., 0., -1., -1., 1., 1., 0., 0.],
           [0., 0., 1., 0., 1., 1., 1., 1., 0., 0.],
           [0., 0., 0., 1., 1., 1., 1., 0., 0., 0.],
           [0., 0., 0., 0., 0., 0., 0., 0., 0., 0.],
           [0., 0., 0., 0., 0., 0., 0., 0., 0., 0.]])

这是不正确的,因为这个配置实际上并没有一个 0 的口袋。

我怎样才能正确地并且可能有效地做到这一点? 就像我说的,模拟在 arrays 上运行,至少大小为 1000x1000。

您可以使用洪水填充算法。
该算法的工作原理类似于绘画中的“填充”功能,并在图像中查找具有相同颜色的所有像素。 使用它用 -1 替换所有外部零,而不是用 1 替换所有剩余的零,而不是将所有 -1 变为零。

这个答案为基础,实现洪水填充,您的算法将类似于:

def floodfill(matrix, x, y, original_value, new_value):
    if matrix[x][y] == original_value:  
        matrix[x][y] = new_value
        #recursively invoke flood fill on all surrounding cells:
        if x > 0:
            floodfill(matrix,x-1,y)
        if x < len(matrix[y]) - 1:
            floodfill(matrix,x+1,y)
        if y > 0:
            floodfill(matrix,x,y-1)
        if y < len(matrix) - 1:
            floodfill(matrix,x,y+1)

def main():
    # Assuming 0, 0 has 0 in it - turning all the outside zeros to -1
    floodfill(matrix, 0, 0, 0, -1)

    for i in range(len(matrix)):
        for j in range(len(matrix[i])):
            if matrix[i][j] == -1:
                matrix[i][j] = 0
            if matrix[i][j] == 0:
                matrix[i][j] = 1

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM