0

I want to split a 3d matrix into smaller matrixes of equal size. In this case a 4x4x3 matrix into 4 individual matrices of 2x2x3. I am trying this:

import numpy as np
from skimage.util.shape import view_as_windows

#create 4x4
data = np.array([[1,2,3,4], 
                  [5,6,7,8], 
                  [9,10,11,12], 
                  [13,14,15,16]])

#make 3 dimensional
stacked = np.dstack([data, data, data])

#split it
windows = view_as_windows(stacked, (2,2,3))

but windows.shape returns (3, 3, 1, 2, 2, 3) when I am expecting something more like (4, 2, 2, 3), or even a list of matrices which has length 4 and is (2,2,3) I don't need to use skimage to do this, numpy are else is fine.

If this were a 2d problem with data and input (4,4) I would expect the output to be 4 matrixes:

[[1,2,
  5,6]]

[[3,4,
  7,8]]

[[9,10,
  13,14]]

[[11,12,
  15,16]]
Jérôme Richard
  • 41,678
  • 6
  • 29
  • 59
Stefano Potter
  • 3,467
  • 10
  • 45
  • 82
  • You do realize the size does not change. ie in your data, the size is 30000. But you just want 3000 thats not possible. Either you get 100 * 10 * 10 * 3 or this wont work – Onyambu Feb 25 '22 at 22:22
  • I set up my problem poorly, I tried to simplify a bit with the edits just made. – Stefano Potter Feb 25 '22 at 22:34
  • 1
    with the stacked data, what is your expected outcome? – Onyambu Feb 25 '22 at 23:23
  • Does this answer your question? [Slice 2d array into smaller 2d arrays](https://stackoverflow.com/questions/16856788/slice-2d-array-into-smaller-2d-arrays) – Jérôme Richard Feb 25 '22 at 23:30
  • @JérômeRichard the `view_as_windows` command should work. Its only that OP has stacked the data depthwise, making it quite difficult to visualize. If it was stacked height-wise it could have worked. For example, `view_as_windows(data, (2,2), 2)` – Onyambu Feb 25 '22 at 23:47

1 Answers1

1

view_as_windows returns overlapping window views into the same array. Your array has 3x3 such windows, starting at (row, col) coordinates (0, 0), (0, 1), (0, 2), (1, 0), (1, 1), (1, 2), (2, 0), (2, 1), and (2, 2). You seem to want nonoverlapping windows, which scikit-image calls view_as_blocks:

import numpy as np
from skimage.util import view_as_blocks

matrix = np.random.random((4, 4, 3))
blocked = view_as_blocks(matrix, (2, 2, 3))
print(blocked.shape)

This will print:

(2, 2, 1, 2, 2, 3)

Your four (2, 2, 3) matrices are at coordinates (0, 0, 0), (0, 1, 0), (1, 0, 0), and (1, 1, 0) in the above array. There is still a dimension for the blocking along the final axis, even though there is only a single block in that axis.

You can get a linear array of just the four with:

linearized = blocked.reshape((4, 2, 2, 3))
Juan
  • 5,433
  • 21
  • 23