tag

NnU-Net

nnU-Net 模型学习笔记

nnU-Net 模型学习笔记 0. 背景 这篇主要是对论文 nnU-Net: Self-adapting Framework for U-Net-Based Medical Image Segmentation 的学习记录。 一开始看到 nnU-Net 的时候,其实很容易把它理解成“一个更厉害的 U-Net 变体”。但是读完论文之后发现,它真正重要的地方好像并不是提出了什么特别炫的新网络结构,而是把医学图像分割里一堆容易被忽略的工程细节系统化了。 论文里也直接把 nnU-Net 解释成 no-new-Net,这个名字还挺有意思的。它大概想表达的是: 不一定非要发明一个新的网络结构,先把 U-Net 该做好的事情全部做好。 这点对我还挺有提醒意义的。因为之前做 DICOM 预处理、期相配准、nnU-Net 输入格式的时候,我也经常会下意识觉得“模型才是核心”,但实际上数据怎么裁剪、怎么重采样、spacing 怎么统一、标签怎么插值、patch 怎么取,这些东西如果没处理好,后面的模型可能只是看起来很努力。 1. nnU-Net 想解决什么问题 医学图像分割里面,U-Net 本身已经是一个很经典的结构了。 但是问题在于,不同数据集之间差异非常大: 有的是 CT,有的是 MRI; 有的是 2D 图像,有的是 3D 体数据; 有的 spacing 比较均匀,有的 z 轴很厚; 有的图像范围很大,比如肝脏、肺; 有的目标很小,比如海马体、胰腺病灶; 有的数据集病例很多,有的数据集病例很少。 所以同样是 U-Net,直接拿来用并不一定能跑出好结果。 如果每来一个新任务,都靠人工去调网络深度、patch size、batch size、归一化方式、数据增强方式、推理策略,那整个流程就会非常依赖经验,也很难保证可复现。 nnU-Net 的思路就是: 给定一个新的医学图像分割任务,尽量自动分析数据集特征,然后自动生成一套适合这个任务的 U-Net 训练和推理方案。 所以它不是单纯的一个模型,而更像是一个完整的自动化分割框架。 2. 核心理解:它不追求“新”,而追求“配好” 论文里有一个观点我觉得挺关键: 很多所谓的新结构,在没有把 baseline 充分调好的情况下,看起来确实能提升性能。但如果基础 U-Net 已经被认真配置过,很多花哨结构带来的提升可能就没有那么明显了。 所以 nnU-Net 没有采用 residual connection、dense connection、attention mechanism 这些当时常见的改造,而是只在原始 U-Net 上做了很小的改动: 使用 leaky ReLU; 使用 instance normalization;

阅读全文 »

Batch Registration Qc

多期相 CT 批量配准和 QC 记录 0. 背景 之前已经写过单个 fixed 和 moving 的配准脚本,但真正开始处理病例的时候才发现,单个脚本只能证明“这件事情理论上可以做”,不能证明“这件事情可以批量稳定地做”。 因为一个病例里面往往不止两个序列,可能有平扫、动脉期、门静脉期、延迟期,也可能夹杂 localizer、lung、std、薄层、厚层之类的序列。更麻烦的是,即使它们都来自同一个病例,也不能默认它们的切片编号就是一一对应的。 所以这次想做的是: 批量读取同一个病例下的多个 DICOM series,自动筛选、配准、评价配准效果,并输出可以作为 nnU-Net 多通道输入的 NIfTI 文件。 完整代码见 GitHub:medical-image-registration-scripts 1. 一开始的想法 最初的思路其实很朴素: 读取一个病例下面所有 seriesXXX 文件夹; 自动选一个序列作为 fixed image; 其余序列作为 moving image; 先通过 DICOM header 做第一轮筛选; 对筛选通过的 moving 做刚性配准和重采样; 配准后计算一组无标签 QC 指标; 根据 QC 结果打 PASS、WARNING、FAIL; 只把合格的序列放入最终多通道; 最后对保留下来的通道做共同区域裁剪; 输出 nnU-Net 的 imagesTr 格式。 看起来非常顺理成章,甚至有点过于顺理成章。 但是医学图像处理很多时候就是这样:流程图画出来的时候像一条笔直的路,真正跑起来的时候才发现中间到处是坑。 2. fixed image 的选择 脚本里暂时采用了一个比较直接的规则: 选择切片数最多的 seriesXXX 作为 fixed image。 这样做的原因是,切片数最多的序列通常扫描范围更完整,更适合作为统一空间的参考。 当然这不是一个绝对正确的规则。更严谨的做法应该结合: 序列描述; 扫描范围; 图像质量; 老师指定的标准期相; 是否为薄层或厚层重建; 是否包含目标器官区域。 但在当前阶段,为了先把批量流程跑通,先用“切片数最多”作为自动选择规则。 3. 配准前 header 筛选 在真正做配准之前,脚本会先比较 fixed 和 moving 的空间信息。 主要检查:

阅读全文 »

How_to_registrate

如何具体实现registration 0. 心得 一开始其实根本没理解配准是具体需要做什么,只是一味的vibe coding,什么重采样,刚性配准什么的,最后生成出来的图像全是噪声,第二周感觉把这些放一起就没问题了,结果惊奇的发现人体直接错位了,锁骨来到了人体的中间地方,经过重新认真严谨思考,才意识到配准的真正含义,接下来是对具体配准过程的学习笔记。 完整代码见 GitHub:registration-scripts 1. 任务目标 当前任务是多期相 CT 图像配准。 对于同一个病例,可能存在多个期相或序列,例如: 平扫期 动脉期 门静脉期 延迟期 std5mm lung5mm 这些序列的原始 DICOM 可能存在: 切片数量不同 扫描起始位置不同 spacing 不同 origin 不同 扫描范围不同 呼吸状态导致器官位置轻微变化 因此,不能直接认为不同期相中相同编号的 DICOM 切片对应同一个身体位置。 当前目标是: 以一个期相作为 fixed image,将其他期相作为 moving image,通过配准和重采样,使不同期相在统一空间中具有一一对应的切片关系。 最终输出为 nnU-Net 多通道输入格式。 2. 大体流程 当前采用的整体流程为: 读取同一病例下的 DICOM 文件; 根据 SeriesInstanceUID 区分不同序列; 排除 localizer、scout、切片数过少、不同部位的序列; 选择一个序列作为 fixed image; 其他序列作为 moving image; 对 moving image 进行配准; 将 moving image 重采样到 fixed image 的空间; 根据共同有效扫描范围进行统一裁剪; 检查同编号切片是否对应同一部位; 保存为 nnU-Net 多通道 NIfTI 格式。 简化表示为: fixed image ↓ 提供统一空间标准 moving image ↓ 配准到 fixed image ↓ 重采样到 fixed image 空间

阅读全文 »