3

I'm trying to fill a numpy array with a list of all of the x-coordinates of a pixel-based image. So basically, an n x m image would have n 1's, n 2's, and so on up to n m's. Is there a simple way to fill a numpy array so that this is the case?

So far, I've thought about using numpy.concatenate, but that seems awfully tedious to have to come up with each array individually, and I'd be using a loop anyway, which wouldn't really help. numpy.flatten also comes to find, but I'd have to generate the grid first. Are there any simple solutions?

2 Answers 2

4

There is always the usual grid creation function mgrid():

x_coords = numpy.mgrid[:m, :n][0]+1  # [[1, 1, 1…], [2, 2, 2,…]]. Element 1 is instead: [[1, 2, 3,…], [1, 2, 3,…]]

(PS: DSM's numpy.indices(image.shape) is simpler if m and n are the dimensions of image.)

If float coordinates are needed, then the more general "complex step" form gives them in an efficient way

numpy.mgrid[:m:(m+1)*1j, :n:(n+1)*1j]  # m+1 values from 0 to m, n+1 values from 0 to n

(another option would be to add the float 1. to the first form, but this would unnecessarily first create an array of integers).

If you only need one coordinate, this is a bit wasteful, though, as mgrid[] also creates a similar grid for the other coordinate (mgrid[] has two elements, here).

In some circumstances, it may be more efficient to use the low memory footprint numpy.ogrid[], which creates in this case a row and a column that are automatically broadcast so as to cover a 2-dimensional grid. The fact that they only use little memory can also speed things up (fewer memory accesses).

Sign up to request clarification or add additional context in comments.

9 Comments

Thanks! I actually need the y-coordinates too, I just thought it would be the same for both axes!
I might use np.indices(image_obj.shape) instead. (BTW, are you sure about the syntax? Isn't mgrid one of the square-bracketed ones?)
np.indices sounds good for what I asked, but I also need to be able to have floats as coordinates. And yeah, mgrid is one of the square bracketed ones (docs.scipy.org/doc/numpy/reference/generated/numpy.mgrid.html)
@Imagine: Since "you also need to be able to have floats as coordinates", I added an efficient way of handling this case.
@Imagine Yes there is a simple way to 'multipy' an array like you would with a list; it uses np.repeat and/or np.tile and it's the solution I gave in my answer.
|
4

If your image.shape is (n, m) then the x coords would be:

np.repeat(np.arange(m), n)

For example:

In [5]: n, m = 4, 3

In [6]: np.repeat(np.arange(m), n)
Out[6]: array([0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2])

Of course, the y-coords would be

np.repeat(np.arange(n), m)

You might want to use np.tile instead for the second coordinate:

np.tile(np.arange(n), m)

Then, you'd be able to zip it and have the coords for all pixels:

In [9]: np.repeat(np.arange(m), n)
Out[9]: array([0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2])

In [10]: np.tile(np.arange(n), m)
Out[10]: array([0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3])

Note that this is basically a flattened version of EOL's mgrid solution.

3 Comments

Very good approach if a flat array is needed. ndarray.reshape() can "unflatten" the resulting arrays, if needed.
Yes, but I think @EOL's mgrid is probably better if the reshaped array is needed. I used the flattened version since @Imagine's question implied a flattened array was desired, by calling it a list and by saying they'd use np.flatten if they could generate a grid first.
@askewchan: Thanks for your answer too -- I ended up using both! (Each for different things)

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.