9

I divided a (512x512) 2-dimensional array to 2x2 blocks using this function.

skimage.util.view_as_blocks (arr_in, block_shape)
array([[ 0,  1,  2,  3],
   [ 4,  5,  6,  7],
   [ 8,  9, 10, 11],
   [12, 13, 14, 15]])
   >>> B = view_as_blocks(A, block_shape=(2, 2))
   >>> B[0, 0]
   array([[0, 1],
          [4, 5]])
   >>> B[0, 1]
   array([[2, 3],
          [6, 7]])

Now I need to put the same blocks to their original places after manipulation but I couldn't see any function in skimage for that.

What's the best way to merge the non-overlapping arrays as it was before?

Thank you!

hma
  • 556
  • 2
  • 11
  • 29

2 Answers2

7

Use transpose/swapaxes to swap the second and third axes and then reshape to have the last two axes merged -

B.transpose(0,2,1,3).reshape(-1,B.shape[1]*B.shape[3])
B.swapaxes(1,2).reshape(-1,B.shape[1]*B.shape[3])

Sample run -

In [41]: A
Out[41]: 
array([[ 0,  1,  2,  3],
       [ 4,  5,  6,  7],
       [ 8,  9, 10, 11],
       [12, 13, 14, 15]])

In [42]: B = view_as_blocks(A, block_shape=(2, 2))

In [43]: B
Out[43]: 
array([[[[ 0,  1],
         [ 4,  5]],

        [[ 2,  3],
         [ 6,  7]]],


       [[[ 8,  9],
         [12, 13]],

        [[10, 11],
         [14, 15]]]])

In [44]: B.transpose(0,2,1,3).reshape(-1,B.shape[1]*B.shape[3])
Out[44]: 
array([[ 0,  1,  2,  3],
       [ 4,  5,  6,  7],
       [ 8,  9, 10, 11],
       [12, 13, 14, 15]])
Divakar
  • 218,885
  • 19
  • 262
  • 358
  • Thank you for help your first answer also worked `B.transpose(0,2,1,3).reshape(512,512)`. Have a question, what is this part means `(-1,B.shape[1]*B.shape[3]) ` ? – hma Jan 06 '17 at 17:10
  • @enterbutton Basically it means that the new shape would have `B.shape[1]*B.shape[3]` number of cols and the number of rows be decided by the reshape function by dividing the total number of elements with the number of cols as denoted by that `-1`. In layman terms, I am letting the computer compute the no. of rows for me with that `-1`. In most cases,, it meant to produce compact codes. Hope that makes sense! – Divakar Jan 06 '17 at 17:13
  • Thank you so much again for help and explanation @Divakar – hma Jan 06 '17 at 18:59
  • @Divakar +1 answer. is there a similar function available in OpenCV? – Jeru Luke Jan 07 '17 at 08:23
  • 2
    @JeruLuke To do `view_as_blocks` or retrieve back/merge back? Sorry, there isn't any for either. Is there some specific usage that you are trying to exploit, because if you are using OpenCV on Python, then NumPy arrays should work just as well. – Divakar Jan 07 '17 at 19:32
  • 1
    `view_as_blocks` uses `as_strided`. In this case the action is the same as: `B=A.reshape(2,2,2,2).transpose(0,2,1,3)`. Going back to `A` is the reverse, the same transpose followed by reshape to (4,4). – hpaulj Aug 22 '17 at 20:01
  • 1
    How can I achieve it if A is 3 dimensional with num of channels? – Roman Aug 11 '20 at 18:17
1

This is where you'd better use einops:

from einops import rearrange

# that's how you could rewrite view_as_blocks
B = rearrange(A, '(x dx) (y dy) -> x y dx dy', dx=2, dy=2)

# that's an answer to your question
A = rearrange(B, 'x y dx dy -> (x dx) (y dy)')

See documentation for more operations on images

Alleo
  • 7,891
  • 2
  • 40
  • 30
  • 1
    Finally something easily deployed and intuitive - I've looked 2 days for something like this - cheers – nate Mar 07 '20 at 01:41