2

I want to recover a "buffer" around a given value in a 2-D numpy array in python. The idea is to select all the values comprised within a given radius and then mask them. It would be something like:

  1. select a "cell" in the matrix, like matrix[x, y]
  2. get the cells comprised in the neighborhood, where the distance from x, y is less than the radius r

I would like to implement a fast function for doing so, since I have a big array for processing (shape is 7000 x 10000).

msw
  • 42,753
  • 9
  • 87
  • 112
Guadancil11
  • 625
  • 3
  • 8
  • 16

1 Answers1

3

numpy slicing does this for you out of the box, and it is very fast:

x
Out[38]: 
array([[1, 2, 3, 4],
       [1, 2, 3, 4],
       [1, 2, 3, 4],
       [1, 2, 3, 4]])

x[0:3,0:3] #neighbors distance=1 from (1,1)
Out[39]: 
array([[1, 2, 3],
       [1, 2, 3],
       [1, 2, 3]])

If you want to generalize this, write a wrapper:

def n_closest(x,n,d=1):
    return x[n[0]-d:n[0]+d+1,n[1]-d:n[1]+d+1]

demo:

y = np.diag(np.ones(10))

n_closest(y,(1,3))
Out[67]: 
array([[ 0.,  0.,  0.],
       [ 0.,  0.,  0.],
       [ 1.,  0.,  0.]])

n_closest(y,(2,3),d=2)
Out[69]: 
array([[ 0.,  0.,  0.,  0.,  0.],
       [ 1.,  0.,  0.,  0.,  0.],
       [ 0.,  1.,  0.,  0.,  0.],
       [ 0.,  0.,  1.,  0.,  0.],
       [ 0.,  0.,  0.,  1.,  0.]])

This is a basic 'square' mask, if you need a different shaped one it is easy to make one. It's unclear if that's what you wanted.

roippi
  • 25,533
  • 4
  • 48
  • 73
  • 2
    This is correct only if you assume he meant the distance to be the L-infinity norm. – Bitwise Aug 09 '13 at 18:35
  • Thanks, that seems to work. I'm trying to figure out how to make a disc shape. – Guadancil11 Aug 09 '13 at 18:47
  • @Guadancil11 then yes you are looking for http://stackoverflow.com/questions/8647024/how-to-apply-a-disc-shaped-mask-to-a-numpy-array. The same strategy applies, you are just slicing using `np.ogrid`. – roippi Aug 09 '13 at 18:52
  • I guess I'm missing the point. I make: >>> ax,ay=ogrid[x-d:x+d+1,y-d:y+d+1] >>> mask = ax*ax + ay*ay <= d*d And the mask is all 'False' – Guadancil11 Aug 09 '13 at 19:04
  • Actually it is quite different... In your answer you are creating a view of the original data. In the other case, you are creating a boolean mask that can be used to access a flattened copy of the original data. – Jaime Aug 09 '13 at 19:36
  • I see the error, @Jaime. It was a newbie error. Now it works great, thank you all. – Guadancil11 Aug 09 '13 at 20:58