Fast patch-based immunohistochemistry (IHC) inference library for whole-slide images (SVS/KFB), powered by DeepLIIF
Project description
ihcinfer
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
📰 What's New
v0.2.1
- 🖼️ 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.
v0.2.0
- 🚀 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).
✨ Core Features
| 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. |
🧑🔬 What Can You Do With It?
🩺 Pathologist / Researcher — Quantify a whole IHC slide
ihc infer \
--slide_path "path/to/CD3.svs" \
--output_dir ./ihc_outputs \
--gpu_ids 0 \
--batch_size 8
Produces 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.
📋 Supported Platforms & Inputs
| 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.
⚡ 30-Second Quick Start
# 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)}")
🐍 Python API
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")
🚀 Why ihcinfer?
| 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.
🏗️ Pipeline Architecture
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]
📚 Documentation & Resources
| 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 |
🛠️ CLI Reference
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]
🔧 Advanced Usage
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_heatmap
📈 Benchmarks
All 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 2048
🤝 Contributing
Issues and PRs are welcome.
📄 License
This project is licensed under the MIT License.
Project details
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file ihcinfer-0.2.1.tar.gz.
File metadata
- Download URL: ihcinfer-0.2.1.tar.gz
- Upload date:
- Size: 54.7 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
ab43251189e59b684aa58dd177a2fa1c66e2204beae990525b56f0989b392458
|
|
| MD5 |
af7fe276ef5046ed95906bc32c9a6259
|
|
| BLAKE2b-256 |
9d70e3b1bc3583f664d1cee01b73cd29699c7a1aeaf9193df578cb7e320c2fac
|
Provenance
The following attestation bundles were made for ihcinfer-0.2.1.tar.gz:
Publisher:
publish.yml on yifanfeng97/ihcinfer
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
ihcinfer-0.2.1.tar.gz -
Subject digest:
ab43251189e59b684aa58dd177a2fa1c66e2204beae990525b56f0989b392458 - Sigstore transparency entry: 2096305579
- Sigstore integration time:
-
Permalink:
yifanfeng97/ihcinfer@f2ccd6c97f706cd44f48ab64afe98b856d4669da -
Branch / Tag:
refs/tags/v0.2.1 - Owner: https://github.com/yifanfeng97
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@f2ccd6c97f706cd44f48ab64afe98b856d4669da -
Trigger Event:
release
-
Statement type:
File details
Details for the file ihcinfer-0.2.1-py3-none-any.whl.
File metadata
- Download URL: ihcinfer-0.2.1-py3-none-any.whl
- Upload date:
- Size: 51.2 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
63d37d72c4cc23654c084ffe4561fa5fd234877cfb7dd40cd67fd934238e0f8d
|
|
| MD5 |
b70ec01482118323eeeccfd9ef6f9f95
|
|
| BLAKE2b-256 |
61d01b276c0095eedbc714512c7a5eb48ff47abae4ac2e0671f2d686b121345c
|
Provenance
The following attestation bundles were made for ihcinfer-0.2.1-py3-none-any.whl:
Publisher:
publish.yml on yifanfeng97/ihcinfer
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
ihcinfer-0.2.1-py3-none-any.whl -
Subject digest:
63d37d72c4cc23654c084ffe4561fa5fd234877cfb7dd40cd67fd934238e0f8d - Sigstore transparency entry: 2096305913
- Sigstore integration time:
-
Permalink:
yifanfeng97/ihcinfer@f2ccd6c97f706cd44f48ab64afe98b856d4669da -
Branch / Tag:
refs/tags/v0.2.1 - Owner: https://github.com/yifanfeng97
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@f2ccd6c97f706cd44f48ab64afe98b856d4669da -
Trigger Event:
release
-
Statement type: