mcpField
H
histolab-wsi-processing

histolab-wsi-processing

github.com/jaechang-hits数据与数据库38467 次安装6 天前更新
代码仓库

关于 histolab-wsi-processing

histolab-wsi-processing 是面向计算病理研究者的 Python 全切片图像处理库,支持组织检测、切片提取与预处理,并可按质量对图块评分。

主要功能

  1. 01组织区域检测与掩膜
  2. 02随机、网格和评分式切片
  3. 03可组合的图像与形态学滤镜
  4. 04按细胞核密度或细胞性评分
  5. 05切片、掩膜和图块可视化

适用场景

  1. 01为模型训练准备图块数据集
  2. 02抽取组织区域供切片检查
  3. 03去除切片背景和伪影
  4. 04比较多个切片集合的图块质量

安装

复制下面的命令,在终端中运行。

$npx skills add https://github.com/jaechang-hits/sciagent-skills --skill histolab-wsi-processing

安装后在 Claude Code 中输入/histolab-wsi-processing确认已加载。

包含的文件

除 SKILL.md 外,安装时一起下载的参考资料和脚本。

references/
filters_preprocessing.md
tile_extraction.md
visualization_slides.md

详细介绍

Histolab WSI 处理

概述

Histolab 是一个用于数字病理学全切片图像(WSI)处理的 Python 库。它可自动检测组织,使用多种策略从十亿像素图像中提取有信息量的图块,并提供可组合的预处理过滤器流水线。该库通过 OpenSlide 处理 SVS、TIFF、NDPI 等 WSI 格式。

适用场景

  • 从全切片图像中提取图块,用于深度学习模型训练
  • 检测组织区域,并过滤组织病理切片中的背景和伪影
  • 为 H&E 或 IHC 染色组织切片构建预处理流水线
  • 创建按细胞核密度或细胞密度排序、基于质量的图块数据集
  • 使用一致的参数,跨多个切片批量提取图块
  • 在计算病理学工作流开始前评估切片质量和组织覆盖率
  • 如果只需访问原始切片而不提取图块,请直接使用 openslide-python
  • 对于复杂的多重成像或空间蛋白质组学流水线,请改用 pathml

前置条件

  • Python 包:histolab(包含 OpenSlide Python 绑定)
  • 系统依赖项:必须单独安装 OpenSlide C 库
  • 支持的格式:SVS、TIFF、NDPI、VMS、SCN、MRXS(通过 OpenSlide)
# macOS
brew install openslide
pip install histolab

# Ubuntu/Debian
sudo apt-get install openslide-tools
pip install histolab

快速入门

from histolab.slide import Slide
from histolab.tiler import RandomTiler

# Load slide
slide = Slide("slide.svs", processed_path="output/")
print(f"Dimensions: {slide.dimensions}, Levels: {slide.levels}")

# Configure tiler
tiler = RandomTiler(
    tile_size=(512, 512), n_tiles=100, level=0, seed=42,
    check_tissue=True, tissue_percent=80.0
)

# Preview and extract
tiler.locate_tiles(slide, n_tiles=20)
tiler.extract(slide)

核心 API

模块 1:切片管理

Slide 类是加载和检查 WSI 文件的主要接口。

from histolab.slide import Slide
from histolab.data import prostate_tissue

# Load from built-in sample data (prostate, ovarian, breast, heart, kidney)
prostate_svs, prostate_path = prostate_tissue()
slide = Slide(prostate_path, processed_path="output/")

# Inspect properties
print(f"Dimensions: {slide.dimensions}")       # (width, height) at level 0
print(f"Levels: {slide.levels}")               # Number of pyramid levels
print(f"Level dims: {slide.level_dimensions}") # Dimensions per level
print(f"Magnification: {slide.properties.get('openslide.objective-power', 'N/A')}")
print(f"MPP-X: {slide.properties.get('openslide.mpp-x', 'N/A')}")

# Thumbnail and scaled image
slide.save_thumbnail()  # Saves to processed_path
scaled = slide.scaled_image(scale_factor=32)

# Extract region at specific coordinates
region = slide.extract_region(location=(1000, 2000), size=(512, 512), level=0)
模块 2:组织检测

掩码类用于识别组织区域,并在提取图块时过滤背景。

from histolab.masks import TissueMask, BiggestTissueBoxMask, BinaryMask
import numpy as np

# TissueMask: segments ALL tissue regions (multiple sections)
tissue_mask = TissueMask()
mask_array = tissue_mask(slide)  # Binary NumPy array: True=tissue, False=background
print(f"Tissue coverage: {mask_array.sum() / mask_array.size * 100:.1f}%")

# BiggestTissueBoxMask: bounding box of largest tissue region (default)
biggest_mask = BiggestTissueBoxMask()

# Visualize mask on slide thumbnail
slide.locate_mask(tissue_mask)

# Custom mask via BinaryMask subclass
class RectangularROI(BinaryMask):
    def __init__(self, x, y, w, h):
        self.x, self.y, self.w, self.h = x, y, w, h

    def _mask(self, slide):
        thumb = slide.thumbnail
        mask = np.zeros(thumb.shape[:2], dtype=bool)
        mask[self.y:self.y+self.h, self.x:self.x+self.w] = True
        return mask
模块 3:图块提取

提供三种图块提取策略:随机采样、网格覆盖和基于评分的选择。

from histolab.tiler import RandomTiler, GridTiler, ScoreTiler
from histolab.scorer import NucleiScorer
from histolab.masks import TissueMask

# RandomTiler: fixed number of randomly positioned tiles
random_tiler = RandomTiler(
    tile_size=(512, 512), n_tiles=100, level=0,
    seed=42, check_tissue=True, tissue_percent=80.0
)
random_tiler.locate_tiles(slide, n_tiles=20)  # Preview first
random_tiler.extract(slide)

# GridTiler: systematic grid coverage
grid_tiler = GridTiler(
    tile_size=(512, 512), level=0,
    pixel_overlap=0, check_tissue=True, tissue_percent=70.0
)
grid_tiler.extract(slide, extraction_mask=TissueMask())

# ScoreTiler: top-ranked tiles by scoring function
score_tiler = ScoreTiler(
    tile_size=(512, 512), n_tiles=50, level=0,
    scorer=NucleiScorer(), check_tissue=True
)
score_tiler.extract(slide, report_path="tiles_report.csv")
# Report CSV: tile_name, x_coord, y_coord, level, score, tissue_percent
模块 4:过滤器和预处理

用于组织检测和预处理的可组合图像过滤器与形态学过滤器。

from histolab.filters.image_filters import (
    RgbToGrayscale, RgbToHsv, RgbToHed,
    OtsuThreshold, AdaptiveThreshold,
    StretchContrast, HistogramEqualization, Invert
)
from histolab.filters.morphological_filters import (
    BinaryDilation, BinaryErosion, BinaryOpening, BinaryClosing,
    RemoveSmallObjects, RemoveSmallHoles
)
from histolab.filters.compositions import Compose

# Standard tissue detection pipeline
tissue_pipeline = Compose([
    RgbToGrayscale(),
    OtsuThreshold(),
    BinaryDilation(disk_size=5),
    RemoveSmallHoles(area_threshold=1000),
    RemoveSmallObjects(area_threshold=500)
])

# Use custom pipeline with TissueMask
from histolab.masks import TissueMask
custom_mask = TissueMask(filters=tissue_pipeline)

# Stain deconvolution (H&E)
hed_filter = RgbToHed()  # Hematoxylin-Eosin-DAB separation
# Apply filters to individual tiles
from histolab.tile import Tile

filter_chain = Compose([RgbToGrayscale(), StretchContrast()])
filtered_tile = tile.apply_filters(filter_chain)

# Lambda for custom inline filters
from histolab.filters.image_filters import Lambda
import numpy as np

brightness = Lambda(lambda img: np.clip(img * 1.2, 0, 255).astype(np.uint8))
red_channel = Lambda(lambda img: img[:, :, 0])
模块 5:评分

评分器根据图块的组织内容质量对其排序,以供 ScoreTiler 使用。

from histolab.scorer import NucleiScorer, CellularityScorer, Scorer
import numpy as np

# Built-in scorers
nuclei = NucleiScorer()       # Scores by nuclei density (grayscale threshold + count)
cellularity = CellularityScorer()  # Scores by overall cellular content

# Custom scorer
class ColorVarianceScorer(Scorer):
    def __call__(self, tile):
        """Score tiles by color variance (higher = more informative)."""
        tile_array = np.array(tile.image)
        return np.var(tile_array, axis=(0, 1)).sum()

score_tiler = ScoreTiler(
    tile_size=(512, 512), n_tiles=30,
    scorer=ColorVarianceScorer()
)
模块 6:可视化

用于检查切片、掩码和图块的内置方法及 matplotlib 用法示例。

import matplotlib.pyplot as plt
from histolab.masks import TissueMask

# Built-in: mask overlay on slide thumbnail
slide.locate_mask(TissueMask())

# Built-in: tile location preview
tiler.locate_tiles(slide, n_tiles=20)

# Manual side-by-side: slide vs mask
mask = TissueMask()
mask_array = mask(slide)
fig, axes = plt.subplots(1, 2, figsize=(15, 7))
axes[0].imshow(slide.thumbnail); axes[0].set_title("Slide"); axes[0].axis('off')
axes[1].imshow(mask_array, cmap='gray'); axes[1].set_title("Mask"); axes[1].axis('off')
plt.tight_layout()
plt.show()

# Display extracted tiles in grid
from pathlib import Path
from PIL import Image
tile_paths = list(Path("output/tiles/").glob("*.png"))[:16]
fig, axes = plt.subplots(4, 4, figsize=(12, 12))
for idx, tp in enumerate(axes.ravel()):
    if idx < len(tile_paths):
        tp.imshow(Image.open(tile_paths[idx]))
        tp.set_title(tile_paths[idx].stem, fontsize=8)
    tp.axis('off')
plt.tight_layout()
plt.show()

核心概念

WSI 金字塔层级

全切片图像采用包含多个分辨率层级的金字塔结构。第 0 层分辨率最高(原生扫描分辨率)。更高层级的分辨率逐级降低,以便更快地访问图像。

for level in range(slide.levels):
    dims = slide.level_dimensions[level]
    downsample = slide.level_downsamples[level]
    print(f"Level {level}: {dims}, downsample: {downsample:.0f}x")
# Level 0: (98304, 221184), downsample: 1x
# Level 1: (24576, 55296), downsample: 4x
过滤器组合模式

过滤器旨在通过 Compose 链式组合。一个过滤器的输出将成为下一个过滤器的输入。图像过滤器处理 RGB/灰度数组;形态学过滤器处理二值数组。顺序很重要:在应用后续过滤器之前,务必先转换为预期的输入类型。

掩码与图块提取器的集成

所有图块提取器都接受 extraction_mask 参数。默认值为 BiggestTissueBoxMask()。对于包含多个组织切片的切片,可将其替换为 TissueMask();对于特定 ROI 的提取,可使用自定义的 BinaryMask 子类。

常见工作流

工作流 1:探索性切片分析

目标:快速检查切片、检测组织,并采样多个不同区域以供审查。

from histolab.slide import Slide
from histolab.tiler import RandomTiler
from histolab.masks import TissueMask
import matplotlib.pyplot as plt
import logging

logging.basicConfig(level=logging.INFO)

slide = Slide("slide.svs", processed_path="output/exploratory/")
print(f"Dimensions: {slide.dimensions}, Levels: {slide.levels}")
slide.save_thumbnail()

# Visualize tissue detection
tissue_mask = TissueMask()
slide.locate_mask(tissue_mask)
mask_arr = tissue_mask(slide)
print(f"Tissue coverage: {mask_arr.sum() / mask_arr.size * 100:.1f}%")

# Sample tiles
tiler = RandomTiler(
    tile_size=(512, 512), n_tiles=50, level=0,
    seed=42, check_tissue=True, tissue_percent=80.0
)
tiler.locate_tiles(slide, n_tiles=20)
tiler.extract(slide)
工作流 2:深度学习数据集准备

目标:从多个切片构建经过质量控制的图块数据集,用于模型训练。

from pathlib import Path
from histolab.slide import Slide
from histolab.tiler import ScoreTiler
from histolab.scorer import NucleiScorer
import pandas as pd
import logging

logging.basicConfig(level=logging.INFO)

slide_dir = Path("slides/")
output_base = Path("output/dataset/")
all_reports = []

tiler = ScoreTiler(
    tile_size=(512, 512), n_tiles=100, level=0,
    scorer=NucleiScorer(), check_tissue=True, tissue_percent=80.0
)

for slide_path in sorted(slide_dir.glob("*.svs")):
    out_dir = output_base / slide_path.stem
    out_dir.mkdir(parents=True, exist_ok=True)
    slide = Slide(str(slide_path), processed_path=str(out_dir))
    slide.save_thumbnail()
    report_path = str(out_dir / "report.csv")
    tiler.extract(slide, report_path=report_path)
    df = pd.read_csv(report_path)
    df["slide"] = slide_path.stem
    all_reports.append(df)
    print(f"{slide_path.stem}: {len(df)} tiles, mean score {df['score'].mean():.3f}")

combined = pd.concat(all_reports, ignore_index=True)
combined.to_csv(output_base / "dataset_manifest.csv", index=False)
print(f"Total: {len(combined)} tiles from {len(all_reports)} slides")
工作流 3:自定义组织检测与伪影去除

目标:使用自定义过滤器流水线处理带有笔迹标注或染色异常的切片。

from histolab.slide import Slide
from histolab.masks import TissueMask
from histolab.tiler import GridTiler
from histolab.filters.compositions import Compose
from histolab.filters.image_filters import RgbToGrayscale, OtsuThreshold
from histolab.filters.morphological_filters import (
    BinaryDilation, RemoveSmallObjects, RemoveSmallHoles
)

# Aggressive artifact removal pipeline
aggressive_filters = Compose([
    RgbToGrayscale(),
    OtsuThreshold(),
    BinaryDilation(disk_size=10),
    RemoveSmallHoles(area_threshold=5000),
    RemoveSmallObjects(area_threshold=3000)
])

custom_mask = TissueMask(filters=aggressive_filters)
slide = Slide("artifact_slide.svs", processed_path="output/clean/")

# Compare default vs custom mask
slide.locate_mask(TissueMask())     # Default
slide.locate_mask(custom_mask)      # Custom (tighter)

# Extract with custom mask
grid_tiler = GridTiler(
    tile_size=(512, 512), level=1,
    check_tissue=True, tissue_percent=70.0
)
grid_tiler.extract(slide, extraction_mask=custom_mask)

关键参数

参数模块默认值范围 / 选项效果
tile_size所有 Tiler(512, 512)任意 (w, h) 元组切片的像素尺寸
level所有 Tiler00 到 slide.levels-1金字塔层级(0 = 最高分辨率)
check_tissue所有 TilerTrueTrue/False根据组织内容筛选切片
tissue_percent所有 Tiler80.00.0-100.0最低组织覆盖率阈值
n_tilesRandom/ScoreTiler不定任意正整数要提取的切片数量
seedRandomTilerNone任意整数用于确保可复现性的随机种子
pixel_overlapGridTiler00+相邻切片之间的像素重叠量
scorerScoreTiler必填NucleiScorer()、CellularityScorer()、自定义用于切片排序的评分函数
extraction_mask所有 TilerBiggestTissueBoxMask()任意 BinaryMask定义有效提取区域的掩码
disk_size形态学滤镜51-20结构元素尺寸
area_thresholdRemoveSmall*500/10000+对象/孔洞的最小像素面积

最佳实践

  1. 提取前务必预览:调用 locate_tiles() 和 locate_mask(),在开始完整提取前验证设置。这能为大型切片集合节省数小时。

  2. 根据分析分辨率选择层级:层级 0 可提供最高细节,但速度较慢;层级 1-2 通常足以进行初步分析。只有需要细胞级细节的任务才使用层级 0。

  3. 选择合适的切片器策略:

    • RandomTiler 用于探索性分析和多样化采样
    • GridTiler 用于完整覆盖和空间分析
    • ScoreTiler 用于以质量为导向的数据集整理
  4. 使用种子确保可复现性:始终为 RandomTiler 设置 seed,以确保每次运行选择的切片一致。

  5. 针对特定染色自定义掩码:H&E 和 IHC 染色具有不同的颜色特征。调整滤镜参数,或为非标准染色构建自定义 Compose 管道。

  6. 反模式——BiggestTissueBoxMask 已足够时不要使用 TissueMask:TissueMask 的计算开销更大。只有在切片包含多个组织区域时才使用它。

  7. 批处理时启用日志记录:logging.basicConfig(level=logging.INFO) 可在提取过程中跟踪进度。

  8. 使用 ScoreTiler 生成 CSV 报告:在 extract() 中使用 report_path,为下游 ML 管道创建元数据清单。

  9. 反模式——初步探索时不要在层级 0 提取:使用层级 1 或 2 快速迭代,然后切换到层级 0 生成最终数据集。

常用示例

示例:细胞核增强管道

适用场景:从 H&E 染色切片中分离并增强细胞核信号,以供分析。

from histolab.filters.image_filters import RgbToHed, HistogramEqualization, Lambda
from histolab.filters.compositions import Compose

nuclei_pipeline = Compose([
    RgbToHed(),
    Lambda(lambda hed: hed[:, :, 0]),  # Extract hematoxylin channel
    HistogramEqualization()
])

# Apply to slide thumbnail for visualization
enhanced = nuclei_pipeline(slide.thumbnail)
示例:评分分布分析

适用场景:评估切片质量分布,并确定最佳评分阈值。

import pandas as pd
import matplotlib.pyplot as plt

report = pd.read_csv("tiles_report.csv")
fig, axes = plt.subplots(1, 2, figsize=(14, 5))

axes[0].hist(report['score'], bins=30, edgecolor='black', alpha=0.7)
axes[0].set_xlabel('Tile Score'); axes[0].set_ylabel('Frequency')
axes[0].set_title('Score Distribution')

axes[1].scatter(report['tissue_percent'], report['score'], alpha=0.5)
axes[1].set_xlabel('Tissue %'); axes[1].set_ylabel('Score')
axes[1].set_title('Score vs Tissue Coverage')

plt.tight_layout()
plt.savefig("quality_analysis.png", dpi=150, bbox_inches='tight')
plt.show()
示例:多层级分层提取

适用场景:从相同位置提取多个放大层级的切片,以进行多尺度分析。

from histolab.tiler import RandomTiler

for level in [0, 1, 2]:
    tiler = RandomTiler(
        tile_size=(512, 512), n_tiles=50,
        level=level, seed=42,  # Same seed = same locations
        prefix=f"level{level}_"
    )
    tiler.extract(slide)
    print(f"Extracted level {level} tiles")

故障排查

问题原因解决方案
OpenSlideError: Unsupported format未安装 OpenSlide C 库,或不支持该切片格式安装 OpenSlide 系统库;使用 openslide-show-properties 验证格式
未提取到图块tissue_percent 过高,或掩膜未覆盖组织降低 tissue_percent(尝试 60-70%);使用 locate_mask() 预览掩膜
背景图块过多check_tissue=False 或掩膜效果不佳启用 check_tissue=True;提高 tissue_percent;使用 TissueMask()
提取速度非常慢对大型切片使用第 0 级,或在多个区域上使用 TissueMask在第 1-2 级提取;使用 BiggestTissueBoxMask;减少 n_tiles
图块包含笔迹伪影默认掩膜包含笔迹使用基于 HSV 的笔迹检测构建自定义筛选器;提高 RemoveSmallObjects 阈值
提取期间出现 MemoryError对非常大的 WSI 进行第 0 级图块访问在较低级别提取;减少每批处理的图块数
多次运行的结果不一致RandomTiler 中缺少 seed始终设置 seed 参数
图块对模型来说过小或过大tile_size 与模型输入尺寸不匹配调整 tile_size 以符合模型要求(通常为 224、256、512)

附带资源

references/filters_preprocessing.md

全面的筛选器参考,涵盖所有图像筛选器(RgbToGrayscale、RgbToHsv、RgbToHed、OtsuThreshold、AdaptiveThreshold、Invert、StretchContrast、HistogramEqualization、Lambda)和形态学筛选器(BinaryDilation、BinaryErosion、BinaryOpening、BinaryClosing、RemoveSmallObjects、RemoveSmallHoles),包含各筛选器的代码示例、用例说明和常见预处理流程(组织检测、笔迹去除、细胞核增强、染色归一化)。

  • 涵盖内容:所有筛选器类型及各自的代码块、Compose 链式调用、质量控制筛选器、自定义掩膜集成
  • 已移至行内:标准组织检测流程和 Lambda 筛选器基础知识已移至 Core API Module 4
  • 省略内容:筛选器效果的分步可视化(见 references/visualization_slides.md);最佳实践列表已部分整合到主最佳实践部分
references/tile_extraction.md

详细的图块提取参考,涵盖全部三种图块提取策略(RandomTiler、GridTiler、ScoreTiler)的完整参数文档、所有内置评分器(NucleiScorer、CellularityScorer)、自定义评分器创建、带日志记录和 CSV 报告的提取工作流,以及高级模式(多级、分层、提取后模糊筛选)。

  • 涵盖内容:各图块提取器的参数和用例、评分器 API、图块预览、带报告的提取、高级模式、性能优化
  • 已移至行内:基础图块提取器用法和评分器创建已移至 Core API Modules 3 和 5;常用参数表已移至关键参数部分
  • 省略内容:ASCII 网格模式示意图(简单的视觉辅助)
references/visualization_slides.md

整合了可视化、幻灯片管理和组织掩膜参考内容。涵盖幻灯片检查工作流、掩膜对比可视化、切片网格显示、质量评估(评分分布、最佳/最差切片对比)、多幻灯片集合缩略图、组织覆盖率条形图、筛选效果可视化流程、PDF 报告生成,以及交互式 Jupyter 控件。

  • 来源:整合了 visualization.md(547 行)+ slide_management.md(172 行)+ tissue_masks.md(251 行)
  • 涵盖内容:原有的所有可视化模式、幻灯片检查工作流、示例数据集、金字塔层级枚举、掩膜类别及自定义、标注排除模式
  • 已内联迁移:核心幻灯片属性和掩膜基础知识已移至 Core API Modules 1-2;缩略图显示及基础的 locate_mask/locate_tiles 已移至 Module 6
  • 已省略:幻灯片名称/路径等简单属性(2 行);通过手动计算坐标实现的自定义切片位置可视化(仅为概念性内容,不具实用性)
原始参考文件处置情况(5 个文件):
  1. slide_management.md(172 行)—— (b) 已整合:核心内容已移至 Core API Module 1(Slide 类、属性、示例数据、缩略图、区域、金字塔层级);高级幻灯片检查和多幻灯片工作流已移至 references/visualization_slides.md
  2. tissue_masks.md(251 行)—— (b) 已整合:核心掩膜类及用法已移至 Core API Module 2;自定义掩膜(RectangularMask、AnnotationExclusionMask)及掩膜对比已移至 references/visualization_slides.md
  3. tile_extraction.md(421 行)—— (a) 已迁移至 references/tile_extraction.md,并进行了精简
  4. filters_preprocessing.md(514 行)—— (a) 已迁移至 references/filters_preprocessing.md,并进行了精简
  5. visualization.md(547 行)—— (a) 已迁移至 references/visualization_slides.md(与 slide_management.md 和 tissue_masks.md 的内容合并)

相关技能

  • pathml-spatial-omics (planned) —— 高级多重成像和空间蛋白质组学
  • matplotlib-scientific-plotting —— 基于 histolab 输出生成符合出版标准的图表

参考资料

评论

支持 Markdown