I am trying to generate an array of coordinates that will lie on an image. The image being used is a 640x480 pixel frame. I have been able to make an array of all the x and y points that I wish to use. I am trying to plot small circles at each of these points just for visualization and for later use so I am trying to get the coordinates into a form that can be entered into the OpenCV circle function. Below is what I have got so far:
Ypts = np.arange(5, 480, 5)
Xpts = np.arange(5, 640, 5)
I have tried using
[pts]= np.vstack([Xpts, Ypts]).T
and
coordinate = []
for x in range(Xpts.size):
for y in range(Ypts.size):
coordinate.append((x, y))
With no success, the output I get for coordinate is [0, 0], [0, 1], [0, 2], ...
instead of points relating to the values of Xpts
and Ypts
.
On a smaller scale this is an example of what the x and y arrays are:
Xpts = [5, 10, 15, 20, 25, 30, 35]
Ypts = [5, 10, 15]
and what i am trying to get to as an answer is:
Points = [[5, 5],
[5, 10],
[5, 15],
[10, 5],
[10, 10],
[10, 15],
[15, 5],
[15, 10],
......,
[35, 15]]
Inspired by this solution
and with focus on performance, you can use np.meshgrid
as well -
X2D,Y2D = np.meshgrid(Ypts,Xpts)
out = np.column_stack((Y2D.ravel(),X2D.ravel()))
Sample run -
In [39]: Xpts=np.array([5, 10, 15, 20, 25, 30, 35])
...: Ypts=np.array([3, 6, 9])
...:
In [40]: X2D,Y2D = np.meshgrid(Ypts,Xpts)
In [41]: np.column_stack((Y2D.ravel(),X2D.ravel()))
Out[41]:
array([[ 5, 3],
[ 5, 6],
[ 5, 9],
......
[35, 6],
[35, 9]])
Runtime test
As usual I am listing timings for the vectorized approaches listed thus far to solve the problem. So, the credit for the approaches listed here goes to the respective authors.
Approaches listed as functions :
def itertools_based():
Ypts = np.arange(5, 480, 5)
Xpts = np.arange(5, 640, 5)
return np.array(list(itertools.product(Xpts, Ypts)))
def c__based():
py, px = np.mgrid[5:640:5,5:480:5]
return np.c_[py.ravel(), px.ravel()]
def meshgrid_based():
Ypts = np.arange(5, 480, 5)
Xpts = np.arange(5, 640, 5)
X2D,Y2D = np.meshgrid(Ypts,Xpts)
return np.column_stack((Y2D.ravel(),X2D.ravel()))
Finally verify and time them :
In [111]: %timeit itertools_based()
...: %timeit c__based()
...: %timeit meshgrid_based()
...:
100 loops, best of 3: 9.16 ms per loop
1000 loops, best of 3: 380 µs per loop
10000 loops, best of 3: 198 µs per loop
In [112]: np.allclose(itertools_based(),c__based())
Out[112]: True
In [113]: np.allclose(itertools_based(),meshgrid_based())
Out[113]: True
You can generate all the possible combinations with numpy's mgrid:
>>> py, px = np.mgrid[5:480:5, 5:640:5]
>>> points = np.c_[py.ravel(), px.ravel()]
>>> points
array([[ 5, 5],
[ 5, 10],
[ 5, 15],
...,
[475, 625],
[475, 630],
[475, 635]])
You can use itertools.product
which will basically return all possible combinations of the provided lists. See this code for an example:
import numpy as np
import itertools
Xpts=[5, 10, 15, 20, 25, 30, 35]
Ypts=[5, 10, 15]
Points = np.array(list(itertools.product(Xpts, Ypts)))
This will return the following:
array([[ 5, 5],
[ 5, 10],
[ 5, 15],
[10, 5],
[10, 10],
[10, 15],
[15, 5],
[15, 10],
[15, 15],
[20, 5],
[20, 10],
[20, 15],
[25, 5],
[25, 10],
[25, 15],
[30, 5],
[30, 10],
[30, 15],
[35, 5],
[35, 10],
[35, 15]])
People have already suggested numpy.mgrid and itertools. Use them.
However, for the sake of education, Python provides us with a powerful concept known as "list comprehension". You can obtain the Cartesian product by running:
[(a,b) for a in range(5, 485, 5) for b in range(5, 645, 5)]
Change (a,b)
to [a,b]
if you don't want a list of tuples.
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