想象你是一名城市规划师,收到了一张覆盖整座城市的超高清航拍图。图里连每一辆出租车、每一个井盖都清清楚楚,可这块屏幕根本放不下整张图。你只能不断放大缩小,先看城市全貌,再放大到某条街区,甚至盯着某个门牌号看。病理医生看一张真实的病理切片,正是同样的体验:组织样本在显微镜下被扫描成一张“巨型城市地图”,里面有肿瘤区、间质区、淋巴细胞区,密密麻麻,一眼望不到头。我们要做的,就是教会 AI 像经验丰富的城市规划师一样,把这张地图切成无数小方块,逐块巡逻、标注、归档,最终生成一张能指导决策的“城市热力图”。 这篇文章带你拆解数字病理切片(WSI)分割的两条技术路线:先靠“金字塔切片”与“区域采样”把巨图变成可处理的街区,再用 HistoSegNet 做精细的“楼宇标注”,用 CLAM 做弱监督下的“重点街区聚光灯”,最后把它们沉淀成可视化与归档方案。
对 AI 从业者而言,掌握 WSI 分割能让你在医学影像项目中真正落地“大图处理”和“弱监督”两大核心课题,避开算力、标注与可解释性陷阱,成为既能调模型、又能搭管线的复合型工程师。
可视化演示
演示病理切片WSI的金字塔切片、区域采样与弱监督聚类分割流程。
本节配有交互动效(进入视口后自动加载,约 3KB)。
金字塔切片 WSI Tile WSI→Tile 多层金字塔逐级切分切片
1. 切片全景挑战
假设你要规划一座城市的交通,但拿到的不是干净的行政区划图,而是一张连墙上涂鸦都清晰可见的超大航拍图。你无法一眼看完,只能靠目光巡逻。病理医生面对的数字病理切片(Whole Slide Image,WSI)也是一样:一张切片在 40 倍物镜下扫描后,常常超过 10 万 × 8 万像素,数据量可达数 GB,相当于“千兆像素级城市地图”。
WSI 的麻烦在于,它既有“城市全局”的需求,又有“街区细节”的需求。医生既要知道肿瘤的大致分布区域,又要放大到细胞级别看核分裂像。这种跨尺度观察无法靠单张普通图片完成。人工阅片时,医生要端着显微镜来回移动,耗时费力且容易漏诊。于是,计算机辅助诊断成了必然选择:我们想让 AI 替医生先做一轮“城市巡逻”,把可疑区域标出来。
要把这种巨图交给 AI,第一步是量化它到底有多大。一张 WSI 的像素总量由长、宽和颜色通道共同决定:
回到城市地图的比喻:既然没法把整座城市搬进一间办公室,我们就必须把它切成一张张街区图,分层归档。这正是后面所有方案的前提——先把“城市图”变成能放进 GPU 的“街区卡片”。
- 图像宽度$W_{\text{WSI}}$ 表示整张切片在某个放大级别下的像素宽度,通常以万为单位。
- 图像高度$H_{\text{WSI}}$ 表示整张切片的像素高度,与宽度相乘得到单通道面积。
- 通道数量$L$ 表示颜色通道数,常规 RGB 图是 3,多光谱图像可能更大。
- 像素总量三者相乘得到 $N_{\text{pixel}}$,它决定了显存占用与预处理成本的量级。
2. 金字塔切片
你还记得用在线地图时的体验吗?缩小看,整个省份是一张轮廓图;放大一档,城市道路出现了;再放大,连小区里的小径都清晰可见。地图 App 并没有保存一张无限大的图,而是存了许多不同缩放级别的“瓦片金字塔”。WSI 处理采用了同样的思路。
WSI 扫描仪会按不同倍率保存多个分辨率层级:比如 1.25 倍、5 倍、10 倍、20 倍、40 倍。每一层都相当于给城市拍了一张不同高度的航拍图。我们把每层图像切成固定大小的正方形瓦片,例如 512×512 像素,网络一次只看一片,像巡逻警察只看自己负责的街区。为了让跨层信息可对齐,还要给瓦片加一点边缘重叠,避免细胞恰好被切成两半时模型看不见全局。
金字塔切片的关键问题是如何计算每个层级需要的瓦片数量。假设某层图像的宽和高分别是 $W_l$ 和 $H_l$,固定瓦片边长是 $P$,那么这一层的瓦片总数为:
在城市地图比喻中,金字塔就是那套“不同高度航拍图”。低层级负责全局概况,高层级负责细胞细节。工程上,我们通常只在需要的层级上切片,而不是每一层都做完整推理,才能在效率与精度之间找到平衡。
- 层级尺寸$W_l$ 与 $H_l$ 是金字塔第 $l$ 层整图的长和宽,宽高会随层级缩放。
- 瓦片边长$P$ 是每次送入模型的瓦片尺寸,比如 256 或 512 像素。
- 向上取整$\lceil \cdot \rceil$ 表示不足一块也要按一块算,因为边缘地区不能丢弃。
- 瓦片总数横向块数与纵向块数相乘,得到该层 $N_l$ 个待处理瓦片。
3. 区域采样
如果城市每个街区都派同样多的警察,那人力一定浪费在大量空无一人的工业区。病理切片同样如此:一片组织里,很大面积是空白背景、脂肪或正常组织,真正有诊断价值的肿瘤区域往往只占一小块。若把全部瓦片不区分地送给模型,模型会被“正常街区”淹没,很难学到关键特征。
区域采样要做的,就是像警力调配一样安排模型的训练数据。第一步是正负样本均衡:既要保留足够多的阳性组织瓦片,也要让阴性瓦片维持一定比例,否则模型只会无脑说“正常”。第二步是困难样本挖掘:每轮训练后,把那些模型最容易分错的瓦片挑出来,下次重点学习,相当于把疑点街区标记出来反复巡逻。第三步是随机采样兜底,防止模型只盯着少数高亮区域而产生偏见。
把采样策略写成损失函数,可以理解为在常规损失之外,给困难样本额外加权:
在城市巡逻场景里,这一步相当于“警力调度系统”。模型不再盲目看每一寸土地,而是把精力集中在高价值、高疑难的街区上,用同样的 GPU 预算是少根杠杆。
- 通用损失项$\frac{1}{N}\sum_{i=1}^{N} \ell_i$ 对所有采样瓦片的损失求平均,保证基础训练稳定。
- 单瓦片损失$\ell_i$ 表示第 $i$ 个瓦片的预测与真实标签之间的差异。
- 困难样本集合$\mathcal{H}$ 是模型当前最容易出错的瓦片集合,训练时要让它们被更多关注。
- 加权系数$\lambda$ 控制困难样本额外损失的重要性,太大容易过拟合,太小等于没挖。
- 总损失$\mathcal{L}$ 是基础损失与困难样本损失的加权和,最终反向传播更新模型。
4. HistoSegNet
有了街区卡片和巡逻优先级,接下来就要真正回答“这栋楼是什么”。HistoSegNet 的做法很聪明:它不直接对每一块瓦片做像素级分割,而是像警察巡逻一样,先站在街口看一眼门牌,判断“这条街值不值得进去搜”,只有拿到足够置信度,才进入建筑内部逐层标记。
具体来说,HistoSegNet 是一个两阶段流程。第一阶段是一个轻量分类器:对于一张瓦片,判断它是否包含目标组织类型,比如肿瘤、间质、淋巴细胞等。如果分类器给出的置信度太低,说明这块瓦片可能是背景或非代表性组织,直接过滤掉。第二阶段才是语义分割网络:只对通过筛选的瓦片做逐像素分类,输出每个像素属于哪种组织。这种“分类引导过滤”既能减少大量无意义计算,又能有效降低背景假阳性。
如果我们用数学表达这个过程,可以写成:
回到城市比喻:分类器是街口望风的巡警,只判断“这一区是否有可疑建筑”;分割网络才是逐户搜查的清查队。这种“先判断再细看”的结构,既让模型跑得更快,也让组织分割结果更干净。
- 输入瓦片$x_i$ 是第 $i$ 张待处理瓦片,通常是某个金字塔层级上的图像块。
- 分类置信度$C(x_i)$ 表示分类器认为该瓦片含目标组织的概率,越高越值得分割。
- 阈值$\tau$ 是预设门槛,比如 0.5 或 0.7,控制过滤严格程度。
- 指示函数$\mathbf{1}[\cdot]$ 在条件成立时取 1,否则取 0,相当于“是否进入下一阶段”的开关。
- 分割结果$S(x_i)$ 是分割网络输出的像素级标签图,$\hat{y}_i$ 是最终结果。
5. CLAM弱监督
城市每年会出一份“健康报告”:这座城市有没有疫情,大致是绿码还是红码。但报告不会告诉你具体是哪个街区导致的。病理诊断也常面临类似情况:医院病历里往往只有“这张切片是癌/非癌”的切片级标签,却没有“哪个像素是癌”的像素级标签。如果每次都去请病理医生手动画像素,成本高到无法落地。CLAM 正是为解决这类问题而生的弱监督方法。
CLAM 的核心思想是多示例学习(MIL):把一张切片看成一个大袋子,里面的每个瓦片就是一个小实例。如果切片是阳性,就认为“至少有一个实例是阳性”,但不知道是哪一个。CLAM 用注意力机制来“投票”:每个瓦片先经过特征提取网络变成一个向量,再通过注意力网络打分,最终所有瓦片的特征按注意力权重聚合成整张切片的特征。分数高的瓦片,就是最可能藏有病灶的“重点街区”。
为了让注意力不跑偏,CLAM 还加了聚类约束:把特征相似的瓦片聚成一类,再从中挑出注意力最高的代表斑块。这样,模型不仅给出切片级判断,还能告诉我们“请重点看这几块”。注意力权重计算如下:
在“城市健康报告”场景里,CLAM 就像一个聪明的分析员:它不知道具体哪个小区致病,但会根据城市各处的细微特征打分,再聚类找出最可疑的几个小区,推荐医生优先检查。这正是数字病理中“用粗标签换细决策”的典型范例。
- 实例特征$\mathbf{h}_i$ 是第 $i$ 个瓦片经特征提取网络得到的向量,相当于每个街区的画像。
- 投影矩阵$\mathbf{V}$ 把原始特征映射到一个更适合打分的空间。
- 注意力向量$\mathbf{w}^{\top}$ 是待学习的打分向量,与映射后的特征做点积,得到原始注意力分数。
- 非线性激活$\tanh(\cdot)$ 让打分带有饱和性,避免个别极大值垄断注意力。
- 归一化分母对所有瓦片的指数分数求和,得到 $a_i$,最终用 $a_i$ 加权聚合整片特征。
6. 可视化与归档
巡逻队完成任务后,如果不画出一张地图,市长还是不知道哪里有问题。WSI 分割与弱监督分析的最终输出,必须变成人类能看懂、能复核、能长期保存的成果。这一步就是可视化与归档。
最常见的是热力分布图。模型对每一块瓦片输出一个“疑似阳性”的置信度,我们把置信度映射成从蓝到红的颜色,按瓦片在原图上的位置贴回去。这样,一张巨幅 WSI 就变成了一张彩色“风险地图”,病理医生可以像看卫星云图一样,一眼锁定红色区域。由于金字塔切片和边缘重叠,同一个像素可能被多块瓦片覆盖,我们需要把它们的预测平均起来,得到平滑的热力图:
最后一步是归档管理。WSI 本身有金字塔结构,我们要把各层级瓦片、模型热力图、CLAM 选出的代表斑块、诊断结论和质控信息一起存入数字病理系统。如果某些区域扫描模糊、切片褶皱或染色不均,系统要标记“需补采”,就像城市规划师发现某块地图被云挡住,必须重新航拍。归档不仅服务于当前诊断,也为未来新模型回补训练数据留下宝贵资产。
- 像素位置$x$ 表示热力图中任意一个像素坐标,对应原图上的某个位置。
- 瓦片概率$p_i$ 是第 $i$ 块瓦片模型输出的目标组织概率。
- 覆盖集合$\Omega_x$ 是所有覆盖了像素 $x$ 的瓦片集合,重叠越多集合越大。
- 集合大小$|\Omega_x|$ 表示覆盖该像素的瓦片数量。
- 平均热力值$H_{\text{map}}(x)$ 在重叠区域取平均,让热力分布更稳定。
AI 应用场景
场景一:数字病理阅片辅助
阶段:图像预处理与初筛
解决的问题:传统病理阅片需要医生在巨幅切片上反复移动视野,耗时且容易漏掉微小病灶。通过金字塔切片与 HistoSegNet 分割,AI 能先输出热力图,把“高风险街区”标红,医生只需重点复核红色区域。
具体案例:某三甲病理科每天处理上千张切片,工程师搭建了“切片入库 → 金字塔瓦片化 → HistoSegNet 初筛 → 医生复核”的流水线,使单张切片的阅片时间从 15 分钟压缩到 5 分钟。
场景二:大规模科研队列筛选
阶段:弱监督建模与代表样本选择
解决的问题:科研机构常有上万张切片,但只有切片级诊断标签,缺少像素级标注。传统做法需要医生手工标注,成本极高。CLAM 能利用弱监督标签完成队列分类,并聚类选出代表性瓦片供医生验证。
具体案例:某肿瘤研究中心用 CLAM 对 5000 例结直肠癌 WSI 做预后风险分层,输出每例切片最可疑的 5 个代表斑块,病理专家组抽检后认为定位准确率超过 85%。
场景三:WSI 归档与质控
阶段:全流程管理与再分析
解决的问题:数字病理系统需要长期保存海量 WSI,同时保证图像质量。金字塔结构 + 热力图归档方案能在有限存储内保留多级分辨率,并通过质控模块自动标出模糊区域、气泡和褶皱,提示补采。
具体案例:某区域病理中心建设“全切片归档平台”,将 WSI 金字塔、AI 热力图、CLAM 代表斑块和诊断结论统一存储,半年后新模型上线时,直接调用历史归档数据完成增量训练。
Python 演示
import mathimport random def patch_counts(level_dims, patch_size): results = [] for l, (w, h) in enumerate(level_dims): total = math.ceil(w / patch_size) * math.ceil(h / patch_size) results.append((l, total, w, h)) return results def sample_patches(tile_scores, rate=0.5, seed=42): random.seed(seed) picked = [] for idx, score in enumerate(tile_scores): if score > 0.7 or random.random() < rate: picked.append(idx) return picked def attention_weights(scores): exp_scores = [math.exp(s) for s in scores] total = sum(exp_scores) return [s / total for s in exp_scores] def cluster_attention(weights, k=3): groups = [[] for _ in range(k)] for i, _ in enumerate(weights): groups[i % k].append(i) best = max(groups, key=lambda g: sum(weights[i] for i in g) / len(g)) return best def main(): levels = [(10000, 8000), (5000, 4000), (2500, 2000)] print("金字塔切片数量:") for l, total, w, h in patch_counts(levels, 512): print(f" level {l}: {total} patches") tile_scores = [0.1, 0.9, 0.4, 0.7, 0.85, 0.2] picked = sample_patches(tile_scores) print("采样瓦片:", sorted(picked)) weights = attention_weights(tile_scores) print("注意力最高的瓦片:", max(range(len(weights)), key=lambda i: weights[i])) print("聚类代表瓦片:", sorted(cluster_attention(weights))) if __name__ == "__main__": main()
levels = [(10000, 8000), (5000, 4000), (2500, 2000)]模拟 WSI 金字塔三层分辨率尺寸,每一层长宽依次减半。total = math.ceil(w / patch_size) * math.ceil(h / patch_size)计算当前层需要切出的瓦片总数,对应金字塔切片公式。if score > 0.7 or random.random() < rate高疑似分数必选,其余按概率随机采样,兼顾难例与随机性。exp_scores = [math.exp(s) for s in scores]将原始分数转成指数权重,softmax 的前置步骤。groups[i % k].append(i)用简单取模模拟特征聚类,把瓦片分到不同组。max(groups, key=lambda g: sum(...))选出平均注意力最高的组,作为“聚类约束代表块”。
常见误区
误区既然 AI 能处理大图,那我直接把整张 10 万 × 8 万的 WSI 放进 CNN 不就行了?最多多买几张 GPU。
正解CNN 的显存占用随输入尺寸急剧膨胀,整图输入会直接导致显存溢出,而且卷积核感受野有限,模型根本看不到远处的上下文。必须用金字塔切片把大图拆成可处理瓦片,再逐块分析。这就像你不能把整座城市地图塞进一台投影仪,只能分页展示。
为何常见:日常图像分类中,我们习惯把整图缩放后输入模型,于是想当然地认为 WSI 也可以缩放;但缩放会丢失关键的细胞级细节,属于治标不治本。
误区把切片切得越细、数量越多,模型能看到更多细节,精度自然会更高。
正解细节确实重要,但无脑增加瓦片数量会引入大量重复背景和冗余计算,还可能破坏正负样本平衡。真正决定精度的是采样策略:该保的阳性区、该挖的困难区、该舍弃的背景区。数量不等于质量,就像派一百万交警去空地站岗,也不会让事故率下降。
为何常见:人们习惯把“数据多”和“效果好”画等号,忽略了 WSI 中信息密度极不均匀的特殊性。
误区CLAM 是弱监督方法,所以我不需要准备标签,直接把切片扔给它就能训练。
正解弱监督依然需要标签,只是标签的粒度更粗:不需要像素级分割图,但必须有切片级诊断标签,比如“这张切片是癌/非癌”。CLAM 用这些粗标签去学注意力,再反推出关键瓦片。没有粗标签,连巡逻的大方向都没有,模型只能瞎逛。
为何常见:“弱监督”这个词常被误解为“少监督”甚至“无监督”,而实际上它降低的是标注精度要求,不是标注有无要求。
误区CLAM 输出了注意力高的瓦片,热力图也标红了可疑区域,就代表模型给出因果解释,可以直接用于诊断。
正解注意力只能说明“模型在关注哪里”,并不等于“那里就是病灶原因”。注意力高可能来自染色差异、边缘伪影或某种偶然模式。热力图应该作为辅助线索,而不是确诊依据,必须由病理医生复核。就像天气预报说某片云可能下雨,但要不要带伞还得看窗外。
为何常见:人们希望“看起来可解释”就等于“解释正确”,忽略了注意力机制本身只是权重分配,而非因果推理。
误区不同医院、不同批次的病理切片颜色深浅不一,但这只是颜色问题,模型自己会适应。
正解染色差异会让相同组织的像素分布发生漂移,模型在 A 院训练得好,到 B 院可能断崖式下跌。实际工程中需要染色归一化、数据增强或域自适应,否则金字塔切片和采样做得再好也白费。就像同样的街道,阴天、晴天、沙尘暴下拍出的航拍图完全不同,巡逻系统需要先统一“天气标准”。
为何常见:很多初学者在公开数据集上训练时数据已经过归一化,容易忽略真实多中心数据中的染色差异。
面试题
Q1. 一张 100000×80000 的 WSI 为什么不能直接送进 CNN?
- A.像素总量大且显存不足← 正确答案
- B.图片格式无法被识别
- C.颜色通道数量过多
- D.缺少医生手工标注
答案:A。CNN 的显存占用随输入尺寸迅速上升,100000×80000 的输入会直接超出常规 GPU 显存;而且卷积感受野有限,整图输入也学不到局部细节。解决方法是金字塔切片,先把巨图拆成小块处理。格式、颜色通道和标注问题都不是整图输入的核心障碍。
Q2. 金字塔切片的核心思想是什么?
- A.多分辨率分层取块← 正确答案
- B.只取图像四角
- C.旋转缩放整张图像
- D.直接做全局池化
答案:A。金字塔切片模拟地图的多级缩放:在不同倍率下保存多个分辨率层,再把每一层切成固定大小瓦片。它既保留了全局结构,又能提供局部细节。只取四角会丢失大部分信息,旋转缩放和全局池化都无法解决巨图的可处理性问题。
Q3. 区域采样中“困难样本挖掘”指的是什么?
- A.优先选模型易分错的区域← 正确答案
- B.只选干净组织区域
- C.完全随机选取全部瓦片
- D.跳过所有大块背景区域
答案:A。困难样本挖掘会在每轮训练后找出模型当前最容易混淆的瓦片,并把它们加入下一轮训练重点学习。它针对的是“看起来像肿瘤的正常组织”或“被背景干扰的边界”等难题。只选干净区域会回避难点,完全随机则不够聚焦,跳过背景虽然必要,但只代表采样策略的一部分。
Q4. HistoSegNet 两阶段流程中的第一步主要做什么?
- A.判断瓦片是否含目标组织← 正确答案
- B.对全图直接做像素分割
- C.把整图压缩成特征向量
- D.计算每个细胞的周长
答案:A。HistoSegNet 采用“分类引导过滤”:第一步先用轻量分类器判断瓦片是否包含目标组织,只有通过筛选的瓦片才进入第二步分割网络。这样能节省大量计算并降低背景假阳性。直接对全图分割正是它试图避免的高成本做法。
Q5. 关于 CLAM 的聚类约束注意力,下列说法正确的有?
- A.用注意力权重聚合实例特征← 正确答案
- B.用聚类约束寻找代表斑块← 正确答案
- C.仍然需要像素级密集标注
- D.只能输出单一分类结果
答案:AB。CLAM 的核心是注意力多示例学习:把整张切片看成袋子,瓦片是实例,用注意力权重把所有实例特征聚合。聚类约束则让相似实例聚成组,再从高注意力组中挑出代表性瓦片。它是弱监督方法,不需要像素级标注;也能扩展为多分类,不是只能输出单一结果。
Q6. CLAM 的注意力机制主要解决什么问题?
- A.弱监督下定位关键实例← 正确答案
- B.无监督压缩整张切片
- C.监督学习做像素分割
- D.图优化提升扫描速度
答案:A。CLAM 面对的标签只有“切片级阳性/阴性”,它必须找出哪些瓦片最终推动了切片判断。注意力机制让模型给每个瓦片打分,从而定位关键实例。它是弱监督下的可解释方案,而不是图像压缩、像素分割或扫描加速工具。
Q7. 关于金字塔切片与采样,下列说法正确的有?
- A.高层级适合看组织全貌← 正确答案
- B.低层级适合看细胞细节← 正确答案
- C.采样应完全忽略背景区域
- D.重叠切片能减少边界损失← 正确答案
答案:ABD。金字塔中低倍率层视野大,适合看组织全貌;高倍率层分辨率高,适合看细胞细节。瓦片加边缘重叠可以让被切开的细胞在相邻瓦片里保留完整上下文,减少边界分割错误。但背景区域不必“完全忽略”,而是要有策略地采样,比如保留少量作为负样本。
Q8. 相比直接端到端分割,HistoSegNet 的分类引导过滤带来了哪些优势?
- A.先筛选再分割节省算力← 正确答案
- B.可降低背景假阳性← 正确答案
- C.完全不需要组织标签
- D.能排除非代表性瓦片← 正确答案
答案:ABD。HistoSegNet 先分类后分割,把明显不含目标组织的瓦片提前过滤掉,因此算力更省,背景假阳性更少,也能排除非代表性的噪声瓦片。但它仍然需要组织标签来训练分类器,并非完全不需要标签。
Q9. 生成 WSI 分割热力图时,较合理的做法是什么?
- A.按置信度叠加瓦片概率← 正确答案
- B.只显示最高分的一个瓦片
- C.把模型输出直接二值化
- D.对整图做随机噪声渲染
答案:A。热力图应该把每个瓦片的置信度投影回原坐标,并对重叠区域取平均,形成平滑的概率分布图。只显示最高分瓦片会丢失全局分布,直接二值化会抹掉灰度信息,随机噪声渲染更是没有意义。
Q10. 弱监督 CLAM 在病理分类中需要的标签形式是什么?
- A.切片级疾病标签← 正确答案
- B.像素级组织标签
- C.每个细胞的边界框
- D.每位病人的基因测序
答案:A。CLAM 的弱监督设定只需要“这张切片是阳性还是阴性”这类切片级标签,不需要像素级分割图或细胞级边界框。模型自己通过注意力聚类反推出关键瓦片。基因测序与组织形态分类属于另一类数据,不是 CLAM 的直接输入。