简体   繁体   English

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

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

I'm working on a particle system simulation in which many thousands of particles randomly walk until they attach to a growing cluster.我正在研究一个粒子系统模拟,其中成千上万的粒子随机游走,直到它们附着到一个不断增长的集群上。 To visualize this cluster, I'm storing the cluster particle positions as 1s in a numpy array initially full of 0s and then using the matshow function.为了可视化这个集群,我将集群粒子位置作为 1 存储在 numpy 数组中,该数组最初充满 0,然后使用matshow function。 The 0s are colored white and the 1s are colored black. 0 为白色,1 为黑色。

I've noticed in these simulations that a situation like the following might occur (the actual arrays are much larger, 1000x1000 or larger):我注意到在这些模拟中可能会发生以下情况(实际的 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.]])

where particles (1s) attach in a such a way so that a "pocket" (of 0s) is formed.其中粒子(1s)以这样的方式附着,从而形成一个“口袋”(0s)。 In the images of these clusters they appear as tiny holes.在这些星团的图像中,它们显示为小孔。 Here's what this looks like for a smaller cluster:这是较小集群的样子:

在此处输入图像描述

If you squint, you can see a handful of the "holes" I'm talking about.如果你眯着眼睛,你可以看到我所说的一些“洞”。 These correspond to 0s completely surrounded by 1s in the associated numpy array.这些对应于在相关的 numpy 阵列中完全被 1 包围的 0。

My question: How can I write a function that will:我的问题:我怎样才能写一个 function :

  1. Count the number of 0s that are completely surrounded by 1s计算完全被 1 包围的 0 的数量
  2. Change the 0s that are completely surrounded by 1s into -1s (I have a reason for wanting them to be -1s instead)将完全被 1 包围的 0 更改为 -1(我有理由希望它们改为 -1)

My first pass at writing such a function works for small/simple arrays like the example above, but fails to work for the actual cluster arrays in the simulation:我第一次编写这样的 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

I recognize this function will fail to do what I want it to do for situations like this, where a "cleft" occurs:我认识到这个 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.]])

Calling my attempt on this would give:调用我的尝试将给出:

    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.]])

which is incorrect, since this configuration does not actually have a pocket of 0s.这是不正确的,因为这个配置实际上并没有一个 0 的口袋。

How can I do this correctly, and perhaps efficiently?我怎样才能正确地并且可能有效地做到这一点? Like I said, the simulation is running on arrays at least of size 1000x1000.就像我说的,模拟在 arrays 上运行,至少大小为 1000x1000。

You can use the Flood Fill algorithm.您可以使用洪水填充算法。
This algorithm is working like the "Fill" feature in paint and finding all the pixels with the same color in an image.该算法的工作原理类似于绘画中的“填充”功能,并在图像中查找具有相同颜色的所有像素。 Use it to replace all the outside zeros with -1, than replace all remaining zeros with 1, than turn all the -1 to zeros.使用它用 -1 替换所有外部零,而不是用 1 替换所有剩余的零,而不是将所有 -1 变为零。

Building on this answer with an implementation to flood fill, your algorithm will be something like:这个答案为基础,实现洪水填充,您的算法将类似于:

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