Transformation
Transformation acts as a prprocessing and augmentation layers for model training. In medicai
for 3D transformation, the expected format is: depth, height, width, channel
. The transformation are implemented for a single sample. All the transformations are implemented using tensorflow
in order to able to run with tf.data
API with keras
multi-backend library.
Run the following code in kaggle environment: 3D Transformation. It contains side by side comparison between medicai
and monai
.
Load Image
def PyLoadImage(image_path, label_path):
# load data
image_nii = nib.load(image_path)
label_nii = nib.load(label_path)
image = image_nii.get_fdata().astype(np.float32)
label = label_nii.get_fdata().astype(np.float32)
affine = np.array(image_nii.affine, dtype=np.float32)
# re-arrange shape [whd -> dhw]
image = np.transpose(image, (2, 1, 0))
label = np.transpose(label, (2, 1, 0))
affine[:, :3] = affine[:, [2, 1, 0]]
# add channel axis
image = image[..., np.newaxis] if image.ndim == 3 else image
label = label[..., np.newaxis] if label.ndim == 3 else label
# pack to dict
data = {}
meta = {}
data['image'] = image
data['label'] = label
meta['affine'] = affine
return data, meta
img_path = 'images/coronacases_001.nii.gz'
mask_path = 'masks/coronacases_001.nii.gz'
Resize
Resize the input image to given spatial size. Implemented using tf.image.resize
and depth_interpolate
.
from medicai.transforms import (
Compose,
Resize,
)
# define transformations
transform = Compose([
Resize(
keys=["image", "label"],
spatial_shape=(96, 96, 96),
mode=("bilinear", "nearest")
)
])
# load the raw data
data, meta = PyLoadImage(image_path=image_path, label_path=mask_path)
# passing sample to medicai transform
output = transform(data, meta)
# get transformed sample
medicai_image = output['image'].numpy()
medicai_label = output['label'].numpy()
ScaleIntensity Range
Scale the intensity of the entire array from the range [a_min, a_max]
to [b_min, b_max]
, with an optional clipping feature.
from medicai.transforms import (
Compose,
ScaleIntensityRange,
)
# define transformations
transform = Compose([
ScaleIntensityRange(
keys=["image"],
a_min=-175,
a_max=250,
b_min=0.0,
b_max=1.0,
clip=True,
)
])
# load the raw data
data, meta = PyLoadImage(image_path=image_path, label_path=mask_path)
# passing sample to medicai transform
output = transform(data, meta)
# get transformed sample
medicai_image = output['image'].numpy()
medicai_label = output['label'].numpy()
Crop Foreground
Crop an image using a bounding box, where the bounding box is generated by selecting the foreground through the select_fn
function at the specified channel_indices. A margin is added to each spatial dimension of the bounding box.
from medicai.transforms import (
Compose,
CropForeground,
)
# define transformations
transform = Compose([
CropForeground(
keys=("image", "label"),
source_key="image"
)
])
# load the raw data
data, meta = PyLoadImage(image_path=image_path, label_path=mask_path)
# passing sample to medicai transform
output = transform(data, meta)
# get transformed sample
medicai_image = output['image'].numpy()
medicai_label = output['label'].numpy()
Spacing
Resample input image into the specified pixdim. It will require affine
meta information.
from medicai.transforms import (
Compose,
Spacing,
)
# define transformations
transform = Compose([
Spacing(
keys=["image", "label"],
pixdim=[2.0, 1.5, 1.5]
)
])
# load the raw data
data, meta = PyLoadImage(image_path=image_path, label_path=mask_path)
# passing sample to medicai transform
output = transform(data, meta)
# get transformed sample
medicai_image = output['image'].numpy()
medicai_label = output['label'].numpy()
Orientation
Change the orientation of the input image to the specified one based on the provided axcodes
. It will require affine
meta information.
from medicai.transforms import (
Compose,
Orientation,
)
# define transformations
transform = Compose([
Orientation(
keys=["image", "label"],
axcodes="RAS"
)
])
# load the raw data
data, meta = PyLoadImage(image_path=image_path, label_path=mask_path)
# passing sample to medicai transform
output = transform(data, meta)
# get transformed sample
medicai_image = output['image'].numpy()
medicai_label = output['label'].numpy()
Random Rotate 90
Rotate the input sample 90 degree at random.
from medicai.transforms import (
Compose,
RandRotate90,
)
# define transformations
transform = Compose([
RandRotate90(
keys=["image", "label"],
prob=1.0,
max_k=3,
spatial_axes=(2,1)
)
])
# load the raw data
data, meta = PyLoadImage(image_path=image_path, label_path=mask_path)
# passing sample to medicai transform
output = transform(data, meta)
# get transformed sample
medicai_image = output['image'].numpy()
medicai_label = output['label'].numpy()
Random Shift Intensity
Randomly shift the intensity of the image by applying a randomly selected offset.
from medicai.transforms import (
Compose,
RandShiftIntensity,
)
# define transformations
transform = Compose([
RandShiftIntensity(
keys=["image"],
offsets=0.10,
prob=1
)
])
# load the raw data
data, meta = PyLoadImage(image_path=image_path, label_path=mask_path)
# passing sample to medicai transform
output = transform(data, meta)
# get transformed sample
medicai_image = output['image'].numpy()
medicai_label = output['label'].numpy()
Random Crop By Positive Negative Label
Randomly crop fixed-sized regions from the image, with the center of each crop being either a foreground or background voxel based on the specified Positive-Negative Ratio. The function will return a list of arrays for all the cropped images.
from medicai.transforms import (
Compose,
RandCropByPosNegLabel,
)
# define transformations
transform = Compose([
RandCropByPosNegLabel(
keys=["image", "label"],
spatial_size=(96, 96, 96),
pos=1,
neg=1,
num_samples=1,
image_reference_key="image",
image_threshold=0
)
])
# load the raw data
data, meta = PyLoadImage(image_path=image_path, label_path=mask_path)
# passing sample to medicai transform
output = transform(data, meta)
# get transformed sample
medicai_image = output['image'].numpy()
medicai_label = output['label'].numpy()
Random Spatial Crop
Randomly crops a region of interest (ROI) with a specified size from the input tensors. This transform extracts a 3D spatial ROI from the tensors specified by keys
. The size and center of the ROI can be either fixed or randomly determined within the bounds of the input tensor.
from medicai.transforms import (
Compose,
RandSpatialCrop,
)
# define transformations
transform = Compose([
RandSpatialCrop(
keys=["image", "label"],
roi_size=(96, 96, 96),
)
])
# load the raw data
data, meta = PyLoadImage(image_path=image_path, label_path=mask_path)
# passing sample to medicai transform
output = transform(data, meta)
# get transformed sample
medicai_image = output['image'].numpy()
medicai_label = output['label'].numpy()
Random Flip
Randomly flips tensors along specified spatial axes with a given probability. This transformation randomly decides whether to flip the input tensors based on the provided probability. If the decision is to flip, it reverses the tensor elements along the specified spatial axes.
from medicai.transforms import (
Compose,
RandFlip,
)
# define transformations
transform = Compose([
RandFlip(
keys=["image", "label"],
spatial_axis=[0],
prob=1.0,
),
RandFlip(
keys=["image", "label"],
spatial_axis=[1],
prob=1.0,
),
RandFlip(
keys=["image", "label"],
spatial_axis=[2],
prob=1.0,
)
])
# load the raw data
data, meta = PyLoadImage(image_path=image_path, label_path=mask_path)
# passing sample to medicai transform
output = transform(data, meta)
# get transformed sample
medicai_image = output['image'].numpy()
medicai_label = output['label'].numpy()