Skip to content

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()