MONAI: Medical Open Network for AI
MONAI (Medical Open Network for AI) is a PyTorch-based, open-source framework providing domain-optimized foundational capabilities for deep learning in healthcare imaging. It offers standardized, efficient, and reproducible components like data loaders, transforms, networks, and metrics, specifically designed for medical applications. The current version is 1.5.2, with regular minor and patch releases, typically multiple times per year.
Common errors
-
RuntimeError: CUDA out of memory. Tried to allocate X GiB (GPU Y)
cause The model, batch size, or image dimensions exceed the available VRAM on the GPU.fixReduce the `batch_size`, crop input images to smaller dimensions, or enable mixed precision training (`torch.cuda.amp.autocast()`) if your model supports it. -
TypeError: can't convert CUDA tensor to numpy. Use .cpu().numpy() instead if you want to transfer the tensor to CPU
cause Attempting to call `.numpy()` directly on a PyTorch tensor residing on the GPU.fixBefore converting a GPU tensor to a NumPy array, first move it to the CPU using `.cpu()`: `my_tensor.cpu().numpy()`. -
KeyError: 'image' (or 'label', etc.)
cause A dictionary-based transform (e.g., `LoadImaged`) cannot find one of the specified `keys` in the input dictionary.fixVerify that your input dictionary contains all the keys specified in the `keys` argument of the transform. For example, if `LoadImaged(keys=['data_key'])`, ensure your input dictionary has `{'data_key': ...}`. -
AttributeError: 'Dataset' object has no attribute 'apply'
cause Attempting to use the `apply` method on a transform. This method was removed in MONAI v1.0.0.fixFor built-in transforms, simply call them directly. For custom transforms, ensure you have overridden the `__call__` method instead of `apply`. -
ImportError: cannot import name 'UNet' from 'monai.networks.nets'
cause Incorrect import path for a specific symbol, or an older version of MONAI where the symbol's location was different.fixConsult the official MONAI documentation for the exact import path corresponding to your installed MONAI version. For `UNet`, the correct path is `from monai.networks.nets import UNet`.
Warnings
- breaking The `apply` method for custom transforms was removed in v1.0.0. Custom transforms should override the `__call__` method.
- breaking The `sliding_window_inference` utility was moved from `monai.data` to `monai.inferers`.
- breaking Format-specific image loaders like `LoadNifti` or `LoadDICOM` were deprecated/removed in favor of `LoadImaged` (for dictionary-based inputs) or `LoadImaget` (for tuple-based inputs).
- gotcha Dictionary-based transforms (e.g., `LoadImaged`, `ScaleIntensityRanged`) operate on specific keys. Mismatching keys between your input dictionary and the transform's `keys` argument will result in a `KeyError`.
- gotcha MONAI heavily relies on PyTorch. Users must ensure their PyTorch version is compatible with the installed MONAI version and their CUDA setup to avoid `RuntimeError` or performance issues.
Install
-
pip install monai
Imports
- Compose
from monai.transforms import Compose
- LoadImaged
from monai.transforms import LoadNifti
from monai.transforms import LoadImaged
- CacheDataset
from monai.data.dataset import CacheDataset
from monai.data import CacheDataset
- UNet
from monai.networks.nets import UNet
- sliding_window_inference
from monai.data import sliding_window_inference
from monai.inferers import sliding_window_inference
Quickstart
import torch
import numpy as np
from monai.transforms import Compose, LoadImaged, EnsureChannelFirstd, ScaleIntensityRanged, Orientationd, Spacingd
import os
import nibabel as nib
# Create dummy image file for demonstration
dummy_image_path = "dummy_image.nii.gz"
if not os.path.exists(dummy_image_path):
print(f"Creating dummy NIfTI image at {dummy_image_path}...")
dummy_data = np.random.rand(10, 10, 10).astype(np.float32)
affine = np.diag([1, 1, 1, 1])
nifti_img = nib.Nifti1Image(dummy_data, affine)
nib.save(nifti_img, dummy_image_path)
# 1. Define a transform pipeline for dictionary-based data
keys = ["image"] # working with dictionary data, key for the image
transform = Compose(
[
LoadImaged(keys=keys), # Load medical image data
EnsureChannelFirstd(keys=keys), # Ensure channel dimension is first
ScaleIntensityRanged(keys=keys, a_min=0, a_max=1, b_min=0.0, b_max=1.0, clip=True), # Normalize intensity
Orientationd(keys=keys, axcodes="RAS"), # Reorient image to standard anatomical space
Spacingd(keys=keys, pixdim=(1.5, 1.5, 2.0), mode="bilinear"), # Resample to desired spacing
]
)
# 2. Create dummy data list (mimicking a dataset of file paths)
data = [{
"image": dummy_image_path
}] * 2 # Two dummy items for batching effect
# 3. Apply transforms (typically done within a Dataset/DataLoader)
transformed_data = [transform(item) for item in data]
print(f"Original image path: {data[0]['image']}")
print(f"Transformed image shape: {transformed_data[0]['image'].shape}")
print(f"Transformed image dtype: {transformed_data[0]['image'].dtype}")
# Clean up dummy file
if os.path.exists(dummy_image_path):
os.remove(dummy_image_path)
print(f"Cleaned up dummy NIfTI image: {dummy_image_path}")