Inspired by & reconstructed from this repository link
How to start? blog
Repository for normalizing whole slide images (WSI) patches.
- [10/2024] Thanks to Cédric Walker's torchvahadane! We have added GPU(Cuda) support for Vahadane method. We can now boost up stain normalization speed by 2x+.
- [04/2025] We have upload the PyPI package for this repository. You can directly install it by using pip and use it without clone the repository.
- Reinhard Reinhard, Erik, et al. "Color transfer between images." IEEE Computer graphics and applications 21.5 (2001): 34-41.
- Macenko Macenko, Marc, et al. "A method for normalizing histology slides for quantitative analysis." 2009 IEEE international symposium on biomedical imaging: from nano to macro. IEEE, 2009.
- Vahadane Vahadane, Abhishek, et al. "Structure-preserving color normalization and sparse stain separation for histological images." IEEE transactions on medical imaging 35.8 (2016): 1962-1971.
Install the package via PyPI:
pip install wsi-normalizerThen you can use it in your code:
import cv2
from wsi_normalizer import imread, MacenkoNormalizer # or ReinhardNormalizer, VahadaneNormalizer, TorchVahadaneNormalizer
macenko_normalizer = MacenkoNormalizer()
macenko_normalizer.fit(imread('TARGET_IMAGE.jpg'))
norm_img = macenko_normalizer.transform(imread('INPUT_IMAGE.jpg'))
cv2.imwrite('OUTPUT_IMAGE.jpg', cv2.cvtColor(norm_img, cv2.COLOR_RGB2BGR))- run
pip install -r requirements.txtfor installing dependencies.
if you need the GPU support for Vahadane method, you need to additionally install the pytorch-gpu, scipy, kornia (optional)
- make sure you have the following folder structure:
├── data
│ ├── slide_1
│ │ ├── patch_1.png
│ │ ├── patch_2.png
│ │ ├── ...
│ ├── slide_2
│ │ ├── patch_1.png
│ │ ├── patch_2.png
│ │ ├── ...
│ ├── ...
│ └── slide_n
│ ├── ...
│ └── patch_n.png
Note that png or jpg images are supported
- modify the following arguments:
<TARGET FOLDER> <OUTPUT FOLDER> <NORM METHOD> <TARGET IMAGE>, and run:
python main.py --target_dir <TARGET FOLDER> --output_dir <OUTPUT FOLDER> --method <NORM METHOD> --target_img <TARGET IMAGE>make sure the <NORM METHOD> is in reinhard, macenko, vahadane, vahadane-gpu
Please note that vahadane-gpu is more suitable for high resolution image normalization, e.g. 1024x1024. Considering the CPU-GPU data transfer cost.
-
each slide will be normalized and saved in the output folder with the same name as the original slide, with a suffix of
.jpg. -
I also provide a sample script and corresponding images in this repository, simply run:
python main.py --target_dir eg/origin --output_dir eg/norm --method vahadane-gpu --target_img eg/standard.jpghere, I use vahadane as norm method, and use standard.jpg as target image
The 3 methods' results are shown below:
| Original | Standard (target) | Reinhard | Macenko | Vahadane | Vahadane-GPU |
|---|---|---|---|---|---|
![]() |
![]() |
![]() |
![]() |
![]() |
![]() |
![]() |
![]() |
![]() |
![]() |
![]() |
![]() |










