2

I have a 2D numpy array of zeros representing some flat surface:

field = np.zeros((10,10))

field
Out[165]: 
array([[0., 0., 0., 0., 0., 0., 0., 0., 0., 0.],
       [0., 0., 0., 0., 0., 0., 0., 0., 0., 0.],
       [0., 0., 0., 0., 0., 0., 0., 0., 0., 0.],
       [0., 0., 0., 0., 0., 0., 0., 0., 0., 0.],
       [0., 0., 0., 0., 0., 0., 0., 0., 0., 0.],
       [0., 0., 0., 0., 0., 0., 0., 0., 0., 0.],
       [0., 0., 0., 0., 0., 0., 0., 0., 0., 0.],
       [0., 0., 0., 0., 0., 0., 0., 0., 0., 0.],
       [0., 0., 0., 0., 0., 0., 0., 0., 0., 0.],
       [0., 0., 0., 0., 0., 0., 0., 0., 0., 0.]])

Then I have an array of coordinates in the form [row,column] such as:

In [166]:c = np.array([[1,2],[4,5],[7,3],[2,6]])

In [167]:c
Out[167]: 
array([[1, 2],
       [4, 5],
       [7, 3],
       [2, 6]])

What I would like to do is populate a block of the field array around the coordinates in c.

Out[192]: 
array([[0., 1., 1., 1., 0., 0., 0., 0., 0., 0.],
       [0., 1., 1., 1., 0., 1., 1., 1., 0., 0.],
       [0., 1., 1., 1., 0., 1., 1., 1., 0., 0.],
       [0., 0., 0., 0., 1., 1., 1., 1., 0., 0.],
       [0., 0., 0., 0., 1., 1., 1., 0., 0., 0.],
       [0., 0., 0., 0., 1., 1., 1., 0., 0., 0.],
       [0., 0., 1., 1., 1., 0., 0., 0., 0., 0.],
       [0., 0., 1., 1., 1., 0., 0., 0., 0., 0.],
       [0., 0., 1., 1., 1., 0., 0., 0., 0., 0.],
       [0., 0., 0., 0., 0., 0., 0., 0., 0., 0.]])

My initial attempt using numpy vectorization was:

In [168]:field[c[:,0]-1:c[:,0]+1,c[:,1]-1:c[:,1]+1] = 10
Traceback (most recent call last):

  File "<ipython-input-168-5433a2f4a5cf>", line 1, in <module>
    field[c[:,0]-1:c[:,0]+1,c[:,1]-1:c[:,1]+1] = 10

TypeError: only integer scalar arrays can be converted to a scalar index

I then tried first creating the c[:,0]-1 and c[:,1]+1 arrays before hand but got the same error which leads me to the conclusion that, that type of ranged indexing cannot be done in numpy.

I have also had a look at the np.ix_() but cannot set surrounding blocks of multiple coordinates without a for loop using this method.

I am able to achieve the desired output however using the for loop:

for row,column in c:
        field[row-1:row+2,column-1:column+2] = 1

But would not like to use a for loop because both c and f will be large and multidimensional in my final application and I feel I can capitalize on the speed improvements made by numpy vectorization.

Also, I know in image processing this could be seen as a dilation or erosion problem but I already have the coordinates for an erosion/dilation kernel to be placed at and again, multiple dimensions and very large arrays.

1
  • Very well written question! Commented Feb 19, 2020 at 14:08

1 Answer 1

2

Here's a simple way which only has a small amount of Python looping and a lot of vectorized work:

x, y = c[:,0], c[:,1]
for i in -1,0,1:
    for j in -1,0,1:
        field[x+i,y+j] = 1

A more complicated way which may be faster:

offsets = np.array([[-1,-1],[-1,0],[-1,1], [0,-1],[0,0],[0,1], [1,-1],[1,0],[1,1]])
fill = (offsets + c[:,None]).reshape(-1,2)
field[fill[:,0], fill[:,1]] = 1
Sign up to request clarification or add additional context in comments.

4 Comments

small and constant, which I think is the important bit here.
doesn't it gives unexpected result when the x+i or y+j become negative index
@ShubhamShaswat: There are no out-of-bounds values in OP's c, but if there are you can just create field one larger in each direction and discard the outermost cells afterward. Or try clipping before indexing.
Thanks @JohnZwinck for the quick response. Timing my basic for loop and then your two answers I get: 0.009973526000976562s, 0.006982088088989258s and 0.0059812068939208984 respectively. **Note I timed these on a larger field with far more coordinates so that it would register wall clock time using time.time().

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.