2. 全切片图像数据基础
数字病理的起点不是模型,而是一张全切片图像(Whole Slide Image,WSI)。它和普通照片的根本差别在于:一张 40× 扫描的切片,物理尺寸约 15 mm × 15 mm,若按 0.25 μm/像素采样,单层像素规模可达 60000 × 60000,约 36 亿像素。任何显存都无法一次装下,因此 WSI 从诞生起就是"分层 + 分块 + 带元数据"的容器格式,而不是一张平面图。理解这一点,是后续切块、染色归一化、训练与验证的全部前提。
一、WSI 格式:容器、编码与厂商差异
WSI 文件本质是一个"容器",内部封装了多分辨率图像、缩略图、标签图(label/macro 图)以及描述扫描过程的元数据。常见格式可分为三类:
- 通用图像容器派:以 Aperio SVS(基于 TIFF)、Hamamatsu NDPI(基于 TIFF)、Leica SCN 为代表,用 TIFF 的 tag 或私有 IFD 存放金字塔层与元数据。
- 专用格式派:如 Philips iSyntax(.isyntax),采用私有分块压缩与索引结构,必须通过厂商 SDK 读取。
- 开放标准派:DICOM WSI(Supplement 145)与 OME-TIFF,前者把每层每块作为 DICOM 实例,便于 PACS 归档与跨厂商交换。
工程上最需要记住的是:不同格式的像素数据可以一致,但元数据字段名、单位、坐标系定义往往不一致。例如 Aperio 用 MPP(Microns Per Pixel)描述分辨率,Hamamatsu 常在私有 tag 中给出物镜倍率与扫描分辨率,Philips 则通过 SDK 暴露。因此读取层应统一抽象为"像素 + 层级 + 物理分辨率 + 染色信息"四要素,而不是直接依赖某个库的字段名。
二、金字塔层级:从 Level 0 到缩略图
金字塔是 WSI 的核心结构。Level 0 是最高分辨率原图,Level 1 通常为 Level 0 的 1/2 边长(面积 1/4),依次下采样,直到整图可放入一屏的缩略图。层与层之间是 2 的幂次关系,但并非所有厂商都严格按 2 倍下采样,有的采用 1/4、1/3 等非标准步长,读取时必须依据每层实际尺寸计算下采样因子,而不能假设 downsample = 2^level。
OpenSlide 等库提供 level_count、level_dimensions、level_downsamples 三个关键量。以一张 40000 × 30000 的 Level 0 为例,若共 4 层,则 Level 3 约为 5000 × 3750,下采样因子约 8。训练时常用的 20× 等效视野,往往对应 Level 0 或 Level 1,取决于扫描倍率与目标放大倍率的换算:目标下采样 = 扫描MPP / 目标MPP。例如扫描 MPP = 0.25,希望得到 0.5 μm/像素的等效 20× 视野,则下采样因子为 2,应读取 Level 1。
三、扫描参数:决定像素物理意义的量
扫描参数直接决定"一个像素代表多少微米",是跨切片、跨中心比较的前提。关键参数包括:
- 物镜倍率与扫描分辨率:常见 20×(约 0.5 μm/px)与 40×(约 0.25 μm/px)。同一张切片用不同倍率扫描,得到的 MPP 不同,若训练时混用而不做重采样,模型会把"分辨率差异"误学成"形态差异"。
- MPP(μm/px):最核心的物理标定量,用于计算等效放大倍率、切块物理尺寸与细胞尺度。
- 扫描仪型号与光源:不同扫描仪的照明光谱、白平衡、对焦策略不同,是染色差异的重要来源。
- 组织区域与背景:扫描仪通常输出带白色背景的整张载玻片,训练前需用组织掩膜(tissue mask)剔除背景,常用 Otsu 阈值或饱和度阈值法。
一个实用的换算示例:若希望每个训练块覆盖 256 μm × 256 μm 的真实组织,在 MPP = 0.5 时块边长应为 512 像素;在 MPP = 0.25 时应为 1024 像素。若统一用 512 像素切块,则前者覆盖 256 μm,后者仅覆盖 128 μm,模型看到的细胞数量相差约 4 倍。因此切块尺寸必须与 MPP 联合确定,而不是固定一个像素值。
四、颜色空间:从 RGB 到染色分离
WSI 存储通常为 RGB(每通道 8 bit),但 RGB 是设备相关的,不同扫描仪对同一张 H&E 切片会给出不同的 RGB 值。病理图像分析中常用的颜色空间包括:
- RGB:直接存储格式,便于显示,但对染色浓度变化不鲁棒。
- HSV / Lab:分离亮度与色度,常用于组织分割与背景剔除。
- OD(光密度):OD = -log10(I/I0),把透射光强转为与染色浓度近似线性的量,是染色分离的基础。
- HED / 染色矩阵:基于 Beer-Lambert 定律,用苏木素(H)、伊红(E)、DAB 等染料的吸收向量做线性解混,得到各染色通道的浓度图。常用 Ruifrok-Johnston 矩阵或 Macenko 方法估计。
工程上,染色归一化(如 Macenko、Reinhard、Vahadane)通常在 OD 空间或 Lab 空间完成,把源切片的染色统计对齐到参考切片,从而降低跨中心色差。需要注意:归一化应在切块后、送入网络前进行,且参考切片应来自与目标域相近的扫描仪,否则可能引入新的偏差。
五、元数据解析:把文件读成结构化对象
元数据是 WSI 的"说明书",包含扫描仪、MPP、倍率、染色、扫描时间、组织类型等。解析时应输出一个统一的结构化对象,供后续流程使用。下面给出一个可直接参考的解析与校验示例(Python 伪代码,参数为示例值):
from openslide import OpenSlide
slide = OpenSlide("case_001.svs")
meta = {
"level_count": slide.level_count,
"level_dims": slide.level_dimensions, # ((40000,30000),(20000,15000),...)
"level_downsamples": slide.level_downsamples,
"mpp_x": float(slide.properties.get("openslide.mpp-x", 0)),
"mpp_y": float(slide.properties.get("openslide.mpp-y", 0)),
"objective_power": slide.properties.get("openslide.objective-power"),
"vendor": slide.properties.get("openslide.vendor"),
}
# 校验:MPP 缺失或异常时拒绝进入训练流程
assert 0.1 < meta["mpp_x"] < 1.0, "MPP 异常,需人工确认扫描参数"
assert meta["level_count"] >= 3, "金字塔层数不足,可能为单层导出图"
# 按目标 MPP 选择层级
target_mpp = 0.5
downsample = meta["mpp_x"] / target_mpp
level = min(range(meta["level_count"]),
key=lambda i: abs(meta["level_downsamples"][i] - downsample))
这段代码体现了三个工程要点:一是MPP 必须校验,缺失或超出合理范围(如 0.1~1.0 μm/px)时应拦截,而不是默认 0.25;二是层级选择用实测 downsample 匹配,而非硬编码 level 编号;三是元数据要落库,与切片 ID、患者 ID、标签一起构成可追溯的数据表,便于后续按扫描仪、倍率分层做验证集划分。
2^level 计算的下采样因子与实际不符,切块物理尺寸出现系统性偏差。把以上五部分串起来,WSI 数据基础可以概括为一条链:格式决定怎么读,金字塔决定读哪层,扫描参数决定像素的物理尺度,颜色空间决定怎么归一化,元数据决定整条链是否可追溯、可校验。这条链上的任何一环出错,都会在训练与验证阶段以"模型性能异常"的形式暴露出来,而根因往往不在模型本身。