Fast, patch-based IHC whole-slide inference β powered by DeepLIIF.
From IHC glass slide to cell-counting CSVs, heatmaps, and visual overlays β in one command.
δΈζ Β· What's New Β· Quick Start Β· Docs Β· Benchmarks
- πΌοΈ MIRAX (.mrxs) support β tissue segmentation now suppresses black out-of-scan regions; thumbnails and overlays are cropped to the scanned bounds so tissue fills the frame.
- π Better thumbnail quality for bounded slides β
OpenSlideReaderexposesbounds;read_slide_thumbnailupscales before cropping when bounds are present. - π Renamed thumbnail output β WSI thumbnail is now saved as
wsi_thumbnail.jpginstead ofhe_thumbnail.jpg. - ποΈ IHC background tuning β
TissueSegmentergains ablack_v_threshparameter to filter dark scanner background in IHC mode.
- π Unified
ihcCLI β one command fortissue_seg,patch_infer, andinfer. - π§« IHC Tissue Segmentation β default
ihcmode optimized for immunohistochemistry backgrounds;hemode for H&E. - β‘ Scoring-only Fast Path β skip intermediate PIL images during WSI inference to lower memory and boost throughput.
- β¬οΈ Automatic Model Download β the DeepLIIF TorchScript model is downloaded from Zenodo the first time
model_diris omitted. - π§© Cross-chunk Batch Tiling β large slides are read in chunks and patches are batched across chunk boundaries for better GPU utilization.
ihcinfer is a lightweight Python library for batch immunohistochemistry (IHC) inference on SVS / KFB whole-slide images and PNG / JPEG patches. It reorganizes patch buffering, chunk tiling, tissue-mask pre-filtering, and a scoring-only fast path on top of DeepLIIF's TorchScript model, while exposing both a Python API (IHCAnalyzer) and a command-line tool (ihc).
| Feature | Description | |
|---|---|---|
| π¬ | Whole-slide image support | Native SVS / KFB reading via OpenSlide and custom readers. |
| π§© | Patch input | Batch inference on PNG / JPEG patches or directories. |
| β‘ | Batch GPU inference | Cross-chunk patch buffer improves GPU utilization on large slides. |
| π | Quantitative outputs | Per-patch total / positive cell counts and positive ratios as CSV + coordinates. |
| πΊοΈ | Visual outputs | Heatmaps, H&E thumbnails, overlays, region / patch samples. |
| π§ | Automatic model loading | DeepLIIF model auto-downloaded from Zenodo when model_dir is omitted. |
| π§« | Tissue segmentation | Standalone ihc / he tissue masks, no model required. |
| π | Dramatic speedups | Up to 14.79Γ faster than original DeepLIIF for the full GPU pipeline. |
π©Ί Pathologist / Researcher β Quantify a whole IHC slide
ihc infer \
--slide_path "path/to/CD3.svs" \
--output_dir ./ihc_outputs \
--gpu_ids 0 \
--batch_size 8Produces patch_scoring.csv, heatmap.jpg, and overlay.jpg for downstream statistical analysis.
𧬠Bioinformatician β Integrate IHC scoring into a pipeline
from ihcinfer import IHCAnalyzer
import pandas as pd
analyzer = IHCAnalyzer(gpu_ids=[0], batch_size=16)
result = analyzer.infer_wsi(
slide_path="path/to/slide.svs",
output_dir="./outputs",
)
df = pd.read_csv(result.csv_path)WSIResult exposes paths to the CSV, heatmap, thumbnail, overlay, and sample directories directly.
π» Developer β Embed tissue segmentation or patch inference
from ihcinfer import segment_tissue
mask = segment_tissue("slide.svs", mode="ihc")
print(mask.mask.shape)Patch-level workflow: ihc patch_infer --input patch.png --output_dir ./out.
π Offline / HPC User β Disable auto-download and use a local model
export IHCINFER_MODEL_DIR="/path/to/DeepLIIF_Latest_Model"
ihc infer --slide_path slide.svs --output_dir ./out --model_dir "$IHCINFER_MODEL_DIR"In Python, set auto_download=False.
| Platform | Python | Notes |
|---|---|---|
| Linux | 3.10+ | Primary development and test platform. |
| Windows | 3.10+ | OpenSlide binaries installed automatically via openslide-bin. |
| macOS | 3.10+ | Requires OpenSlide to be installed on the system. |
| Input type | Formats | Usage |
|---|---|---|
| Whole-slide images | SVS, KFB | ihc infer, ihc tissue_seg, IHCAnalyzer.infer_wsi() |
| Patch images | PNG, JPEG | ihc patch_infer, IHCAnalyzer.infer_patches() |
Model: DeepLIIF TorchScript model (~3 GB). It is downloaded automatically from Zenodo the first time model_dir is omitted, or you can point to a local copy.
# Install
pip install ihcinfer
# 1. Tissue segmentation (no model required)
ihc tissue_seg --input "slide.svs" --output_dir ./tissue_mask --overlay
# 2. Patch inference
ihc patch_infer --input patch.png --output_dir ./patch_outputs
# 3. Whole-slide IHC inference
ihc infer --slide_path slide.svs --output_dir ./ihc_outputs --gpu_ids 0π Prefer the Python API? Click to expand
from ihcinfer import IHCAnalyzer
analyzer = IHCAnalyzer(
model_dir="/path/to/DeepLIIF_Latest_Model", # omit to auto-download
gpu_ids=[0],
batch_size=16,
)
result = analyzer.infer_wsi(
slide_path="/path/to/slide.svs",
output_dir="/path/to/output",
)
print(result.csv_path)
print(result.heatmap_path)
print(f"Region samples: {len(result.region_sample_paths) // 2}")
print(f"Patch samples: {len(result.patch_sample_dirs)}")IHCAnalyzer is the unified entry point for most users:
from ihcinfer import IHCAnalyzer
analyzer = IHCAnalyzer(gpu_ids=[0], batch_size=16)
# Whole-slide inference
result = analyzer.infer_wsi("slide.svs", output_dir="./outputs")
# Patch inference
patch_result = analyzer.infer_patches(["p1.png", "p2.png"], output_dir="./patch_outputs")
# Tissue segmentation
mask = analyzer.segment_tissue("slide.svs", mode="ihc")| Metric | Original DeepLIIF | ihcinfer | Speedup |
|---|---|---|---|
| Full patch pipeline (CPU, 4 patches) | 28.54 s | 19.50 s | 1.46Γ |
| Inference only (GPU) | 1.75 s | 0.55 s | 3.17Γ |
| Full patch pipeline (GPU) | 10.21 s | 0.69 s | 14.79Γ |
| WSI end-to-end (1453 patches, GPU, estimated) | ~10 min | ~4 min | ~2.5β3Γ |
Test environment: 6Γ NVIDIA RTX 3090 / 24 GiB. Reproduction scripts are in benchmarks/.
Charts generated by
benchmarks/plot_benchmarks.pyfrom the table above.
graph LR
A[WSI: SVS / KFB] --> B[Tissue Segmentation<br/>ihc / he mode]
B --> C[Chunked Patch Tiler]
C --> D[DeepLIIF Batch Inference]
D --> E[Cell Scoring]
E --> F[CSV + Heatmap]
E --> G[H&E Thumbnail + Overlay]
E --> H[Region / Patch Samples]
| Resource | Link | Description |
|---|---|---|
| Example scripts | examples/ |
Patch inference, WSI inference, and tissue-segmentation examples |
| CLI details | examples/README.md |
ihc command and subcommand reference |
| Benchmarks | benchmarks/ |
Reproducible comparisons against original DeepLIIF |
ihc --help
# Subcommands
ihc tissue_seg --input <slide> --output_dir <dir> [--overlay] [--mode ihc|he]
ihc patch_infer --input <patch_or_dir> --output_dir <dir> [--model_dir <dir>]
ihc infer --slide_path <slide> --output_dir <dir> [--gpu_ids 0] [--batch_size 8]from ihcinfer.inference import PatchInference, RegionInference
from ihcinfer.models import DeepLIIFModel
from ihcinfer.prep import Tiler, TissueSegmenter, segment_tissue
from ihcinfer.readers import create_reader
from ihcinfer.scoring import compute_scoring, extract_cells
from ihcinfer.outputs import build_patch_output, save_patch_output, build_heatmapAll numbers can be reproduced with the scripts in benchmarks/:
# Patch-level comparison (original DeepLIIF repo must be on PYTHONPATH)
PYTHONPATH=/path/to/DeepLIIF uv run python benchmarks/bench_patch_vs_original.py --device cuda:0
# Region-level comparison
PYTHONPATH=/path/to/DeepLIIF uv run python benchmarks/bench_region_inference.py
# WSI 50-patch comparison
PYTHONPATH=/path/to/DeepLIIF uv run python benchmarks/bench_wsi_50_vs_original.py
# Full IHC WSI pipeline timing
uv run python examples/infer_ihc.py \
--slide_path /path/to/slide.svs \
--output_dir ./ihc_outputs \
--gpu_ids 0 --batch_size 8 \
--patch_size 512 --region_size 2048Issues and PRs are welcome.
This project is licensed under the MIT License.



