3kt
3kt

Reputation: 2553

Numpy array value "contamination"

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

Answers (2)

Warren Weckesser
Warren Weckesser

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

Divakar
Divakar

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

Related Questions