如何使用PaddleSeg 2.0快速测量心胸比?

冯嘉骏,毕业于广州医科大学医学影像技术专业,就职于广州市第一人民医院南沙医院。

项目背景

放射科医生下诊断之前,都需要花费不少时间在医学影像图像上,测量各种数据指标,从而更好地判断患者的病情。这篇文章主要介绍PaddleSeg 2.0在X线胸片上的应用,即如何使用PaddleSeg 2.0快速测量心胸比。

心胸比指的是X线胸片上心脏的横径(左、右心缘至体中线的最大距离之和)与胸廓横径(通过右膈肌顶水平胸廓内径)的比例(如图1),这是确定心脏是否有增大的最简方法。正常值女性约为0.45,男性约为0.43,大于0.5即被认为有心脏扩大的可能。

图1

目前,心胸比需要通过医生手动测量和计算得出。但是人们可以使用飞桨PaddleSeg 2.0开发工具,实现自动快速测量心胸比。

PaddleSeg是飞桨图像分割套件。2020年12月18日,PaddleSeg发布了2.0.0rc的动态图版本。通过模块化的设计,其提供了配置化驱动和API调用等两种方式,可以更便捷地完成训练到部署的开发流程。

此项目使用PaddleSeg封装的Unet网络结构,分割胸片上的肺部和心脏。最终,肺部和心脏分割结果分别达到了0.9780.955的准确率。然后,我们将通过OpenCV分别获取肺部和心脏mask外界矩,并进行计算得到心胸比。

项目在AI Studio上已经公开,并提供了数据集在内的完整路径。Fork之后可以直接运行,相关链接为:

https://aistudio.baidu.com/aistudio/projectdetail/1438719

https://github.com/paddlepaddle/paddleseg

最终效果如图2:

图2

网络结构介绍

此项目使用PaddleSeg 的API接口,进行数据增强、Loss、和训练和推理,本文主要针对以上步骤进行介绍。

现在,我们将简单介绍项目中用到的网络结构Unet(如图3)。由于人体内部结构相对固定,生成的医学图像内容分布相对规律,加上医学图像边界模糊,且数据集一般都比较小,对分割结果还要求准确,使用网络结构Unet是个不错的选择。

网络结构Unet是结合了低分辨率和高分辨率信息的分割网络,在医学图像分割中表现出很好的性能。PaddleSeg 2.0已经封装Unet和高质量预训练模型,提供API接口(paddleseg.models),调用并设置类别数量即可。

图3

from paddleseg.models import UNet
pretrained = '/home/aistudio/work/model.pdparams'
model = UNet(num_classes=3,pretrained=pretrained)

数据处理和增强

我们从公开SIIM气胸数据集中选择101张胸片,图片格式为“jpg”,作为此次项目的数据集。我们需要对图像进行再次标注肺部和心脏,因为标注的结果文件是nii格式文件,ct值0代表背景,2值代表是肺部,3值代表是心脏。使用nibabel读取并转换成“jpg”格式。由于数据集数据不多,容易过拟合。针对这个此问题,我们将采用数据增强策略。

结合实际情况,疾病可能会导致获取的胸片肺部部分出现白色致密度影,同时,拍摄角度旋转对比度明亮度的差异,也会影响胸片呈现。因此,我们采用随机水平翻转、小角度随机旋转、随机模糊、随机对比度、明亮度等策略。通过PaddleSeg的数据增强API(paddleseg.transform),可以快速实现。

import paddleseg.transforms as Ttrain_transforms = [
    T.RandomHorizontalFlip(),
    T.RandomDistort(),
    T.RandomRotation(max_rotation = 10,im_padding_value =(0,0,0),label_padding_value = 0),
    T.RandomBlur(),
    T.RandomScaleAspect(min_scale = 0.8, aspect_ratio = 0.5),
    T.Resize(target_size=(512, 512)),
    T.Normalize()
]

图4

训练之前,需要通过API(paddleseg.datasets)快速构建可迭代的训练数据装载器和验证集/测试集数据装载器。只需要传入包含origin和label文件路径的train.txt文件、数据增强策略、分类类别数量和数据装载器类型,即可构建高效的数据装载器。

from paddleseg.datasets import Dataset
train_dataset = Dataset(transforms = train_transforms,
                        dataset_root = dataset_root,
                        num_classes = num_classes,
                        train_path = train_path,
                        mode = 'train')

开始训练前,还需要定义损失函数,PaddleSeg提供多种损失函数的选择。只需要通过API(paddleseg.models.losses)调用就能实现。在这里,我们简单对比了单独使用交叉熵和使用“交叉熵+Dice”的效果,发现使用“交叉熵+Dice”时,IOU提升约1到2点。

from paddleseg.models.losses import CrossEntropyLoss,DiceLoss
losses = {}
losses['types'] = [CrossEntropyLoss(),DiceLoss()]
losses['coef'] = [1,1]

模型训练

PaddleSeg动态图版本开始训练模型只需要一行代码,调用API(paddleseg.core.train)即可开始训练,训练期间还可以通过VisualDL可视化训练期间的Loss、ACC、IOU等结果。比起静态图组网,此种方式大幅度降低了代码量。

train(
    model=model,
    train_dataset=train_dataset,
    val_dataset=val_dataset,
    optimizer=optimizer,
    save_dir='output',
    iters=10000,
    batch_size=4,
    save_interval=200,
    log_iters=10,
    num_workers=0,
    losses=losses,
    use_vdl=True)

而后,我们通过VisualDL进行可视化,得到图5:

图5

推理预测并计算心胸比

PaddleSeg动态图版本和PaddlePaddle动态图版本,能无缝连接。我们可以调用PaddleSeg的API接口(paddleseg.core.predict)进行推理。同样地,我们也可以自定义推理接口,只需要导入PaddleSeg模型,加载最优模型训练结果,设置模型为eval模式,传入需要预测的胸片数据,即可进行推理。

def predict(model, model_path, im_path):
    #预测
    para_state_dict = paddle.load(model_path)
    model.set_dict(para_state_dict)
    model.eval()
    im = cv2.imread(im_path)
    im, _ = transforms(im)
    im = im[np.newaxis, ...]
    im = paddle.to_tensor(im)
    output = model(im)[0]
    output = output.numpy()
    output = np.argmax(output,axis=1)
    output = output.transpose(1,2,0)
    return output

当我们得到模型的推理结果后,通过OpenCV分别获取肺部和心脏的mask结果的最左点、最右点、外边界矩的Width,再找出右膈肌顶的位置,即可计算出此胸部的心胸比,具体实现代码这里不做详细展示,读者可以访问AI Studio项目查看。

#画出肺部的最大横径 和心脏的横径
cv2.line(image,left_heart,(left_heart[0] + int(WidthHeart/2),left_heart[1]),(0,255,0),2)
cv2.line(image,right_heart,(right_heart[0] - int(WidthHeart/2),right_heart[1]),(0,255,0),2)
cv2.line(image,left_chest,(left_chest[0] + WidthChest,left_chest[1]),(0,0,255),2)

总结

通过使用对比改版前的PaddleSeg和如今PaddleSeg动态图版本,大家可以明显感觉代码量的减少,且飞桨越来越Pythonic了。这样的改变可以让开发者更多关注数据本身和开发项目的实际用途。比如,在医疗临床方面上,各种繁琐和重复的工作占用了医生的大部分时间。

欢迎扫码关注:

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值