Loaders
The loaders module provides functions for loading and saving medical images and masks in various formats.
Overview
This module handles I/O operations for medical images, supporting common 2D and 3D formats including NIFTI, PNG, TIFF, and DICOM.
Key Features:
Automatic format detection
2D and 3D image support
Metadata preservation
Image and mask validation
Compatibility checking
Supported Formats:
3D: NIFTI (.nii, .nii.gz), NRRD (.nrrd), MetaImage (.mha, .mhd)
2D: PNG, TIFF, JPEG, BMP
DICOM: Single files or series
Functions
load_image
- medtda.loaders.load_image(path)[source]
Load image from file (auto-detects format).
Supports: - 2D formats: PNG, JPG, JPEG, TIFF, PGM - 3D/4D formats: NIfTI (.nii, .nii.gz), NRRD (.nrrd), MHA (.mha), MHD (.mhd)
- Parameters:
path (str or Path) – Path to the image file.
- Return type:
- Returns:
image_array (numpy.ndarray) – Loaded image as numpy array.
metadata (dict) – Dictionary containing image metadata: - ‘spacing’: Pixel/voxel spacing (tuple) - ‘origin’: Image origin coordinates (tuple) - ‘direction’: Direction cosines (tuple or None for 2D) - ‘dtype’: Original data type - ‘format’: File format
- Raises:
FileNotFoundError – If the file doesn’t exist.
ValueError – If the file format is not supported or required library is missing.
Load a medical image from file.
Signature:
def load_image(path: Union[str, Path]) -> Tuple[np.ndarray, dict]
Parameters:
path (str or Path) - Path to image file
Returns:
image (np.ndarray) - Image array
metadata (dict) - Image metadata including:
'spacing'- Voxel spacing (if available)'origin'- Image origin'direction'- Image orientation'dtype'- Original data type
Example:
from medtda.loaders import load_image
# Load 3D NIFTI image
image, metadata = load_image('ct_scan.nii.gz')
print(f"Image shape: {image.shape}")
print(f"Spacing: {metadata.get('spacing')}")
# Load 2D PNG image
image_2d, metadata_2d = load_image('xray.png')
load_mask
- medtda.loaders.load_mask(path)[source]
Load mask from file (auto-detects format).
Masks are loaded preserving all label values for multi-label support.
- Parameters:
path (str or Path) – Path to the mask file.
- Return type:
- Returns:
mask_array (numpy.ndarray) – Loaded mask as numpy array (dtype: uint8) with original label values preserved.
metadata (dict) – Dictionary containing mask metadata (same structure as load_image).
- Raises:
FileNotFoundError – If the file doesn’t exist.
ValueError – If the file format is not supported.
Notes
Multi-label masks are supported. Use the label parameter in preprocessing and extraction classes to specify which label to work with.
Load a mask (binary or multi-label) from file.
Signature:
def load_mask(path: Union[str, Path]) -> Tuple[np.ndarray, dict]
Parameters:
path (str or Path) - Path to mask file
Returns:
mask (np.ndarray) - Mask array (integer type)
metadata (dict) - Mask metadata
Example:
from medtda.loaders import load_mask
# Binary mask
mask, metadata = load_mask('segmentation.nii.gz')
# Multi-label mask
multi_mask, metadata = load_mask('multi_label.nii.gz')
print(f"Labels present: {np.unique(multi_mask)}")
save_image
- medtda.loaders.save_image(image_array, path, metadata=None)[source]
Save image array to file.
- Parameters:
image_array (numpy.ndarray) – Image array to save.
path (str or Path) – Output file path.
metadata (dict, optional) – Image metadata (spacing, origin, direction). Only used for 3D/4D formats.
- Raises:
ValueError – If the file format is not supported.
- Return type:
Save an image array to file.
Signature:
def save_image(
image_array: np.ndarray,
path: Union[str, Path],
metadata: Optional[dict] = None
) -> None
Parameters:
image_array (np.ndarray) - Image array to save
path (str or Path) - Output file path
metadata (dict or None) - Optional metadata (spacing, origin, etc.)
Example:
from medtda.loaders import save_image
# Save processed image
save_image(
processed_image,
'output.nii.gz',
metadata={'spacing': (1.0, 1.0, 1.0)}
)
# Save as 2D PNG
save_image(slice_2d, 'slice.png')
Validation Functions
validate_image
- medtda.loaders.validate_image(image)[source]
Validate image array.
- Parameters:
image (numpy.ndarray) – Image array to validate.
- Raises:
TypeError – If image is not a numpy array.
ValueError – If image has invalid dimensions or contains invalid values.
- Return type:
Validate an image array.
Signature:
def validate_image(image: np.ndarray) -> None
Raises:
ValueError if image is invalid
Example:
from medtda.loaders import validate_image
try:
validate_image(image_array)
print("Image is valid")
except ValueError as e:
print(f"Invalid image: {e}")
validate_mask
- medtda.loaders.validate_mask(mask)[source]
Validate mask array.
- Parameters:
mask (numpy.ndarray) – Mask array to validate.
- Raises:
TypeError – If mask is not a numpy array.
ValueError – If mask has invalid dimensions or values.
- Return type:
Validate a mask array.
Signature:
def validate_mask(mask: np.ndarray) -> None
Raises:
ValueError if mask is invalid
Example:
from medtda.loaders import validate_mask
validate_mask(mask_array)
validate_compatibility
- medtda.loaders.validate_compatibility(image, mask)[source]
Check image-mask compatibility.
Ensures image and mask have the same shape.
- Parameters:
image (numpy.ndarray) – Image array.
mask (numpy.ndarray) – Mask array.
- Raises:
ValueError – If image and mask shapes don’t match.
- Return type:
Validate that image and mask are compatible.
Signature:
def validate_compatibility(
image: np.ndarray,
mask: np.ndarray
) -> None
Raises:
ValueError if image and mask are incompatible
Example:
from medtda.loaders import validate_compatibility
validate_compatibility(image, mask)
# Raises ValueError if shapes don't match
Complete Examples
Example 1: Basic Loading
from medtda.loaders import load_image, load_mask
# Load image and mask
image, img_meta = load_image('data/patient001.nii.gz')
mask, mask_meta = load_mask('data/patient001_mask.nii.gz')
print(f"Image shape: {image.shape}")
print(f"Image spacing: {img_meta.get('spacing')}")
print(f"Mask labels: {np.unique(mask)}")
Example 2: Loading with Validation
from medtda.loaders import (
load_image,
load_mask,
validate_compatibility
)
# Load
image, _ = load_image('scan.nii.gz')
mask, _ = load_mask('mask.nii.gz')
# Validate
try:
validate_compatibility(image, mask)
print("Image and mask are compatible")
except ValueError as e:
print(f"Error: {e}")
Example 3: Processing and Saving
from medtda import Preprocessor
from medtda.loaders import load_image, save_image
# Load
image, metadata = load_image('original.nii.gz')
# Process
preprocessor = Preprocessor(
normalize=True,
spacing=(1.0, 1.0, 1.0)
)
processed = preprocessor.preprocess(image)
# Save with metadata
save_image(
processed,
'processed.nii.gz',
metadata={'spacing': (1.0, 1.0, 1.0)}
)
Example 4: Batch Loading
from medtda.loaders import load_image
import glob
from pathlib import Path
# Load all NIFTI files
image_paths = glob.glob('data/*.nii.gz')
images = []
for path in image_paths:
image, metadata = load_image(path)
images.append({
'name': Path(path).stem,
'array': image,
'metadata': metadata
})
print(f"Loaded {len(images)} images")
Example 5: 2D Image Handling
from medtda.loaders import load_image, save_image
import numpy as np
# Load 2D images
xray, metadata = load_image('xray.png')
print(f"2D image shape: {xray.shape}")
# Process
normalized = (xray - xray.min()) / (xray.max() - xray.min())
# Save as different format
save_image(normalized, 'xray_processed.tiff')
Example 6: Multi-Label Mask
from medtda.loaders import load_mask
from medtda.utils import extract_label_from_mask
# Load multi-label mask
multi_mask, metadata = load_mask('organs.nii.gz')
# Check labels
labels = np.unique(multi_mask)
print(f"Available labels: {labels}")
# e.g., [0, 1, 2, 3] for background, liver, kidney, spleen
# Extract single label
liver_mask = extract_label_from_mask(multi_mask, label=1)
Example 7: Metadata Handling
from medtda.loaders import load_image, save_image
# Load with metadata
image, metadata = load_image('scan.nii.gz')
# Inspect metadata
print("Metadata:")
for key, value in metadata.items():
print(f" {key}: {value}")
# Modify metadata
metadata['spacing'] = (1.0, 1.0, 1.0) # Change to isotropic
# Save with modified metadata
save_image(image, 'scan_modified.nii.gz', metadata=metadata)
Supported Formats
3D Formats
NIFTI (.nii, .nii.gz)
Most common medical imaging format
Supports metadata (spacing, orientation)
Recommended for 3D volumes
image, meta = load_image('brain.nii.gz')
NRRD (.nrrd)
Nearly Raw Raster Data
Good metadata support
image, meta = load_image('volume.nrrd')
MetaImage (.mha, .mhd)
ITK format
Separate header and data files (.mhd + .raw)
image, meta = load_image('scan.mha')
2D Formats
PNG
Lossless compression
Good for masks and processed images
image, meta = load_image('slice.png')
TIFF
Supports 16-bit grayscale
Good for high dynamic range
image, meta = load_image('microscopy.tiff')
JPEG
Lossy compression
Not recommended for analysis (lossy)
image, meta = load_image('preview.jpg')
DICOM
DICOM (.dcm)
Medical imaging standard
Rich metadata
May require series loading
# Single DICOM file
image, meta = load_image('slice001.dcm')
# Note: For DICOM series, use specialized tools
Format Detection
Automatic Detection
Format is automatically detected from file extension:
# Automatically detects NIFTI
img, _ = load_image('scan.nii.gz')
# Automatically detects PNG
img, _ = load_image('image.png')
Troubleshooting
Common Issues
Issue: Shape mismatch between image and mask
# Check shapes before processing
image, _ = load_image('image.nii.gz')
mask, _ = load_image('mask.nii.gz')
if image.shape != mask.shape:
print(f"Shape mismatch: {image.shape} vs {mask.shape}")
Issue: Missing metadata
image, metadata = load_image('image.nii.gz')
# Provide default spacing if missing
spacing = metadata.get('spacing', (1.0, 1.0, 1.0))
Issue: Unsupported format
# Check file extension
from pathlib import Path
path = Path('image.xyz')
if path.suffix not in ['.nii', '.nii.gz', '.nrrd', '.png', '.tiff']:
print(f"Unsupported format: {path.suffix}")
Performance Tips
Use compressed NIFTI:
.nii.gz files are smaller and load quickly:
# Prefer this img, _ = load_image('scan.nii.gz')
Cache loaded images:
Avoid reloading the same file:
# Load once image, metadata = load_image('large_scan.nii.gz') # Reuse image array result1 = process1(image) result2 = process2(image)
Validate once:
Validate at load time, not during processing:
from medtda.loaders import load_image, validate_image image, _ = load_image('scan.nii.gz') validate_image(image) # Once only
See Also
Preprocessor - Image preprocessing
Utils - Image processing utilities
Preprocessing - Preprocessing guide
FeatureExtractor - Feature extraction