简体   繁体   中英

NumPy: fill fields surrounding a 1 in an array

Suppose I have a 4x4 matrix that looks like the following:

[[0, 0, 0, 0]
 [0, 0, 1, 0]
 [0, 0, 0, 0]
 [0, 0, 0, 0]]

I want to write a function that takes all 4 surrounding fields of the one and turns them into a 1 as well.

The above matrix would become:

[[0, 0, 1, 0]
 [0, 1, 1, 1]
 [0, 0, 1, 0]
 [0, 0, 0, 0]]

I know that this is possible using if-statements, but I really want to optimize my code.

The matrix only contains 0's and 1's. If the 1 is at the edge of the matrix, the 1's should not wrap around, ie if the most left field is a 1, the most right field still stays at 0. Also, I am using Python 3.5

Is there a more mathematical or concise way to do this?

This looks like binary dilation. There's a function available in SciPy that implements this efficiently:

>>> from scipy.ndimage import binary_dilation
>>> x
array([[0, 0, 0, 0],
       [0, 0, 1, 0],
       [0, 0, 0, 0],
       [0, 0, 0, 0]])

>>> binary_dilation(x).astype(int)
array([[0, 0, 1, 0],
       [0, 1, 1, 1],
       [0, 0, 1, 0],
       [0, 0, 0, 0]])

1s at the edges are handled as you've specified they should be (ie no wrapping).

See the documentation for further options and arguments.

FWIW, here's a way to do it just using Numpy. We pad the original data with rows & columns of zeros, and then bitwise-OR offset copies of the padded array together.

import numpy as np

def fill(data):
    rows, cols = data.shape
    padded = np.pad(data, 1, 'constant', constant_values=0)
    result = np.copy(data)
    for r, c in ((0, 1), (1, 0), (1, 2), (2, 1)):
        result |= padded[r:r+rows, c:c+cols]
    return result

data = np.asarray(
    [
        [0, 0, 0, 0],
        [0, 0, 1, 0],
        [0, 0, 0, 0],
        [0, 0, 0, 0],
    ], dtype='uint8')
print(data, '\n')

result = fill(data)
print(result)

output

[[0 0 0 0]
 [0 0 1 0]
 [0 0 0 0]
 [0 0 0 0]] 

[[0 0 1 0]
 [0 1 1 1]
 [0 0 1 0]
 [0 0 0 0]]

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.

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