0
  • 聊天消息
  • 系统消息
  • 评论与回复
登录后你可以
  • 下载海量资料
  • 学习在线课程
  • 观看技术视频
  • 写文章/发帖/加入社区
会员中心
创作中心

完善资料让更多小伙伴认识你,还能领取20积分哦,立即完善>

3天内不再提示

UNet和UNet++:医学影像经典分割网络对比

OpenCV学堂 来源:AI公园 作者:AI公园 2022-04-25 10:38 次阅读
加入交流群
微信小助手二维码

扫码添加小助手

加入工程师交流群

导读

在不同的任务上对比了UNet和UNet++以及使用不同的预训练编码器的效果。

介绍

语义分割是计算机视觉的一个问题,我们的任务是使用图像作为输入,为图像中的每个像素分配一个类。在语义分割的情况下,我们不关心是否有同一个类的多个实例(对象),我们只是用它们的类别来标记它们。有多种关于不同计算机视觉问题的介绍课程,但用一张图片可以总结不同的计算机视觉问题:

5891bd82-c3e2-11ec-bce3-dac502259ad0.png

语义分割在生物医学图像分析中有着广泛的应用:x射线、MRI扫描、数字病理、显微镜、内窥镜等。https://grand-challenge.org/challenges上有许多不同的有趣和重要的问题有待探索。

从技术角度来看,如果我们考虑语义分割问题,对于N×M×3(假设我们有一个RGB图像)的图像,我们希望生成对应的映射N×M×k(其中k是类的数量)。有很多架构可以解决这个问题,但在这里我想谈谈两个特定的架构,Unet和Unet++。

有许多关于Unet的评论,它如何永远地改变了这个领域。它是一个统一的非常清晰的架构,由一个编码器和一个解码器组成,前者生成图像的表示,后者使用该表示来构建分割。每个空间分辨率的两个映射连接在一起(灰色箭头),因此可以将图像的两种不同表示组合在一起。并且它成功了!

58bd8a7a-c3e2-11ec-bce3-dac502259ad0.png

接下来是使用一个训练好的编码器。考虑图像分类的问题,我们试图建立一个图像的特征表示,这样不同的类在该特征空间可以被分开。我们可以(几乎)使用任何CNN,并将其作为一个编码器,从编码器中获取特征,并将其提供给我们的解码器。据我所知,Iglovikov & Shvets 使用了VGG11和resnet34分别为Unet解码器以生成更好的特征和提高其性能。

58dcf5cc-c3e2-11ec-bce3-dac502259ad0.png

TernausNet (VGG11 Unet)

Unet++是最近对Unet体系结构的改进,它有多个跳跃连接。

58f2818a-c3e2-11ec-bce3-dac502259ad0.png

根据论文, Unet++的表现似乎优于原来的Unet。就像在Unet中一样,这里可以使用多个编码器(骨干)来为输入图像生成强特征。

我应该使用哪个编码器?

这里我想重点介绍Unet和Unet++,并比较它们使用不同的预训练编码器的性能。为此,我选择使用胸部x光数据集来分割肺部。这是一个二值分割,所以我们应该给每个像素分配一个类为“1”的概率,然后我们可以二值化来制作一个掩码。首先,让我们看看数据。

5913b238-c3e2-11ec-bce3-dac502259ad0.png

来自胸片X光数据集的标注数据的例子

这些是非常大的图像,通常是2000×2000像素,有很大的mask,从视觉上看,找到肺不是问题。使用segmentation_models_pytorch库,我们为Unet和Unet++使用100+个不同的预训练编码器。我们做了一个快速的pipeline来训练模型,使用Catalyst (pytorch的另一个库,这可以帮助你训练模型,而不必编写很多无聊的代码)和Albumentations(帮助你应用不同的图像转换)。

  1. 定义数据集和增强。我们将调整图像大小为256×256,并对训练数据集应用一些大的增强。
importalbumentationsasA
fromtorch.utils.dataimportDataset,DataLoader
fromcollectionsimportOrderedDict

classChestXRayDataset(Dataset):
def__init__(
self,
images,
masks,
transforms):
self.images=images
self.masks=masks
self.transforms=transforms

def__len__(self):
return(len(self.images))

def__getitem__(self,idx):
"""Willloadthemask,getrandomcoordinatesaround/withthemask,
loadtheimagebycoordinates
"""
sample_image=imread(self.images[idx])
iflen(sample_image.shape)==3:
sample_image=sample_image[...,0]
sample_image=np.expand_dims(sample_image,2)/255
sample_mask=imread(self.masks[idx])/255
iflen(sample_mask.shape)==3:
sample_mask=sample_mask[...,0]
augmented=self.transforms(image=sample_image,mask=sample_mask)
sample_image=augmented['image']
sample_mask=augmented['mask']
sample_image=sample_image.transpose(2,0,1)#channelsfirst
sample_mask=np.expand_dims(sample_mask,0)
data={'features':torch.from_numpy(sample_image.copy()).float(),
'mask':torch.from_numpy(sample_mask.copy()).float()}
return(data)

defget_valid_transforms(crop_size=256):
returnA.Compose(
[
A.Resize(crop_size,crop_size),
],
p=1.0)

deflight_training_transforms(crop_size=256):
returnA.Compose([
A.RandomResizedCrop(height=crop_size,width=crop_size),
A.OneOf(
[
A.Transpose(),
A.VerticalFlip(),
A.HorizontalFlip(),
A.RandomRotate90(),
A.NoOp()
],p=1.0),
])

defmedium_training_transforms(crop_size=256):
returnA.Compose([
A.RandomResizedCrop(height=crop_size,width=crop_size),
A.OneOf(
[
A.Transpose(),
A.VerticalFlip(),
A.HorizontalFlip(),
A.RandomRotate90(),
A.NoOp()
],p=1.0),
A.OneOf(
[
A.CoarseDropout(max_holes=16,max_height=16,max_width=16),
A.NoOp()
],p=1.0),
])


defheavy_training_transforms(crop_size=256):
returnA.Compose([
A.RandomResizedCrop(height=crop_size,width=crop_size),
A.OneOf(
[
A.Transpose(),
A.VerticalFlip(),
A.HorizontalFlip(),
A.RandomRotate90(),
A.NoOp()
],p=1.0),
A.ShiftScaleRotate(p=0.75),
A.OneOf(
[
A.CoarseDropout(max_holes=16,max_height=16,max_width=16),
A.NoOp()
],p=1.0),
])

defget_training_trasnforms(transforms_type):
iftransforms_type=='light':
return(light_training_transforms())
eliftransforms_type=='medium':
return(medium_training_transforms())
eliftransforms_type=='heavy':
return(heavy_training_transforms())
else:
raiseNotImplementedError("Notimplementedtransformationconfiguration")
  1. 定义模型和损失函数。这里我们使用带有regnety_004编码器的Unet++,并使用RAdam + Lookahed优化器使用DICE + BCE损失之和进行训练。
importtorch
importsegmentation_models_pytorchassmp
importnumpyasnp
importmatplotlib.pyplotasplt
fromcatalystimportdl,metrics,core,contrib,utils
importtorch.nnasnn
fromskimage.ioimportimread
importos
fromsklearn.model_selectionimporttrain_test_split
fromcatalyst.dlimportCriterionCallback,MetricAggregationCallback
encoder='timm-regnety_004'
model=smp.UnetPlusPlus(encoder,classes=1,in_channels=1)
#model.cuda()
learning_rate=5e-3
encoder_learning_rate=5e-3/10
layerwise_params={"encoder*":dict(lr=encoder_learning_rate,weight_decay=0.00003)}
model_params=utils.process_model_params(model,layerwise_params=layerwise_params)
base_optimizer=contrib.nn.RAdam(model_params,lr=learning_rate,weight_decay=0.0003)
optimizer=contrib.nn.Lookahead(base_optimizer)
scheduler=torch.optim.lr_scheduler.ReduceLROnPlateau(optimizer,factor=0.25,patience=10)
criterion={
"dice":DiceLoss(mode='binary'),
"bce":nn.BCEWithLogitsLoss()
}
  1. 定义回调函数并训练!
callbacks=[
#Eachcriterioniscalculatedseparately.
CriterionCallback(
input_key="mask",
prefix="loss_dice",
criterion_key="dice"
),
CriterionCallback(
input_key="mask",
prefix="loss_bce",
criterion_key="bce"
),

#Andonlythenweaggregateeverythingintooneloss.
MetricAggregationCallback(
prefix="loss",
mode="weighted_sum",
metrics={
"loss_dice":1.0,
"loss_bce":0.8
},
),

#metrics
IoUMetricsCallback(
mode='binary',
input_key='mask',
)

]

runner=dl.SupervisedRunner(input_key="features",input_target_key="mask")
runner.train(
model=model,
criterion=criterion,
optimizer=optimizer,
scheduler=scheduler,
loaders=loaders,
callbacks=callbacks,
logdir='../logs/xray_test_log',
num_epochs=100,
main_metric="loss",
minimize_metric=True,
verbose=True,
)

如果我们用不同的编码器对Unet和Unet++进行验证,我们可以看到每个训练模型的验证质量,并总结如下:

59583070-c3e2-11ec-bce3-dac502259ad0.png

Unet和Unet++验证集分数

我们注意到的第一件事是,在所有编码器中,Unet++的性能似乎都比Unet好。当然,有时这种差异并不是很大,我们不能说它们在统计上是否完全不同 —— 我们需要在多个folds上训练,看看分数分布,单点不能证明任何事情。第二,resnest200e显示了最高的质量,同时仍然有合理的参数数量。有趣的是,如果我们看看https://paperswithcode.com/task/semantic-segmentation,我们会发现resnest200在一些基准测试中也是SOTA。

好的,但是让我们用Unet++和Unet使用resnest200e编码器来比较不同的预测。

597a5e7a-c3e2-11ec-bce3-dac502259ad0.png

Unet和Unet++使用resnest200e编码器的预测。左图显示了两种模型的预测差异

在某些个别情况下,Unet++实际上比Unet更糟糕。但总的来说似乎更好一些。

一般来说,对于分割网络来说,这个数据集看起来是一个容易的任务。让我们在一个更难的任务上测试Unet++。为此,我使用PanNuke数据集,这是一个带标注的组织学数据集(205,343个标记核,19种不同的组织类型,5个核类)。数据已经被分割成3个folds。

59e83314-c3e2-11ec-bce3-dac502259ad0.png

PanNuke样本的例子

我们可以使用类似的代码在这个数据集上训练Unet++模型,如下所示:

5a230200-c3e2-11ec-bce3-dac502259ad0.png

验证集上的Unet++得分

我们在这里看到了相同的模式 - resnest200e编码器似乎比其他的性能更好。我们可以用两个不同的模型(最好的是resnest200e编码器,最差的是regnety_002)来可视化一些例子。

5a37ee2c-c3e2-11ec-bce3-dac502259ad0.png

resnest200e和regnety_002的预测

我们可以肯定地说,这个数据集是一项更难的任务 —— 不仅mask不够精确,而且个别的核被分配到错误的类别。然而,使用resnest200e编码器的Unet++仍然表现很好。

总结

这不是一个全面语义分割的指导,这更多的是一个想法,使用什么来获得一个坚实的基线。有很多模型、FPN,DeepLabV3, Linknet与Unet有很大的不同,有许多Unet-like架构,例如,使用双编码器的Unet,MAnet,PraNet,U²-net — 有很多的型号供你选择,其中一些可能在你的任务上表现的比较好,但是,一个坚实的基线可以帮助你从正确的方向上开始。

审核编辑 :李倩
声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉
  • 编码器
    +关注

    关注

    45

    文章

    3905

    浏览量

    141472
  • 医学影像
    +关注

    关注

    1

    文章

    112

    浏览量

    17736

原文标题:UNet 和 UNet++:医学影像经典分割网络对比

文章出处:【微信号:CVSCHOOL,微信公众号:OpenCV学堂】欢迎添加关注!文章转载请注明出处。

收藏 人收藏
加入交流群
微信小助手二维码

扫码添加小助手

加入工程师交流群

    评论

    相关推荐
    热点推荐

    影像仪AI自动寻边技术精准捕捉边界测量,检测效率翻倍!

    【智能制造测量】影像测量仪的AI自动寻边技术是通过深度学习模型,实现对工件特征的自主识别与边缘精准提取。能解决质检环节中多重边界提偏、刀纹干扰、对比度低等测量痛点。
    发表于 11-18 10:16

    4K影像赋能精准医疗:索尼FCB-CS8230与SDI编码板的协同创新之路

    在医疗技术向精准化、智能化迈进的今天,影像系统已成为疾病诊断、手术治疗与医学教研的核心支撑。清晰的微观成像、实时的信号传输、稳定的环境适配,关系到诊疗决策的准确性与医疗操作的安全性。索尼4K模组
    的头像 发表于 10-28 14:29 195次阅读

    手机板 layout 走线跨分割问题

    初学习layout时,都在说信号线不可跨分割,但是在工作中为了成本不能跨分割似乎也非绝对。 在后续工作中,跨分割的基础都是相邻层有一面完整的GND参考,跨分割发生在相邻的另外一层。 但
    发表于 09-16 14:56

    RK3576 yolo11-seg训练部署教程

    结构和分割头设计,实现了像素级的精确目标检测与分割,适用于自动驾驶、医学影像、工业检测等对精度和速度要求苛刻的场景。本教程针对目标分割算法yolov11seg的训练和部
    的头像 发表于 07-25 15:21 1292次阅读
    RK3576 yolo11-seg训练部署教程

    芯盾时代如何打造下一代医疗的可信访问体系

    近年来,我国医疗行业掀起了“智慧医院”建设高潮,医院信息系统(HIS)、实验室信息系统(LIS)、电子病历系统(EMR)、医学影像存档与通信系统(PACS)等业务应用极大提升了诊疗效率,让医生工作更轻松,让群众看病更方便。
    的头像 发表于 07-21 14:30 631次阅读

    全球首个胃癌影像筛查AI模型发布

    浙江省肿瘤医院联合阿里巴巴达摩院,发布了全球首个胃癌影像筛查AI模型DAMO GRAPE,首次利用平扫CT影像识别早期胃癌病灶,并联合全国20家医院,在近10万人的大规模临床研究中大幅提升胃癌检出率。 相关论文在24日登上了国际顶级期刊《自然·
    的头像 发表于 06-30 14:37 3682次阅读

    【正点原子STM32MP257开发板试用】基于 DeepLab 模型的图像分割

    :https://arxiv.org/pdf/1706.05587 应用场景 自动驾驶:用于道路、车辆、行人等目标的精确分割医学影像分析:用于肿瘤、器官等区域的分割。 卫星图像分析:用于土地覆盖、建筑物
    发表于 06-21 21:11

    华为发布HUAWEI Pura 80系列,让影像远超想象

    [中国,上海,2025年6月11日] 华为正式推出影像旗舰手机——HUAWEI Pura 80系列,凭借极致的影像技术和创新能力,再次引领移动影像未来。 HUAWEI Pura 80 Pro+
    发表于 06-12 15:10 2808次阅读
    华为发布HUAWEI Pura 80系列,让<b class='flag-5'>影像</b>远超想象

    深度揭秘,MXM显卡竟然是医疗设备的“隐形刚需”!

    在医疗设备领域,随着医学影像技术的不断发展,超声、内窥镜等医疗设备对于图像处理、数据运算等方面的要求也在日益提高,而GPU(图形处理器)显卡凭借其强大的并行计算能力和高内存带宽等优势,逐渐成为医疗
    的头像 发表于 06-04 15:54 1028次阅读
    深度揭秘,MXM显卡竟然是医疗设备的“隐形刚需”!

    东软集团入选国家数据局数据标注优秀案例

    近日,东软飞标医学影像标注平台在国家数据局发布数据标注优秀案例集名单中排名第一(案例名称“多模态医学影像智能数据标注平台”)。评选专家认为东软案例取得了显著成效,一方面,抢占了自主可控的数据标注技术
    的头像 发表于 05-09 14:37 1015次阅读

    RK3576 yolov11-seg训练部署教程

    级的精确目标检测与分割,适用于自动驾驶、医学影像、工业检测等对精度和速度要求苛刻的场景。        本教程针对目标分割算法yolov11 seg的训练和部署到EASY-EAI-Orin-nano(RK3576)进行说明,而
    的头像 发表于 04-16 09:43 1896次阅读
    RK3576 yolov11-seg训练部署教程

    医疗设备工业成像采集卡:提升医疗影像诊断水平的关键组件

    依据。随着医学影像技术的不断进步,例如计算机断层扫描(CT)、磁共振成像(MRI)、超声成像(Ultrasound)以及内窥镜成像等,对成像采集卡的性能要求也越来越
    的头像 发表于 03-19 15:55 684次阅读
    医疗设备工业成像采集卡:提升医疗<b class='flag-5'>影像</b>诊断水平的关键组件

    无法在在DL Workbench中导入unet-camvid-onnx-0001模型之前下载CamVid数据集?

    无法在在 DL Workbench 中导入 unet-camvid-onnx-0001 模型之前下载 CamVid 数据集
    发表于 03-06 07:12

    中信建投报告泄密,AI硬件正在重塑医疗影像与IVD领域的未来

    《2025医疗科技趋势报告》中预判的刚性需求。报告还指出,至2025年,医学影像与体外诊断(IVD)领域将迎来AI应用的深化期,其中AI硬件则会是推动这一变革的关键
    的头像 发表于 02-25 18:03 735次阅读
    中信建投报告泄密,AI硬件正在重塑医疗<b class='flag-5'>影像</b>与IVD领域的未来

    三维测量在医疗领域的应用

    三维测量在医疗领域的应用十分广泛,为医疗诊断、治疗及手术规划等提供了重要的技术支持。以下是对三维测量在医疗领域应用的分析: 一、医学影像的三维重建与分析 CT、MRI等影像的三维重建 : 三维测量
    的头像 发表于 12-30 15:21 1096次阅读