4

I'm have a line of code that efficiently reshapes a numpy array from a 400x8x8 array to a 160x160 array and I need to reverse the process but can't figure out the reverse of the line.

I can already do this process but it is very inefficient and requires nested loops which I would like to avoid for performance purposes.

Here is the code that I currently have to reverse the process (160x160 > 400x8x8):

       previousRow = 0
    for rowBlock in range(noBlocksOn1Axis):
        previousRow = rowBlock * blockSize  
        previousColumn = 0
        for columnBlock in range(noBlocksOn1Axis):
            previousColumn = columnBlock * blockSize
            block = 
            arrayY[previousRow:previousRow+blockSize, 
            previousColumn:previousColumn + blockSize]
            blocksList.append(block) 

And here is the line of code that reshapes 400x8x8 > 160x160:

    xy = np.zeros((160,160), dtype = np.uint8)

    xy = np.vstack(np.hstack(overDone[20*i:20+20*i]) for i in 
    range(overDone.shape[0]//20))

So any ideas of how I can perform this line of code in reverse?

Thanks :D

Divakar
  • 218,885
  • 19
  • 262
  • 358
Harry Reid
  • 89
  • 1
  • 7

2 Answers2

2

Reshape, swap-axes (or transpose axes) and reshape to get overDone back -

xy.reshape(20,8,20,8).swapaxes(1,2).reshape(400,8,8)

More info on intuition behind nd-to-nd array transformation.

Make it generic to handle generic shapes -

m,n = xy.shape
M,N = 20,20 # block size used to get xy
overDone_ = xy.reshape(M,m//M,N,n//N).swapaxes(1,2).reshape(-1,m//M,n//N)

Sample run -

# Original input
In [21]: overDone = np.random.rand(400,8,8)

# Perform forward step to get xy
In [22]: xy = np.vstack(np.hstack(overDone[20*i:20+20*i]) for i in range(overDone.shape[0]//20))

# Use proposed approach to get back overDone
In [23]: out = xy.reshape(20,8,20,8).swapaxes(1,2).reshape(400,8,8)

# Verify output to be same as overDone
In [42]: np.array_equal(out,overDone)
Out[42]: True

Bonus :

We could use those same vectorized reshape+permute-axes steps to create xy for the forward process -

xy = overDone.reshape(20,20,8,8).swapaxes(1,2).reshape(160,160)
Divakar
  • 218,885
  • 19
  • 262
  • 358
0

What's wrong with numpy.reshape?

my_array_3d = my_array.reshape((400, 8, 8))
my_array_2d = my_array.reshape((160, 160))
scnerd
  • 5,836
  • 2
  • 21
  • 36