from bioMONAI.core import cells3d
from bioMONAI.visualize import visualize_slicesTransforms
FunctionTransform
def FunctionTransform(
func, has_channels:bool=True, func_kwargs:VAR_KEYWORD
):
Generic MonaiTransform to apply any NumPy or SciPy function to an image. Works with CHW/CDHW arrays or BioImageBase.
MonaiTransform
def MonaiTransform(
monai_transform, # MONAI transform class (e.g., monai.transforms.GaussianSmooth)
has_channels:bool=True, # Whether numpy input already has a channel dimension
kwargs:VAR_KEYWORD
):
Generic MonaiTransform for MONAI transforms (non-dictionary versions).
This MonaiTransform allows MONAI transforms to be used within the BioImage transform pipeline while supporting both BioImageBase objects and NumPy arrays as inputs.
The MONAI transform is internally instantiated and applied to the input image after converting it to the appropriate tensor format.
RandMonaiTransform
def RandMonaiTransform(
monai_transform, # Deterministic MONAI transform class
prob:float=0.1, # Probability of applying transform
param_sampler:NoneType=None, # Function that returns sampled kwargs
has_channels:bool=True, kwargs:VAR_KEYWORD
):
Wrap a deterministic MONAI transform inside a fastai RandTransform.
Random parameters are sampled in before_call, then used to instantiate a deterministic MONAI transform.
ApplyTo
def ApplyTo(
tfm, idx:int=0
):
Apply a transform to a specific element of a tuple.
Args: tfm: the transform or callable to apply idx: index of the tuple element to modify (default 0)
Size & Sampling
Resample
def Resample(
sampling, # Sampling factor for isotropic resampling
has_channels:bool=True, # Indicates whether the input image has a channel dimension (only for numpy arrays)
kwargs:VAR_KEYWORD
):
A subclass of Spacing that handles image resampling based on specified sampling factors or voxel dimensions.
The Resample class inherits from Spacing and provides a flexible way to adjust the spacing (voxel size) of images by specifying either a sampling factor or explicitly providing new voxel dimensions.
torchTensor(cells3d()[:,0])
Tensor2BioImage()(torchTensor(cells3d()[:,0]))img = BioImageStack(torchTensor(cells3d()[:,0]))
visualize_slices(img, showlines=False)
img2 = Resample(4)(img)
print(type(img2))
visualize_slices(img2, showlines=False)
img2 = Resample(4)(cells3d()[:,0])
print(type(img2))
visualize_slices(img2, showlines=False)Resize
def Resize(
size:NoneType=None, # Target dimensions for resizing (height, width). If its length is smaller than the spatial dimensions, values will be repeated. If an int is provided, it will be broadcast to all spatial dimensions.
kwargs:VAR_KEYWORD
):
A subclass of Reshape that handles image resizing based on specified target dimensions.
The Resize class inherits from Reshape and provides a flexible way to adjust the size of images by specifying either a target size or scaling factors.
print(img.size())
visualize_slices(img, showlines=False)
img2 = Resize(50)(img)
print(img2.size())
visualize_slices(img2, showlines=False)CropND
def CropND(
slices:list, # List of slice objects or tuples (start, end) for each dimension
dims:list=None, # List of dimensions to apply the slices. If None, slices are applied to all dimensions.
):
Crops an ND tensor along a specified dimension.
This transform crops an ND tensor along specified dimensions, which could be a channel or spatial dimension.
# Define the slices for cropping
slices = [(30, 50)]
# Create an instance of CropND
crop_transform = CropND(slices=slices)
img3 = crop_transform(img)
print(img3.size())
visualize_slices(img3, showlines=False)# Define the slices for cropping
slices = [(30, 50), (0, 40)]
dims = [0, 2]
# Create an instance of CropND
crop_transform = CropND(slices=slices, dims=dims)
img3 = crop_transform(img)
print(img3.size())
visualize_slices(img3, showlines=False)Noise
RandCameraNoise
def RandCameraNoise(
p:float=1.0, # Probability of applying Transform
damp:float=0.01, # Dampening factor to prevent saturation when adding noise
qe:float=0.7, # Quantum efficiency of the camera (0 to 1).
gain:int=2, # Camera gain factor. If an array, it should be broadcastable with input_image shape.
offset:int=100, # Camera offset in ADU. If an array, it should be broadcastable with input_image shape.
exp_time:float=0.1, # Exposure time in seconds.
dark_current:float=0.6, # Dark current per pixel in electrons/second.
readout:float=1.5, # Readout noise standard deviation in electrons.
bitdepth:int=16, # Bit depth of the camera output.
seed:int=42, # Seed for random number generator for reproducibility.
simulation:bool=False, # If True, assumes input_image is already in units of photons and does not convert from electrons.
camera:str='cmos', # Specifies the type of camera ('cmos' or any other). Used to add CMOS fixed pattern noise if 'cmos' is specified.
gain_variance:float=0.1, # Variance for the gain noise in CMOS cameras. Only applicable if camera type is 'cmos'.
offset_variance:int=5, # Variance for the offset noise in CMOS cameras. Only applicable if camera type is 'cmos'.
):
Simulates camera noise by adding Poisson shot noise, dark current noise, and optionally CMOS fixed pattern noise.
Returns: numpy.ndarray: The noisy image as a NumPy array with dimensions of input_image.
from bioMONAI.visualize import plot_imageimg3 = img[30]# Original clean image
plot_image(img3)# Noisy image simulating a CMOS camera
plot_image(RandCameraNoise(camera = 'cmos').encodes(img3))# Noisy image simulating a CCD camera
plot_image(RandCameraNoise(camera = 'ccd', readout=2).encodes(img3))Blur
def Blur(
sigma:float=1.0, ksize:int=5, prob:float=0.5
):
Apply Gaussian blur to the image.
# Generate a random NumPy array
random_array = np.random.rand(64, 64)
# Apply Blur transform to the image
blur_transform = Blur(ksize=15, prob=1)
blurred_nparray = blur_transform(random_array)
# plot the original image
plot_image(random_array)
# Plot the blurred image
plot_image(blurred_nparray)# Apply Blur transform to the image
blur_transform = Blur(sigma=5, prob=1.0)
blurred_img = blur_transform(img)
# plot the original image
plot_image(img)
# Plot the blurred image
plot_image(blurred_img)SavitzkyGolaySmooth
def SavitzkyGolaySmooth(
window_length, order, axis:int=1, mode:str='zeros', kwargs:VAR_KEYWORD
):
Smooth data using a Savitzky-Golay filter.
MedianSmooth
def MedianSmooth(
radius:int=1, kwargs:VAR_KEYWORD
):
Apply median filtering to the input image.
GaussianSmooth
def GaussianSmooth(
sigma:float=1.0, approx:str='erf', kwargs:VAR_KEYWORD
):
Apply Gaussian smoothing to the input image.
GaussianSharpen
def GaussianSharpen(
sigma1:float=3.0, sigma2:float=1.0, alpha:float=30.0, approx:str='erf', kwargs:VAR_KEYWORD
):
Sharpen images using Gaussian filtering.
RandGaussianSmooth
def RandGaussianSmooth(
sigma_x:tuple=(0.5, 1.5), sigma_y:NoneType=None, sigma_z:NoneType=None, prob:float=0.1, approx:str='erf',
has_channels:bool=True
):
Apply Gaussian smoothing with randomly sampled sigma.
RandGaussianSharpen
def RandGaussianSharpen(
sigma1:tuple=(0.5, 1.0), sigma2:tuple=(0.5, 1.0), alpha:tuple=(10.0, 30.0), prob:float=0.1, approx:str='erf',
has_channels:bool=True
):
Randomly sharpen image using Gaussian kernels.
RandGaussianNoise
def RandGaussianNoise(
mean:float=0.0, std:float=0.1, prob:float=0.1, dtype:type=float32, has_channels:bool=True
):
Add Gaussian noise to image.
Intensity Normalization
ScaleImage
def ScaleImage(
x, # The input image to scale.
min:float=0.0, # The minimum intensity value.
max:float=1.0, # The maximum intensity value.
axis:NoneType=None, # The axis or axes along which to compute the minimum and maximum values.
eps:float=1e-20, # A small value to prevent division by zero.
dtype:type=float32, # The data type to use for the output image.
):
Image normalization.
ScaleImagePercentiles
def ScaleImagePercentiles(
x, # The input image to scale.
pmin:int=3, # The minimum percentile value.
pmax:float=99.8, # The maximum percentile value.
axis:NoneType=None, # The axis or axes along which to compute the minimum and maximum values.
clip:bool=True, # If True, clips the output values to the specified range.
b_min:float=0.0, # The minimum intensity value.
b_max:float=1.0, # The maximum intensity value.
eps:float=1e-20, # A small value to prevent division by zero.
dtype:type=float32, # The data type to use for the output image.
):
Percentile-based image normalization.
ScaleImageVariance
def ScaleImageVariance(
target_variance:float=1.0, # The desired variance for the scaled intensities.
ndim:int=2, # Number of spatial dimensions in the image.
):
Scales the intensity variance of an ND image to a target value.
# Example usage with a random tensor of shape (1, 3, 256, 256)
rand_tensor = BioImageBase(torch.rand(1, 3, 256, 256))
transform = ScaleImageVariance(ndim=4)
# Apply the transform to the tensor
scaled_tensor = transform(rand_tensor)
print('Original Tensor Variance:', rand_tensor.var().item())
print('Scaled Tensor Variance:', scaled_tensor.var().item())ScaleIntensityRangePercentiles
def ScaleIntensityRangePercentiles(
lower, upper, b_min, b_max, clip:bool=False, relative:bool=False, channel_wise:bool=False, dtype:type=float32,
kwargs:VAR_KEYWORD
):
Scale intensity values based on image percentiles.
The transform maps the intensity range defined by two percentiles to a target range.
ScaleIntensityRange
def ScaleIntensityRange(
a_min, a_max, b_min:NoneType=None, b_max:NoneType=None, clip:bool=False, dtype:type=float32, kwargs:VAR_KEYWORD
):
Linearly rescale intensities from one range to another.
ScaleIntensityFixedMean
def ScaleIntensityFixedMean(
factor:int=0, preserve_range:bool=False, fixed_mean:bool=True, channel_wise:bool=False, dtype:type=float32,
kwargs:VAR_KEYWORD
):
Scale intensity while preserving the original mean.
After scaling intensities, the transform shifts the output so that the mean intensity remains equal to the input mean.
ScaleIntensity
def ScaleIntensity(
minv:float=0.0, maxv:float=1.0, factor:NoneType=None, channel_wise:bool=False, dtype:type=float32,
kwargs:VAR_KEYWORD
):
Scale image intensity to a specified range or by a multiplicative factor.
HistogramNormalize
def HistogramNormalize(
num_bins:int=256, min:int=0, max:int=255, mask:NoneType=None, dtype:type=float32, kwargs:VAR_KEYWORD
):
Normalize image intensity using histogram equalization.
NormalizeIntensity
def NormalizeIntensity(
subtrahend:NoneType=None, divisor:NoneType=None, nonzero:bool=False, channel_wise:bool=False, dtype:type=float32,
kwargs:VAR_KEYWORD
):
Normalize image intensity using mean and standard deviation.
The transform performs: (img - subtrahend) / divisor
Label Mapping
RelabelInstances
def RelabelInstances(
background:int=0, # Label considered background
dtype:type=int32, # Output dtype
):
Remap instance mask labels to consecutive integers.
Example: [0, 1, 3, 7, 18] → [0, 1, 2, 3, 4]
InstanceToMaskAndDistance
def InstanceToMaskAndDistance(
has_channels:bool=True, # If False, adds channel dim
normalize:bool=True, # Normalize distance map per instance
):
Converts a single-channel instance segmentation map (CHW or CDHW) into a 2-channel image:
Channel 0: Binary mask (instances > 0) Channel 1: Distance transform (inside objects)
md = InstanceToMaskAndDistance()(np.random.rand(1, 33, 90, 90))
test_eq(md.shape, (2, 33, 90, 90))ComputeHoVerMaps
def ComputeHoVerMaps(
dtype:str='float32', kwargs:VAR_KEYWORD
):
Compute HoVer maps (horizontal and vertical distance maps) from instance masks.
These maps are commonly used in HoVer-Net based nucleus segmentation.
Thresholding / Masking
ForegroundMask
def ForegroundMask(
threshold:str='otsu', hsv_threshold:NoneType=None, invert:bool=False, kwargs:VAR_KEYWORD
):
Generate a binary foreground mask based on image intensity.
MaskIntensity
def MaskIntensity(
mask_data:NoneType=None, select_fn:NoneType=None, kwargs:VAR_KEYWORD
):
Mask intensity values using a binary mask.
Pixels outside the mask are set to zero.
ThresholdIntensity
def ThresholdIntensity(
threshold, above:bool=True, cval:float=0.0, kwargs:VAR_KEYWORD
):
Filter image intensities using a threshold.
Values above or below the threshold are replaced with a constant value.
Color space
RGB2HED
def RGB2HED(
enc:NoneType=None, dec:NoneType=None, split_idx:NoneType=None, order:NoneType=None
):
Convert RGB images to HED color space.
HED2RGB
def HED2RGB(
enc:NoneType=None, dec:NoneType=None, split_idx:NoneType=None, order:NoneType=None
):
Convert HED images back to RGB color space.
Data Augmentation
RandCrop2D
def RandCrop2D(
size:int | tuple, # Size to crop to, duplicated if one value is specified
lazy:bool=False, # a flag to indicate whether this transform should execute lazily or not. Defaults to False
kwargs:VAR_KEYWORD
):
Randomly crops a 2D image to a specified size.
This transform randomly crops a 2D image to a specified size during training and performs a center crop during validation.
RandCropND
def RandCropND(
size:int | tuple, # Size to crop to, duplicated if one value is specified
lazy:bool=False, # a flag to indicate whether this transform should execute lazily or not. Defaults to False
kwargs:VAR_KEYWORD
):
Randomly crops an ND image to a specified size.
This transform randomly crops an ND image to a specified size during training and performs a center crop during validation. It supports both 2D and 3D images and videos, assuming the first dimension is the batch dimension.
# Define a random tensor
orig_size = (65, 65)
rand_tensor = BioImageBase(torch.rand(8, *orig_size))
for i in range(100):
test_eq((8,64,64),RandCropND((64,64))(rand_tensor).shape)RandFlip
def RandFlip(
prob:float=0.1, # Probability of flipping
spatial_axis:NoneType=None, # Axes to flip. Default is None (random selection)
ndim:int=2, # Number of spatial dimensions
lazy:bool=False, # Flag for lazy execution (for BioImageBase)
kwargs:VAR_KEYWORD
):
Randomly flips an ND image over a specified axis. Works with both NumPy arrays and BioImageBase objects.
image = np.random.rand(1, 3, 3)
flip_transform = RandFlip(prob=1., ndim=2, spatial_axis=1)
flipped_image = flip_transform(image)
print('original:\n', image)
print('flipped:\n', flipped_image)
test_eq(image[0,0,0], flipped_image[0,2,0]) # Check if the image is flipped correctly# Define a random tensor
orig_size = (1,4,4)
rand_tensor = BioImageBase(torch.rand(*orig_size))
print('orig tensor: ', rand_tensor, '\n')
for i in range(3):
print(RandFlip(prob=.75, spatial_axis=None)(rand_tensor))RandRot90
def RandRot90(
prob:float=0.1, # Probability of rotating
k:NoneType=None, # Number of times to rotate by 90 degrees. If k is None, it will be set randomly in `before_call`.
max_k:int=3, # Max number of times to rotate by 90 degrees
spatial_axes:tuple=(0, 1), # Spatial axes that define the plane around which to rotate. Default: (0, 1), this are the first two axis in spatial dimensions.
ndim:int=2, # Number of spatial dimensions
lazy:bool=False, # Flag to indicate whether this transform should execute lazily or not. Defaults to False
kwargs:VAR_KEYWORD
):
Randomly rotate an ND image by 90 degrees in the plane specified by axes.
# Define a random tensor
orig_size = (1,4,4)
rand_tensor = BioImageBase(torch.rand(*orig_size))
print('orig tensor: ', rand_tensor, '\n')
for i in range(3):
print(RandRot90(prob=1, k=i+1)(rand_tensor))RandRotate
def RandRotate(
prob:float=0.1, # Probability of rotating
range_x:NoneType=None, range_y:NoneType=None, range_z:NoneType=None, ndim:int=2, has_channels:bool=True,
keep_size:bool=True, mode:GridSampleMode=bilinear, padding_mode:GridSamplePadMode=border,
align_corners:bool=False, dtype:dtype=torch.float32,
lazy:bool=False, # Flag to indicate whether this transform should execute lazily or not. Defaults to False
kwargs:VAR_KEYWORD
):
Randomly rotate the input arrays.
print('orig tensor: ', rand_tensor, '\n')
for i in range(3):
print(RandRotate(prob=1, range_x=1)(rand_tensor))RandZoom
def RandZoom(
prob:float=0.1, # Probability of the transform
min_zoom:float=0.9, max_zoom:float=1.1, has_channels:bool=True, keep_size:bool=True, mode:InterpolateMode=area,
padding_mode:NumpyPadMode=edge, align_corners:NoneType=None, dtype:dtype=torch.float32,
lazy:bool=False, # Flag to indicate whether this transform should execute lazily or not. Defaults to False
kwargs:VAR_KEYWORD
):
Randomly zoom the input arrays with given probability within given zoom range.
print('orig tensor: ', rand_tensor, '\n')
for i in range(3):
print(RandZoom(prob=1)(rand_tensor))Intensity Shifting
StdShiftIntensity
def StdShiftIntensity(
factor, nonzero:bool=False, channel_wise:bool=False, dtype:type=float32, kwargs:VAR_KEYWORD
):
Shift intensity values using the image standard deviation.
The transform modifies intensity values using: v = v + factor * std(v)
ShiftIntensity
def ShiftIntensity(
offset, safe:bool=False, kwargs:VAR_KEYWORD
):
Shift the intensity values of the entire image by a constant offset.
This transform uniformly adds an offset to all pixel/voxel values.
RandStdShiftIntensity
def RandStdShiftIntensity(
factors, prob:float=0.1, nonzero:bool=False, channel_wise:bool=False, has_channels:bool=True
):
Randomly shift intensity by a factor of the image standard deviation.
RandShiftIntensity
def RandShiftIntensity(
offsets, prob:float=0.1, safe:bool=False, has_channels:bool=True
):
Randomly shift image intensity.
Equivalent to MONAI RandShiftIntensity but uses the deterministic ShiftIntensity transform internally.
Contrast Adjustment
AdjustContrast
def AdjustContrast(
gamma, invert_image:bool=False, retain_stats:bool=False, kwargs:VAR_KEYWORD
):
Adjust image contrast using gamma transformation.
Each pixel intensity is transformed using a gamma function.
RandAdjustContrast
def RandAdjustContrast(
gamma, prob:float=0.1, invert_image:bool=False, retain_stats:bool=False, has_channels:bool=True
):
Randomly adjust image contrast using gamma correction.