Python Numpy generate coordinates for X and Y values in a certain range

14,617

Solution 1

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]])

Solution 2

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

Solution 3

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]])

Solution 4

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.

Share:
14,617

Related videos on Youtube

James Mallett
Author by

James Mallett

Final Year MEchatronic Engineering Student at Stellenbosch University.

Updated on October 06, 2022

Comments

  • James Mallett
    James Mallett over 1 year

    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]]
    
  • Divakar
    Divakar almost 8 years
    Shouldn't that be py, px = np.mgrid[5:640:5,5:480:5] going by the sample's expected output?
  • Imanol Luengo
    Imanol Luengo almost 8 years
    @Divakar yes I think you are right! I tend to think of an image as height x width (as is the C ordering in python). I guess it might also be a bit irrelevanf if the OP only wants the points, and the order is not important.
  • qwr
    qwr about 2 years
    This operates in vanilla python which may be slower