I am working with 3D images(300) of size (128x128x128). I want to extract the image area (remove the background), do some transformation, and plug the transformed part back on the original image. How can I do this in python?
This is what I tried:
I created a mask which has the shape (128, 128, 128)
. I then got the np.sum
on that mask n_voxels_flattened = np.sum(mask)
(removed the zero voxels so that I can do the transformation on non-zeros voxels) where now the n_voxels_flattened=962517
. Then iterated over all images (300 images) which resulted in an array with shape (962517, 300)
. I did some adjustments to this array and the output has the same shape as input:(962517, 300)
. I now want to reshape this array and put back the zero voxels I removed so that it has the shape (128,128,128,300)
.
This is what I tried, but it resulted in a weird looking image when visualized.
zero_array = np.zeros((128*128*128 * 300))
zero_array[:len(result.reshape(-1))]=result.reshape(-1)
Can someone please help me with this?
CodePudding user response:
Ok, if I've read your question correctly, you want to apply some function, f
, to all the voxels which are not background pixels (0
)?
In that case, you can do this using the np.where
function in numpy
, but I'll provide a longer example which does the same thing, too.
np.where
has two modes. When you specify the optional second and third arguments, it will insert all the values from the second argument into a new array where the condition is True
, and the values from the third argument where the condition is False
.
Example using np.where
import numpy as np
# I used 3 to test because your original array is quite large,
# but you can change this back to (128, 128, 128, 300).
# I would suggest you iterate over this instead of having such a large
# single array object.
shape = (128,128,128,3)
# Computing some random data to try and emulate your situation
voxels = np.random.randint(low=0, high=10, size=shape)
# I'm going to use np.power(x, 2) as my transformation function
# because I don't know what you're doing with the voxels
# so you can just replace this with your actual transformation function.
output_voxels = np.where(voxels != 0, np.power(voxels, 2), voxels)
print(output_voxels.shape)
# (128, 128, 128, 3)
This results in a new array, where all voxels which are not 0
have been raised to a power of 2, and all voxels which are 0
are filled with their original value, 0
.
Longer example using array masking directly.
import numpy as np
shape = (128,128,128,3)
voxels = np.random.randint(low=0, high=10, size=shape)
# Index the array to find all the data which is not equal to 0.
# Here we are using an inverse (~) mask so it has to be in brackets,
# Alternatively you could use voxels[voxels != 0]
valid_voxels = voxels[~(voxels == 0)]
# Simple transformation function to emulate your situation.
transformed_valid_voxels = np.power(valid_voxels, 2)
# Define a new array in the same shape as the input data.
output_voxels = np.zeros(shape=shape)
# Assign the new pixels to the output where the mask is applied.
output_voxels[~(voxels == 0)] = transformed_valid_voxels
print(output_voxels.shape)
# (128, 128, 128, 3)
Hope I read the question correctly.