I need to get the values of all the neighbors around an element in a matrix in python. Suppose I have a matrix like below,
matrix=[[1,2,3,4],
[5,6,7,8],
[9,10,11,12]]
For the first element i.e., matrix[0][0]
, the neighbors are [2,5,6]
.
For matrix[0][1]
, the neighbors are [1,3,5,6,7]
.
For matrix[0][2]
, the neighbors are [2,4,6,7,8]
.
For a given element, i need to get these list of values.
I can do the same by comparing i,j values when i=0,j=0 get matrix[0][1], matrix[1][0], matrix[1][1] using switch case and so. But it will become lengthy code. Is there any inbuilt function or any module to make the above task even simpler?
If you don't care about efficiency, use scipy
:
import scipy, scipy.ndimage
def nb_vals(matrix, indices):
matrix = scipy.array(matrix)
indices = tuple(scipy.transpose(scipy.atleast_2d(indices)))
arr_shape = scipy.shape(matrix)
dist = scipy.ones(arr_shape)
dist[indices] = 0
dist = scipy.ndimage.distance_transform_cdt(dist, metric='chessboard')
nb_indices = scipy.transpose(scipy.nonzero(dist == 1))
return [matrix[tuple(ind)] for ind in nb_indices]
e.g.
>>> matrix=[[1,2,3,4],
... [5,6,7,8],
... [9,10,11,12]]
>>>
>>> nb_vals(matrix, [1,1])
[1,2,3,5,7,9,10,11]
This is dimension agnostic (works for an arbitrary number of dimensions for the input "matrix") and handles an arbitrary number of indices which you may wish to find neighbours around.
>>> arr_shape = (2,3,4,5)
>>> testMatrix = scipy.array(scipy.random.random(arr_shape)*10, dtype=int)
>>> print(testMatrix)
[[[[7 0 0 1 9]
[9 5 8 5 8]
[4 0 0 8 0]
[1 9 1 3 2]]
[[9 2 3 3 5]
[2 3 3 7 9]
[6 5 6 6 2]
[9 1 1 0 0]]
[[8 8 5 7 9]
[9 0 7 7 6]
[3 8 7 6 4]
[8 7 5 5 9]]]
[[[8 9 2 0 0]
[8 3 5 5 2]
[4 0 1 0 3]
[1 0 9 1 3]]
[[6 9 2 5 2]
[2 7 5 5 3]
[6 7 2 9 5]
[4 2 7 3 1]]
[[1 7 7 7 6]
[5 1 4 1 0]
[3 9 4 9 7]
[7 7 6 6 7]]]]
>>> nb_vals(testMatrix, [1,2,2,3])
[3, 7, 9, 6, 6, 2, 1, 0, 0, 7, 7, 6, 7, 6, 4, 5, 5, 9, 5, 5, 3, 2, 9, 5, 7, 3, 1, 4, 1, 0, 4, 7, 6, 6, 7]
This solution uses a chessboard-type chamfer transform on an image-like binary array mask, where 1
is equal to a white pixel on the mask and 0
is equal to a black pixel (background) to the mask. The chamfer transform calculates the chessboard distance of all white pixels to the background; all pixel locations with a distance calculated as 1 are the neighbours, and the values at these locations on the input array are returned.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With