How to create an increasing multidimensional array in numpy

I am trying to perform the reverse deformation taking into account the homographic matrix, and for this I need a numpy array that looks like this:

([[0, 0, 1], [0, 1, 1], [0, 2, 1], ... [1, 0, 1], [1, 1, 1], ... [n, p, 1]])

Where n is the image width ( im.shape[0]) and p is the image height ( im.shape[1]). Any idea on how to efficiently create numpy arrays that look like this?

Edit:

There are several discussions about what is the fastest if someone has information about what I think would be interesting to hear. I am grateful to everyone for their help!

+4
source share
4 answers

Using indices_merged_arr_generic_using_cpby @unutbu -

def indices_one_grid(n,p):
    ar = np.ones((n,p),dtype=int)
    return indices_merged_arr_generic_using_cp(ar)

Run Example -

In [141]: indices_one_grid(n=3,p=4)
Out[141]: 
array([[0, 0, 1],
       [0, 1, 1],
       [0, 2, 1],
       [0, 3, 1],
       [1, 0, 1],
       [1, 1, 1],
       [1, 2, 1],
       [1, 3, 1],
       [2, 0, 1],
       [2, 1, 1],
       [2, 2, 1],
       [2, 3, 1]])

Benchmarking

Other approaches -

def MSeifert(n,p):
    x, y = np.mgrid[:n, :p]
    return np.stack([x.ravel(), y.ravel(), np.ones(x.size, dtype=int)], axis=1)

def DanielF(n,p):
    return np.vstack([np.indices((n,p)), np.ones((1, n,p))]).reshape(3,-1).T

def Aaron(n,p):
    arr = np.empty([n*p,3])
    arr[:,0] = np.repeat(np.arange(n),p)
    arr[:,1] = np.tile(np.arange(p),n)
    arr[:,2] = 1
    return arr

Dates -

In [152]: n=1000;p=1000

In [153]: %timeit MSeifert(n,p)
     ...: %timeit DanielF(n,p)
     ...: %timeit Aaron(n,p)
     ...: %timeit indices_one_grid(n,p)
     ...: 
100 loops, best of 3: 15.8 ms per loop
100 loops, best of 3: 8.46 ms per loop
100 loops, best of 3: 10.4 ms per loop
100 loops, best of 3: 4.78 ms per loop
+5
source

np.mgrid ( ) np.stack, :

>>> x, y = np.mgrid[:3, :3]   # assuming a 3x3 image
>>> np.stack([x.ravel(), y.ravel(), np.ones(x.size, dtype=int)], axis=1)
array([[0, 0, 1],
       [0, 1, 1],
       [0, 2, 1],
       [1, 0, 1],
       [1, 1, 1],
       [1, 2, 1],
       [2, 0, 1],
       [2, 1, 1],
       [2, 2, 1]])

3 , , np.mgrid, .

+1

In one line:

np.vstack([np.indices(im.shape), np.ones((1, *im.shape))]).reshape(3,-1).T

Basically, the key to getting indexes like this is using something like indices, mgrid/ meshgridor the like.

+1
source

You can do this without a loop with numpy.tileand numpy.repeatand a pre-allocated container

import numpy as np
arr = np.empty([n*p,3])
arr[:,0] = np.repeat(np.arange(n),p)
arr[:,1] = np.tile(np.arange(p),n)
arr[:,2] = 1
+1
source

Source: https://habr.com/ru/post/1686546/


All Articles