Get random 2D slices from a 3D NumPy array orthogonally across each dimension

404 views Asked by At

I am trying to randomly sample 30% of a NumPy array of shape (790, 64, 64, 1). The last dimension is the channel info for the image so essentially it's a 3D image. The intention is to generate 2D slices orthogonally across each dimension in a random way so as to get 30% of the total information of the original.

I looked at this question to understand how to randomly generate slices but I'm being unable to extend it to my use case.

So far I'm only able to generate the size of the data I would need.

dim1_len = 0.3 * img.shape[0]
dim2_len = 0.3 * img.shape[1]
dim3_len = 0.3 * img.shape[2]

Sorry if the question is a little broad.

1

There are 1 answers

0
scleronomic On

First a few comments, you say you want to keep 30 % of the original information. If you keep 30% of each axis you only end up with 0.3*0.3*0.3 = 0.027 (2.7%) of the information. Consider using 0.3 ^(1/3)as reduction factor. The next thing is that you maybe want to preserve the spatial ordering of the randomly sampled indices, so maybe include a np.sort(...) to the question you linked.

Now to the main question, you can use np.meshgrid(*arrays, sparse=True, indexing='ij') to get a list of arrays which can be used for broadcasting. This comes in handy for adding the necessary newaxis to the random indices.

import numpy as np

img = np.random.random((790, 64, 64, 1))
alpha = 0.3 ** (1/3)

shape_new = (np.array(img.shape[:-1]) * alpha).astype(int)
idx = [np.sort(np.random.choice(img.shape[i], shape_new[i], replace=False))
       for i in range(3)]
# shapes: [(528,)  (42,)  (42,)]

idx_o = np.meshgrid(*idx, sparse=True, indexing='ij')
# shapes: [(528, 1, 1)
#          (1,  42, 1)
#          (1,  1, 42)]

img_new = img[tuple(idx_o)]
# shape: (528, 42, 42, 1)