Split a 3D numpy array into 3D blocks
Here are vectorized versions of those loopy implementations using a combination of permuting dims with np.transpose
and reshaping
-
def make_blocks_vectorized(x,d): p,m,n = x.shape return x.reshape(-1,m//d,d,n//d,d).transpose(1,3,0,2,4).reshape(-1,p,d,d)def unmake_blocks_vectorized(x,d,m,n): return np.concatenate(x).reshape(m//d,n//d,d,d).transpose(0,2,1,3).reshape(m,n)
Sample run for make_blocks
-
In [120]: x = np.random.randint(0,9,(2,4,4))In [121]: make_blocks(x,2)Out[121]: [array([[[4, 7], [8, 3]], [[0, 5], [3, 2]]]), array([[[5, 7], [4, 0]], [[7, 3], [5, 7]]]), ... and so on.In [122]: make_blocks_vectorized(x,2)Out[122]: array([[[[4, 7], [8, 3]], [[0, 5], [3, 2]]], [[[5, 7], [4, 0]], [[7, 3], [5, 7]]], ... and so on.
Sample run for unmake_blocks
-
In [135]: A = [np.random.randint(0,9,(3,3)) for i in range(6)]In [136]: d = 3In [137]: m,n = 6,9In [138]: unmake_blocks(A,d,m,n)Out[138]: array([[6, 6, 7, 8, 6, 4, 5, 4, 8], [8, 8, 3, 2, 7, 6, 8, 5, 1], [5, 2, 2, 7, 1, 2, 3, 1, 5], [6, 7, 8, 2, 2, 1, 6, 8, 4], [8, 3, 0, 4, 4, 8, 8, 6, 3], [5, 5, 4, 8, 5, 2, 2, 2, 3]])In [139]: unmake_blocks_vectorized(A,d,m,n)Out[139]: array([[6, 6, 7, 8, 6, 4, 5, 4, 8], [8, 8, 3, 2, 7, 6, 8, 5, 1], [5, 2, 2, 7, 1, 2, 3, 1, 5], [6, 7, 8, 2, 2, 1, 6, 8, 4], [8, 3, 0, 4, 4, 8, 8, 6, 3], [5, 5, 4, 8, 5, 2, 2, 2, 3]])
Alternative to make_blocks
with view_as_blocks
-
from skimage.util.shape import view_as_blocksdef make_blocks_vectorized_v2(x,d): return view_as_blocks(x,(x.shape[0],d,d))
Runtime test
1) make_blocks
with original and view_as_blocks
based approaches -
In [213]: x = np.random.randint(0,9,(100,160,120)) # scaled down by 10In [214]: %timeit make_blocks(x,10)1000 loops, best of 3: 198 µs per loopIn [215]: %timeit view_as_blocks(x,(x.shape[0],10,10))10000 loops, best of 3: 85.4 µs per loop
2) unmake_blocks
with original and transpose+reshape
based approaches -
In [237]: A = [np.random.randint(0,9,(10,10)) for i in range(600)]In [238]: d = 10In [239]: m,n = 10*20,10*30In [240]: %timeit unmake_blocks(A,d,m,n)100 loops, best of 3: 2.03 ms per loopIn [241]: %timeit unmake_blocks_vectorized(A,d,m,n)1000 loops, best of 3: 511 µs per loop