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. The 0s are colored white and the 1s are colored black.
I've noticed in these simulations that a situation like the following might occur (the actual arrays are much larger, 1000x1000 or larger):
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. 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.
My question: How can I write a function that will:
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:
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:
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.
How can I do this correctly, and perhaps efficiently? Like I said, the simulation is running on arrays at least of size 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.
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
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.