AlbumentationsExplore
DocumentationExploreAdoptionPricingBlog
GitHub

HEStain

Targets:
image
volume
Image Types:uint8, float32

Perturb hematoxylin and eosin concentrations in H&E histology images to simulate stain variation across laboratories, scanners, and protocols.

Use this transform to train pathology models against expected staining variation. It converts RGB values to optical density, separates hematoxylin and eosin with the selected stain basis, perturbs both concentrations, and reconstructs the RGB image.

Arguments
method
preset | random_preset | vahadane | macenko | custom
random_preset

Selects the stain basis:

  • "preset": Use the matrix named by preset.
  • "random_preset": Select one of the eight preset matrices for each call.
  • "vahadane": Extract the matrix from the input with the Vahadane method.
  • "macenko": Extract the matrix from the input with the Macenko method.
  • "custom": Use the fixed matrix supplied through stain_matrix. Default: "random_preset".
preset
ruifrok | macenko | standard | high_contrast | h_heavy | e_heavy | dark | light |

Preset stain matrix used when method="preset":

  • "ruifrok": Standard reference from Ruifrok and Johnston.
  • "macenko": Reference from the Macenko method.
  • "standard": Typical bright-field microscopy.
  • "high_contrast": Enhanced contrast.
  • "h_heavy": Hematoxylin-dominant staining.
  • "e_heavy": Eosin-dominant staining.
  • "dark": Darker staining.
  • "light": Lighter staining. When None with method="preset", "standard" is used. Default: None.
intensity_scale_range
tuple[float, float]
[0.7, 1.3]

Non-negative range for the multiplicative concentration factor sampled independently for hematoxylin and eosin. For example, (0.7, 1.3) varies each concentration from 70% to 130%. Default: (0.7, 1.3).

intensity_shift_range
tuple[float, float]
[-0.2, 0.2]

Range within [-1.0, 1.0] for the additive concentration shift sampled independently for hematoxylin and eosin. Default: (-0.2, 0.2).

augment_background
bool
false

Whether to perturb background pixels along with tissue pixels. Default: False.

p
float
0.5

Probability of applying the transform. Default: 0.5.

stain_matrix
ndarray | None

Fixed H&E stain basis used when method="custom". The matrix must have shape (2, 3): row 0 is the hematoxylin RGB optical-density vector and row 1 is the eosin vector. Both rows must contain finite values, be non-zero, and be linearly independent. The transform copies the matrix as float32 and uses its values without row normalization. Default: None.

Examples
>>> import numpy as np
>>> import albumentations as A
>>>
>>> # Create a sample H&E stained histopathology image
>>> # For real use cases, load an actual H&E stained image
>>> image = np.zeros((300, 300, 3), dtype=np.uint8)
>>> # Simulate tissue regions with different staining patterns
>>> image[50:150, 50:150] = np.array([120, 140, 180], dtype=np.uint8)  # Hematoxylin-rich region
>>> image[150:250, 150:250] = np.array([140, 160, 120], dtype=np.uint8)  # Eosin-rich region
>>>
>>> # Example 1: Using a custom stain matrix calibrated for an acquisition pipeline
>>> stain_matrix = np.array(
...     [
...         [0.71, 0.65, 0.27],  # Hematoxylin
...         [0.18, 0.91, 0.37],  # Eosin
...     ],
...     dtype=np.float32,
... )
>>> transform = A.HEStain(
...     method="custom",
...     stain_matrix=stain_matrix,
...     intensity_scale_range=(0.8, 1.2),
...     intensity_shift_range=(-0.1, 0.1),
...     p=1.0,
... )
>>> transformed_image = transform(image=image)["image"]
>>>
>>> # Example 2: Using a specific preset stain matrix
>>> transform = A.HEStain(
...     method="preset",
...     preset="standard",
...     intensity_scale_range=(0.8, 1.2),
...     intensity_shift_range=(-0.1, 0.1),
...     augment_background=False,
...     p=1.0,
... )
>>> transformed_image = transform(image=image)["image"]
>>>
>>> # Example 3: Using random preset selection
>>> transform = A.HEStain(
...     method="random_preset",
...     intensity_scale_range=(0.7, 1.3),
...     intensity_shift_range=(-0.15, 0.15),
...     p=1.0,
... )
>>> transformed_image = transform(image=image)["image"]
>>>
>>> # Example 4: Using Vahadane extraction (requires an H&E stained input)
>>> transform = A.HEStain(
...     method="vahadane",
...     intensity_scale_range=(0.7, 1.3),
...     p=1.0,
... )
>>> transformed_image = transform(image=image)["image"]
>>>
>>> # Example 5: Using Macenko extraction (requires an H&E stained input)
>>> transform = A.HEStain(
...     method="macenko",
...     intensity_scale_range=(0.7, 1.3),
...     intensity_shift_range=(-0.2, 0.2),
...     p=1.0,
... )
>>> transformed_image = transform(image=image)["image"]
>>>
>>> # Example 6: Combining stain and brightness variation in one pipeline
>>> transform = A.Compose([
...     A.HEStain(method="preset", preset="high_contrast", p=1.0),
...     A.RandomBrightnessContrast(p=0.5),
... ])
>>> transformed_image = transform(image=image)["image"]
Notes
  • Let M be the (2, 3) stain matrix and C the per-pixel stain concentrations. The transform solves OD ~= C @ M, samples scale and shift for each stain, then reconstructs RGB = exp(-(C * scale + shift) @ M).
  • A custom matrix is fixed for the lifetime of the transform. Per-image callable extraction is not supported.
References
  • [{'description': 'A. C. Ruifrok and D. A. Johnston, "Quantification of histochemical"', 'source': 'Analytical and quantitative cytology and histology, 2001.'}, {'description': 'M. Macenko et al., "A method for normalizing histology slides for', 'source': '2009 IEEE International Symposium on quantitative analysis," 2009 IEEE International Symposium on Biomedical Imaging, 2009.'}]