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 — 有很多的型号供你选择,其中一些可能在你的任务上表现的比较好,但是,一个坚实的基线可以帮助你从正确的方向上开始。

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

    关注

    42

    文章

    3458

    浏览量

    132217
  • 医学影像
    +关注

    关注

    1

    文章

    108

    浏览量

    17291

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

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

收藏 人收藏

    评论

    相关推荐

    听医信人说 | 为什么医院建网选择极简以太彩光网络

    效率、改善患者的就医体验,网络部署需要更加灵活、高效。传统的频繁打孔和布线方式不仅影响医疗业务的正常进行,而且使用Hub和简易交换机可能会给网络稳定性和运维管理带来额外的挑战。 医学影像的即时读取 :高清
    的头像 发表于 06-20 14:56 137次阅读

    利用NVIDIA的nvJPEG2000库分析DICOM医学影像的解码功能

    本文将深入分析 DICOM 医学影像的解码功能。AWS HealthImaging 利用 NVIDIA 的 nvJPEG2000 库来实现此功能。
    的头像 发表于 05-28 14:27 218次阅读
    利用NVIDIA的nvJPEG2000库分析DICOM<b class='flag-5'>医学影像</b>的解码功能

    AI医学影像企业深智透医完成B+轮近千万美元融资

    AI医学影像领域的领军企业深智透医(Subtle Medical Inc.)近日成功完成了B+轮近千万美元的融资,使其累计融资额超过五千万美元。此次融资的注入,将为公司全球商业拓展和产品研发创新提供强大的资金支持。
    的头像 发表于 05-14 10:08 212次阅读

    西门子医疗与山东第一医科大学放射学院达成战略合作

    校企携手培育医学影像高端人才,虚实融生引领教育培训崭新模式 共建全国首个"医学影像元宇宙沉浸式教研示范学院" 探索实施"产学研用"四位一体的校企联合定向培养计划 促进各层级医研产学人才交叉培养与有机
    的头像 发表于 01-30 14:33 611次阅读
    西门子医疗与山东第一医科大学放射学院达成战略合作

    轻松实现医学影像 AI:NVIDIA 提供 MONAI 托管云服务

    这项创新服务具有用于交互式 AI 标注和训练的强大 API,可以加速医学影像解决方案发展。 NVIDIA 推出医学影像 AI 云服务,通过全托管的云端应用程序编程接口(API),进一步简化和加速真值
    的头像 发表于 11-30 19:35 309次阅读

    为什么需要分割?U-Net能提供什么?U-Net和自编码器的区别

    U-Net是一种卷积神经网络(CNN)方法,由Olaf Ronneberger、Phillip Fischer和Thomas Brox于2015年首次提出,它可以更好的分割生物医学图像。
    的头像 发表于 11-25 11:38 2576次阅读
    为什么需要<b class='flag-5'>分割</b>?U-Net能提供什么?U-Net和自编码器的区别

    高压放大器能够在哪里使用呢

    高压放大器是一种重要的电子设备,可以在许多不同的领域和应用中使用。下面西安安泰将详细介绍高压放大器的应用。 医学影像:高压放大器在医学影像领域具有广泛的应用。医学影像设备(如X射线机、CT扫描仪
    的头像 发表于 11-07 17:18 242次阅读
    高压放大器能够在哪里使用呢

    基于一种用于医学图像分割的方法

    这次我们要解读的工作发表在 IPMI 2023(IPMI全名 Information Processing in Medical Imaging,两年一届,是医学影像分析处理领域公认的最具特色的会议
    的头像 发表于 09-05 11:29 1232次阅读
    基于一种用于<b class='flag-5'>医学</b>图像<b class='flag-5'>分割</b>的方法

    深度学习在医学图像分割与病变识别中的应用实战

    等方面具有重要意义。本文将介绍这一领域的背景、挑战,以及通过一个代码实例展示如何利用深度学习方法进行医学图像分割与病变识别。 背景与挑战医学图像分割是将
    发表于 09-04 11:11

    医学影像四大设备是什么 医学影像的作用和存在意义

    医学影像可以提供医生对疾病的非侵入性视觉化信息,帮助医生进行准确的诊断。通过医学影像,医生可以观察人体内部的解剖结构、组织和器官的变化,识别异常的肿瘤、损伤、炎症等,并为制定治疗方案提供依据。医学影像也可以用于手术规划和引导手术
    发表于 08-29 14:48 9152次阅读

    东软医学影像信息系统实现系统间的数据共享和互联互通

    近日,IDC发布《中国医学影像信息系统市场份额,2022》,东软凭借在医学影像信息系统领域对市场的深刻理解、持续创新的技术能力、稳健的服务能力居市场份额第一。 东软深耕医学影像信息系统多年,不断
    的头像 发表于 08-24 15:17 1012次阅读

    CVPR 2023 中的领域适应:用于切片方向连续的无监督跨模态医学图像分割

    如上图所示,以前的医学图像分割 UDA 方法大多采用 2D UDA,当将预测堆叠在一起时,会导致切片方向上的预测不一致。SDC-UDA 在翻译和分割过程中考虑了体积信息,从而改善了分割
    的头像 发表于 08-17 16:35 1582次阅读
    CVPR 2023 中的领域适应:用于切片方向连续的无监督跨模态<b class='flag-5'>医学</b>图像<b class='flag-5'>分割</b>

    医学影像设备包括哪些设备 医学影像设备发展历程简单介绍

    人工智能(AI)在医学影像领域的应用将越来越广泛。AI算法可以帮助医生在大量影像数据中提取信息,辅助诊断和预测患者病情的发展趋势。这有助于提高诊断准确性、速度和效率。
    发表于 08-10 14:54 7057次阅读

    影像诊断技术包括哪些 影像诊断和影像技术的区别

    影像技术是用于获取和生成医学影像的各种技术和设备;而影像诊断是利用医学影像来诊断疾病、评估病情和指导治疗的过程。影像技术是实现
    发表于 07-21 15:11 2113次阅读

    常见的医疗系统中DSP的应用领域

     医学影像设备是指用于获取、处理和显示医学影像的专用设备。它们能够生成具有高分辨率和丰富信息的图像,帮助医生进行疾病诊断、治疗和监测。
    发表于 07-03 17:17 1549次阅读