3

I looking for a way in which I using a for loop can iterate through a bigger matrix, in which each iteration will output a sub matrix of size (row, col, depth) (6,3,3).

My big matrix is stored as numpy matrix, and would possible also like the each iteration to be outputted as such.

>>> import numpy as np
>>> a = np.random.rand(6*3,3*3,3)
>>> print a.shape
(18, 9, 3)
>>> print a
>>> b

The variable b should contain all the sub matrixes of size (6,3,3) from matrix a. Each submatrix should not overlap with the prior.

enter image description here

J.Down
  • 700
  • 1
  • 9
  • 32
  • Are you looking for sliding matrices? How many dimensions are in the input array? Could you add a sample case? – Divakar Mar 15 '17 at 14:43
  • Yes... I guess you could call it a sliding matrix.. The dimension well.. rows are always 78 (dividable with 6). columns depends on the data length, but always dividable with 3, and depth is 3 (actually 4 RGBA, but i am slicing the alpha channel away) – J.Down Mar 15 '17 at 14:47
  • So, how many such submatrices are you supposed to get from the just edited sample data? – Divakar Mar 15 '17 at 14:49
  • @Divakar 3 sub matrices from the bigger matrix – J.Down Mar 15 '17 at 14:51
  • Or 27? Do the math again? – Divakar Mar 15 '17 at 14:52
  • How are you getting 27? – J.Down Mar 15 '17 at 14:54
  • Well `a` has `1458 (18*9*9)` elems, whereas the block as `54 (6*3*3)` elems. So, by dividing? – Divakar Mar 15 '17 at 14:56
  • Ohh sorry... wait. I edited the post above. Now... its correct.. it should be 9 sub matrices. The input shape will always have depth 3. and the sub matrixes cannot be overlapping. – J.Down Mar 15 '17 at 14:57
  • I guess we are not clear on the `sliding` terms. So, let me put a different term - Are we looking for overlapping blocks that slides along the three dimensions of the input array or distinct ones? – Divakar Mar 15 '17 at 15:01

1 Answers1

2

Approach #1

I am assuming we are looking for non-overlapping/distinct blocks. As such we could use Scikit-image's view_as_blocks utility -

from skimage.util.shape import view_as_blocks

BSZ = (6,3,3)
out = view_as_blocks(a,BSZ).reshape((-1,)+ (BSZ))

Sample run -

In [279]: a = np.random.rand(6*3,3*3,3)

In [280]: out = view_as_blocks(a,BSZ).reshape((-1,)+ (BSZ))

In [281]: out.shape
Out[281]: (9, 6, 3, 3)

Approach #2

Using just native NumPy tools like reshaping and transpose, here's one way -

m,n,r = a.shape
split_shp = m//BSZ[0], BSZ[0], n//BSZ[1], BSZ[1], r//BSZ[2], BSZ[2]
out = a.reshape(split_shp).transpose(0,2,4,1,3,5).reshape((-1,)+ (BSZ))
Divakar
  • 218,885
  • 19
  • 262
  • 358
  • `/usr/local/lib/python2.7/dist-packages/skimage/util/shape.py:94: RuntimeWarning: Cannot provide views on a non-contiguous input array without copying. warn(RuntimeWarning("Cannot provide views on a non-contiguous input "` – J.Down Mar 15 '17 at 15:52
  • Something i should be worried about? – J.Down Mar 15 '17 at 15:52
  • @J.Down Well as the warning msg states, I am guessing your input isn't a contiguous one, which depends on the source of the input. So, to be safe I guess you could go with the second app, as internally first app is doing something similar. – Divakar Mar 15 '17 at 16:44
  • ` out = matrix.reshape(split_shp).transpose(0,2,4,1,3,5).reshape((-1,)+ (BSZ)) ValueError: total size of new array must be unchanged` – J.Down Mar 15 '17 at 17:03
  • @J.Down So, the question to you is `Are all dimensions divisible by the block size`? Like in the give sample the input array shape is (18,9,3) and thus each of those three dims are divisble by the respective sizes in block size (6,3,3). Is that the case with your actual inputs and block sizes? – Divakar Mar 15 '17 at 17:05
  • 1
    ahh. yes I had to fix something... I like approach 1 better than approach 2, due to the readbility.. Would it be possible to make a bit more readable? – J.Down Mar 15 '17 at 17:26
  • @J.Down Well I think that's the best I could do :) – Divakar Mar 15 '17 at 18:01