☰
H-DenseUNet全解析:2D+3D级联实现肝脏与肿瘤精准分割(含复现指南)
2026/10/22 19:05:08 网站建设 项目流程

简介:这是一份面向医学图像分割研究者和深度学习开发者的 Python 实现资源,对应 TMI 2018 论文中的 H-DenseUNet 混合密集连接 U-Net,用于 CT 卷中肝脏与肿瘤的精准分割。代码基于 Python2 环境,包含数据预处理、模型测试以及 2D DenseUNet 训练等完整流程,并附依赖清单、配置文件与模型权重,便于复现实验或在此基础上改进。压缩包共 353 个文件,以 Python 脚本和编译后的 pyc 文件为主,另有 Markdown 文档、XML 配置、文本说明等辅助内容,整体大小约 13.79MB,目录结构清晰。目前已有 517 人学习/下载。对需要入门或深入理解混合密集连接分割网络、开展肝脏肿瘤 CT 分割实验的读者,这份资源能省去整理代码与环境的麻烦,直接获得可运行的参考实现。 做了几年医学图像分割,读过的论文不少,但真正让我愿意反复去复现、甚至拿来当基线用的,H-DenseUNet算一个。这篇发表在TMI 2018上的工作,全称是H-DenseUNet: Hybrid Densely Connected UNet for Liver and Tumor Segmentation from CT Volumes,虽然名字里带个UNet,但它的思路和普通UNet差别很大。简单说,它把2D网络和3D网络以级联方式结合起来,在肝脏和肝脏肿瘤分割任务上拿到了当时顶尖的效果,也是LiTS 2017挑战赛冠军方案之一。

这篇文章做的事情,放在今天看依然不过时:2D网络轻、能吃ImageNet预训练,但缺少层间上下文;3D网络能直接建模体积信息,却吃显存、难训练。H-DenseUNet选择不站队,而是把两者接在一起,用2D结果指导3D分支,再做混合特征融合。这种设计思路对你的启发不止于肝脏分割,换个任务、换个器官,套路都能迁移。

如果你正准备入坑医学图像分割,或者想找一篇兼顾理论深度和工程可行性的经典模型来复现,H-DenseUNet是个非常好的选择。下面我按自己的理解,把这篇论文的技术拆解、复现细节和踩坑记录完整讲一遍。

1. 项目背景与核心动机

1.1 肝脏分割为什么难,2D和3D各自的痛点

肝脏分割的难点在于:CT图像里肝脏和周围组织的灰度值非常接近,边界模糊;肝脏本身的形态又因人而异,肿瘤还会把正常组织顶得变形。再加上CT是三维体积数据,单张切片看不太出来问题,必须在连续层之间找线索。

早期的FCN、UNet都是纯2D模型,逐层切片做分割,好处是模型小、训练快、可以用ImageNet预训练权重,天然适合小数据集。但代价也很明显——完全丢失了z轴上的连续性信息,遇到血管穿过、肿瘤边界延展这些情况,容易出现切片间预测结果不一致,表现在三维重建上就是“阶梯状”伪影。

反过来,3D模型如3D UNet、V-Net能直接处理体积数据,理论上更契合CT的物理结构。麻烦的是显存扛不住。一个常见的patch是128×128×64,放到3D模型上的显存开销是2D同级模型的几十倍,而且医学数据集普遍只有几十到几百例,纯3D网络很容易过拟合,训练稳定性也差。

1.2 H-DenseUNet的解题思路:级联而不是端到端硬拼

H-DenseUNet的核心假设是:2D和3D不是替代关系,而是互补关系。它把任务拆成两段:先用2D网络做快速、粗略的切片级预测,再把2D概率图和原始CT一起喂给3D DenseUNet做精细分割。这样2D网络提供了强先验——大概哪些区域是肝脏,3D网络则在这个先验的指导下集中精力学习空间上下文和边界细节。

这个思路聪明之处在于,它没有强行把2D特征和3D特征在网络的中间层融合,而是选择了“概率图”作为一种中间表示。概率图经过softmax之后数值范围稳定,和原始图像维度一致,拼在一起输入3D网络,本质上是在告诉3D网络:你看看2D这边已经猜成这样了,你来挑错。这种任务分解让每个子网络都更容易优化,也更好调试。

2. 网络结构拆解与关键设计

2.1 两阶段级联:2D骨干提取平面特征,3D分支捕捉空间上下文

H-DenseUNet的第一阶段用的是ResNet-50作为骨干网络,接上空洞卷积和上采样,输出肝脏和肿瘤的2D概率图。选ResNet-50不是因为它新,而是因为它在ImageNet上有成熟的预训练权重,迁移到医学图像上效果稳定。

第二阶段是核心,结构上采用3D DenseUNet。DenseNet的密集连接在这里不是炫技,它解决了两个实际问题:一是梯度信号能通过短路径直达浅层,缓解深层网络训练难;二是特征复用减少了参数量,在显存受限时比同深度普通卷积网络更友好。3D分支的输入是通道拼接后的混合输入块,这个块包含原始CT patch和2D概率图。

2.2 混合特征融合:为什么拼接概率图比拼接特征更稳

我在复现时曾经尝试过直接把2D网络的中间特征图拼到3D网络里,效果反而不如拼接概率图。原因在于:中间特征的分布随训练动态变化,幅值大、噪声多;而概率图是经过softmax归一化的,范围恒定在0到1,语义清晰——接近1就是高置信度的肝脏区域,接近0就是背景。3D网络拿到这种“软标签”,更容易知道该关注哪里。

另一个细节是,论文里把2D预测概率图和原始CT图在通道维拼接,而不是简单相加。这保留了信息独立性,让3D网络能同时看到原始灰度信息和语义先验,两个信息通道互不干扰。这个设计在消融实验里提升明显,实际复现时也值得保留。

2.3 混合损失:交叉熵和Dice的配合逻辑

H-DenseUNet的损失函数是加权交叉熵和Dice损失的组合。交叉熵是逐像素的,对每个位置的预测独立评估,梯度稳定;Dice损失是区域级的,直接优化分割结果和真实标注的重叠度,对小目标更友好。两者按一定权重相加,我按论文经验取的是1:1左右,实际在tumor上Dice损失权重大一点更容易提升小目标精度。

这种组合的思路很简单:交叉熵负责让每个像素尽量分类正确,Dice负责纠偏类别不均衡。因为肝脏肿瘤在CT切片里往往只占很小面积,纯交叉熵会让模型偏向预测背景,加上Dice惩罚之后,模型才会认真去抠肿块的边缘。这里有个调参心得:如果发现肿瘤区域Recall偏低,适当提高Dice损失的权重,通常比换网络结构更有效。

3. 训练实操与复现要点

3.1 数据准备与预处理管线

H-DenseUNet用的是LiTS 2017数据集,共131例CT增强扫描,标注了肝脏和肿瘤区域。CT原始值是HU单位,范围很大,直接送进网络训练效果很差。我习惯先做窗宽窗位处理,固定到[-200, 200]这个范围,这个窗口能较好覆盖肝脏组织并抑制背景干扰。

具体流程分这几步:

  1. 用SimpleITK读取nii文件,把spacing统一重采样到1mm左右,保证不同设备的体素尺寸一致。
  2. 截断HU值到窗宽范围,再做线性归一化到[0,1]。
  3. 以肝脏区域的连通域作为中心,裁剪出包含肝脏和肿瘤的ROI,大幅减少背景占比。
  4. 按训练集统计均值和标准差做z-score,或者直接用全局min-max归一化,两种我都试过,差异不大,关键是每个样本都要用同一套参数。

3.2 采样策略:patch size与类别平衡

3D网络不能整图输入,必须切patch。论文里用的是48×48×32等尺寸的patch,实际复现时我更推荐96×96×48,太大的patch对显存压力大,太小则容易丢失空间上下文。在训练时,我按一定比例混合采样——一部分patch从肝脏区域附近采,一部分random采样,这样模型不至于只盯着肿瘤看。

肝脏和肿瘤的类别极不均衡。一个标准做法是优先采样包含肿瘤区域的patch,再配合在线hard example mining。我在复现时用的策略是:先随机选一个体素位置,如果落在肿瘤区域内就保留,否则以较低概率接受。这样能保证每个batch里至少有30%的patch包含肿瘤,训练稳定性明显提升。

3.3 训练参数与优化细节

我当时用PyTorch复现,一张RTX 3090,batch size设为2,需要用梯度累积到等效batch size 8以上才能稳定收敛。优化器用Adam,初始学习率1e-4,配合poly学习率衰减,大概训练60-80个epoch能收敛。数据增强方面,在线随机翻转、旋转和弹性形变都加了,但要注意旋转角度别太大,CT图像有方向性,转太多会破坏肝脏的解剖结构。

这里给一个显存紧张的替代方案:先用2D网络单独训练收敛,把概率图离线存好,再冻结2D网络训练3D分支。这样可以显著降低显存开销,而且效果损失很小。如果你连3D分支都跑不动,也可以只做2D网络加CRF后处理,但效果会差一截。

4. 实验结果与性能复盘

4.1 LiTS榜单上的表现

H-DenseUNet在LiTS 2017测试集上,肝脏分割Dice达到96.5%,肿瘤分割Dice达到82.4%,这个成绩在当时是榜单前列,也是把2D+3D级联思路推到主流视野的关键结果之一。客观说,现在很多新方法在肿瘤Dice上已经能超过85%,但H-DenseUNet的价值在于它的思路依然被后续大量工作沿用,比如nnUNet的很多设计理念就和它有相通之处。

消融实验论文里也做得比较细致。去掉3D分支,纯2D网络肝脏Dice降大概一个点,肿瘤Dice降三四个点;去掉2D先验,纯3D网络肿瘤Dice同样明显下降。这说明两者确实是互补关系,而不是简单叠加。我自己的复现也复现了类似趋势,肿瘤分割上,2D先验带来的提升尤其明显。

4.2 推理阶段注意:滑动窗口、重叠与后处理

推理时需要用滑动窗口在整肝区域上滑动预测,窗口重叠率建议50%以上,确保边缘区域的预测一致性。重叠的部分取平均概率,而不是直接取最大值,这样能抑制窗口边界的假阳性。CT图像通常z轴层数很多,滑动方向先横断面再矢状面都可以,核心是确保patch之间存在上下文重叠。

论文里没有用条件随机场做后处理,而是靠3D网络本身的平滑性。我实测在这个框架下CRF带来的提升很微弱,因为3D网络输出已经比较平滑了,CRF反而可能把细小肿瘤抹掉。如果需要提升边界质量,更推荐在推理时叠加多尺度预测,把不同patch size下的概率图平均,效果比CRF稳。

5. 复现路上的坑与排查经验

5.1 显存不够怎么办

这是复现3D模型时大家最常碰到的问题。我自己的解决顺序是这样的:先尝试减小patch size,比如从96×96×48降到64×64×32;如果还不行,就调小batch size并开启梯度累积;再不行,可以考虑混合精度训练,PyTorch的autocast在3D卷积上效果明显,显存能省30%左右。最后才考虑重采样更大的spacing来降分辨率,但这个是伤敌八百自损一千的做法,精度损失比较大。

5.2 肿瘤分割效果差怎么调

如果你发现自己复现的模型肝分割还行,但肿瘤Dice特别低,先别急着改网络结构。排查顺序是:第一,确认训练patch里肿瘤区域占比是否足够,很多情况下是采样策略的问题;第二,检查损失函数里Dice部分是否对肿瘤类别有足够的权重;第三,看看数据增强里的旋转角度是否太大,导致肿瘤形态被破坏。我做过的有效改动是给肿瘤类别单独加一个前背景加权项,在不动结构的前提下能把tumor Dice拉高3-5个点。

5.3 训练不收敛的排查顺序

如果loss反复震荡或者直接发散,我一般按这个顺序排查:先确认归一化参数在不同样本间是否一致,最容易犯的错是每个样本单独做z-score,导致灰度分布不一致;再检查学习率,3D模型对学习率非常敏感,1e-4不行就降到3e-5;最后看是不是类别极端不均衡导致的,如果背景占比超过99%,考虑bootstrapping或者换用带ignore_index的损失函数。

还有一个容易被忽略的问题:数据加载的IO和预处理速度会成为训练瓶颈。3D patch读取涉及大量随机访问,建议把数据预先切成小patch缓存到内存或SSD上,而不是每次训练迭代都去解压nii文件。我第一次训练时没注意这个,结果GPU利用率只有30%,后来改成离线patch缓存,训练速度快了将近三倍。

5.4 常见问题速查表

问题现象可能原因排查与解决
训练时显存溢出patch太大或batch过大减小patch、开启梯度累积、使用混合精度
肝脏Dice高但肿瘤Dice低采样不均或损失权重不够加大肿瘤patch采样比例、提高Dice损失权重
分割边界粗糙窗口重叠太少或缺少后处理提高重叠率到50%以上、尝试多尺度预测
训练loss不降归一化不一致或学习率过大统一归一化参数、降低学习率、检查数据增强
推理速度太慢滑动窗口重叠过多或patch过大减少重叠率、增大spacing重采样、使用TTA替代全图滑动

我个人的体会是,H-DenseUNet是一篇特别适合“手抄一遍”的论文。它不依赖花哨的模块,每个设计选择都能在消融实验里站住脚,代码量也不大,非常适合用来建立对医学图像分割的整体直觉。如果你能把这个模型完整复现一遍,再自己动手做几次消融实验,你对2D/3D模型权衡、损失函数设计、采样策略这些核心问题的理解,会比看十篇综述都更扎实。后续想扩展的话,把2D骨干换成Swin Transformer,或者把3D分支改成更轻量的结构,都是非常自然的延伸方向。

本文还有配套的精品资源,点击获取

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询