Reputation: 2553
I have a 2D numpy array filled with 0 and 1, and I would like to transform it so that every value neighboring a 1 is transformed to a 1 (hence the "contamination" in the title).
For example :
0 0 0 0 0 0
0 0 0 0 0 0
0 0 0 1 0 0
0 0 0 0 1 0
0 0 1 0 0 0
0 0 0 0 0 0
Becomes :
0 0 0 0 0 0
0 0 1 1 1 0
0 0 1 1 1 1
0 1 1 1 1 1
0 1 1 1 1 1
0 1 1 1 0 0
I can achieve this by looping through all the values, finding the 1s, and then replacing the adjacent values :
import numpy as np
ones = []
ar = np.array([[0,0,0,0,0,0],
[0,0,0,0,0,0],
[0,0,0,1,0,0],
[0,0,0,0,1,0],
[0,0,1,0,0,0],
[0,0,0,0,0,0]])
n_row, n_col = ar.shape
for i in range(n_row):
for j in range(n_col):
if ar[i][j] == 1:
ones.append((i, j))
for x,y in ones:
# Replace neighboring values
But this seems overkill (especially because I'm planning to deal with really large arrays).
Is there a way to achieve this without having to loop through all the values ?
Upvotes: 1
Views: 249
Reputation: 114921
The operation that you described is known as "binary dilation". There is an implementation in scipy.ndimage
. For example,
In [369]: a
Out[369]:
array([[0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0],
[0, 0, 0, 1, 0, 0],
[0, 0, 0, 0, 1, 0],
[0, 0, 1, 0, 0, 0],
[0, 0, 0, 0, 0, 0]])
In [370]: from scipy.ndimage import binary_dilation
In [371]: binary_dilation(a, structure=np.ones((3, 3)))
Out[371]:
array([[False, False, False, False, False, False],
[False, False, True, True, True, False],
[False, False, True, True, True, True],
[False, True, True, True, True, True],
[False, True, True, True, True, True],
[False, True, True, True, False, False]], dtype=bool)
In [372]: binary_dilation(a, structure=np.ones((3, 3))).astype(int)
Out[372]:
array([[0, 0, 0, 0, 0, 0],
[0, 0, 1, 1, 1, 0],
[0, 0, 1, 1, 1, 1],
[0, 1, 1, 1, 1, 1],
[0, 1, 1, 1, 1, 1],
[0, 1, 1, 1, 0, 0]])
Upvotes: 0
Reputation: 221664
That's basically dilation operation in Image-processing domain
. So, you can use Scipy's binary dilation
-
from scipy.ndimage import binary_dilation
out = binary_dilation(arr, structure=np.ones((3,3))).astype(int)
Sample run -
In [21]: arr
Out[21]:
array([[0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0],
[0, 0, 0, 1, 0, 0],
[0, 0, 0, 0, 1, 0],
[0, 0, 1, 0, 0, 0],
[0, 0, 0, 0, 0, 0]])
In [22]: binary_dilation(arr, structure=np.ones((3,3))).astype(int)
Out[22]:
array([[0, 0, 0, 0, 0, 0],
[0, 0, 1, 1, 1, 0],
[0, 0, 1, 1, 1, 1],
[0, 1, 1, 1, 1, 1],
[0, 1, 1, 1, 1, 1],
[0, 1, 1, 1, 0, 0]])
Upvotes: 2