Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to get all the values of neighbours around an element in matrix?

Tags:

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?

like image 444
Ssukumar Avatar asked Mar 10 '18 15:03

Ssukumar


1 Answers

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.

like image 73
dROOOze Avatar answered Sep 21 '22 12:09

dROOOze