I have a 2D image with the shape (M, N), and would like to reshape it into (M//m * N//n, m, n). That is, to stack small patches of images into a 3D array.
Currently, I used two for-loop to achieve that
JavaScript
x
31
31
1
import numpy as np
2
a = np.arange(16).reshape(4,4)
3
b = np.zeros( (4,2,2))
4
5
# a = array([[ 0, 1, 2, 3],
6
# [ 4, 5, 6, 7],
7
# [ 8, 9, 10, 11],
8
# [12, 13, 14, 15]])
9
10
11
row_step = 2
12
col_step = 2
13
row_indices = np.arange(4, step = 2)
14
col_indices = np.arange(4, step = 2)
15
16
for i, row_idx in enumerate(row_indices):
17
for j, col_idx in enumerate(col_indices):
18
b[i*2+j, :,:] = a[row_idx:row_idx+row_step, col_idx:col_idx+col_step]
19
20
# b = array([[[ 0., 1.],
21
# [ 4., 5.]],
22
#
23
# [[ 2., 3.],
24
# [ 6., 7.]],
25
#
26
# [[ 8., 9.],
27
# [12., 13.]],
28
#
29
# [[10., 11.],
30
# [14., 15.]]])
31
Is there any other faster way to do this? Thanks a lot!
Advertisement
Answer
Use skimage.util.view_as_blocks
:
JavaScript
1
4
1
from skimage.util.shape import view_as_blocks
2
3
out = view_as_blocks(a, (2,2))#.copy()
4
Output:
JavaScript
1
13
13
1
array([[[[ 0, 1],
2
[ 4, 5]],
3
4
[[ 2, 3],
5
[ 6, 7]]],
6
7
8
[[[ 8, 9],
9
[12, 13]],
10
11
[[10, 11],
12
[14, 15]]]])
13
NB. Be aware that you have a view of the original object. If you want a copy, use view_as_blocks(a, (2,2)).copy()