基于PaddleSeg实现MR头部矢状位上快速自动定位

2023-10-30 19:59

本文主要是介绍基于PaddleSeg实现MR头部矢状位上快速自动定位,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

点击左上方蓝字关注我们

项目背景

在日常放射科工作中对患者进行磁共振头部检查时,扫描头部轴位,规范标准要求扫描轴位像,需要在矢、冠、轴位定位像上进行定位。冠、轴位像只需要左右对称即可。但是在矢状位定位像上,需要平行胼胝体的前后缘连线(如图)。目前一部分品牌的磁共振机器已经实现自动定位的功能。

磁共振成像,有个特点,时间长。假如确定好扫描范围和参数后,要扫描结束后才能阅览图像。阅览图像时发现范围定位错误或者参数设置错误,那只能重新扫描。而磁共振成像,每一个成像序列都需要1到几分钟不等。因上述错误导致重新扫描,需要的时间成本是很大的,也增加了患者的负担。因此自动定位可以减少人为的错误并加快检查速度,节约时间。

因此本项目是基于PaddleSeg分割开发套件实现类似的自动定位功能。

图1 磁共振颅脑扫描规范

这个项目主要分割颅脑中的胼胝体器官。大脑主要由皮质(灰质)和白质组成,而胼胝体作为最大的连合纤维,连接着左右大脑半球的皮质。胼胝体位于大脑正中矢状切面上,形态上类似弓形,如图2所示。

图2 胼胝体的解剖位置

本项目基于PaddleSeg开发。PaddleSeg是基于飞桨PaddlePaddle开发的端到端图像分割开发套件,涵盖了高精度轻量级等不同方向的大量高质量分割模型。通过模块化的设计,提供了配置化驱动API调用两种应用方式,帮助开发者更便捷地完成从训练到部署的全流程图像分割应用。这个项目主要用到的是API调用的方式。

项目使用PaddleSeg实现的BiSeNetV2网络结构,分割MR头部矢状位上的胼胝体。最终,胼胝体的分割结果miou达到了0.8696。然后,我们将通过OpenCV获取胼胝体的轮廓,得到最左、右的像素点位置,并计算旋转的角度。根据角度得到旋转的定位范围框。

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

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

https://github.com/paddlepaddle/paddleseg

最终效果如图3所示。

图3 最终效果

网络结构介绍

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

因为自动定位需要速度够快,并且有一定的准确性。因此,选择使用BiSeNetV2 网络结构。BiSeNetV2 网络结构在Cityscapes测试集上获得了72.6%的平均IoU,在一张NVIDIA GeForce GTX 1080Ti卡上获得了156 FPS的速度,如图4所示。使用此分割网络很适合“实时”定位任务。

目前提高语义分割的运行速度一般有以下方法:

  1. 可以通过缩小输入图像的大小来实现,但是会失去部分空间信息。

  2. 通过对减少网络通道数量加快处理速度,但是弱化网络提取特征的能力。

这些提速的方法会丢失很多空间信息,从而导致精准度下降。为了防止空间信息的丢失,有些网络会采用U型结构来恢复空间信息。但是U型结构会降低速度。因此BiSeNetV2提出“双边分割”。在速度和准确性之间进行了很好的权衡。

BiSeNetV2结构设计上,实现细节分支和语义分支,并设计一个引导聚合层来融合两个分支的特征。还设计了一种增强训练策略。只在训练中使用,在推理过程中不增加任何代价,BiSeNetV2整体网络结构,如图E所示。

BiSeNetV2的细节分支,使用宽通道和进行三次下采样卷积,来提取低语义空间信息生成高分辨率特征。在语义分支,使用窄通道和深度卷积来增强感受野和获取丰富的上下文信息。由于采用“双边”分支,需要把两支分支进行融合。但是细节分支和语义分支的特征大小不一致,还有细节分支是低级语义信息,语义分支是高级语义信息,简单的组合这两者信息,得不到有效利用。

因此BiSeNetV2提出双边引导的聚合层融合两个分支的信息,如图6。作者为了进一步不影响推理速度的情况下,提出一种增强训练策略(SegHead),使用在语义分支的不同位置上,如图5的Booster。最终在Cityscapes测试集上获得了72.6%的平均IoU,在一张NVIDIA GeForce GTX 1080Ti卡上获得了156 FPS的速度。

图4 BiSeNetV2 在Cityscapes测试集上推理精度和速度

图5 BiSeNet V2的整体网络结构

图6 BiSeNetV2的双边引导聚合层(Bilateral Guided Aggregation)

使用PaddleSeg套件搭建BiSeNetV2 只需要两行代码。代码如下:

from paddleseg.models import BiSeNetV2
model = BiSeNetV2(num_classes=2,lambd=0.25,align_corners=False,pretrained=None)

lambd这个参数用来控制语义分支中前两者的通道数,使语义分支是轻量的。作者论文中提到,加大lambda可以提高精度,但是会损失一定推理时间。align_corners这个参数控制使用插值时是否将输入和输出张量的4个角落像素的中心对齐,并保留角点像素的值。

数据处理和增强

从约600个健康的患者的头部MRT1轴位NiFit格式数据,随机挑选120例。使SimpleITK读取数据,获取120张正中位置的矢状位MR图像,并保存成jpg格式图像。并使Labelme对胼胝体器官的进行标注。把数据集分成8:2,作为训练集和验证集并生成train.txt和val.txt搭建Dataset时使用,如图7。

注:数据来源https://brain-development.org/ixi-dataset/

图7 数据的处理流程

结合实际情况,不同的矢状定位图的旋转角度相差巨大。除了增加了随机水平翻转和随机模糊、随机对比度、明亮度等数据增强策略。重要的使用较大的角度旋转来增加数据的多样性。通过PaddleSeg的API(paddleseg.transform),可以快速实现数据增强策略。预览通过数据增强后的图片数据,如图8所示。

import paddleseg.transforms as T
from paddleseg.datasets import Dataset#数据增强部分
train_transforms = [T.RandomHorizontalFlip(),#水平翻转T.RandomDistort(),#随机对比度,颜色等变化T.RandomRotation(max_rotation = 25,im_padding_value=(0,0,0), label_padding_value = 0),#随机旋转T.Resize(target_size=(512, 512)),T.Normalize()
]

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

train_dataset = Dataset(transforms = train_transforms,dataset_root = dataset_root,num_classes = 2,train_path  = train_path,mode = 'train')

图8经过数据增强的原图和Mask

模型训练

开始训练前,还需要定义损失函数,PaddleSeg提供多种损失函数的选择。只需要通过API(paddleseg.models.losses)调用就能实现。因为BiSeNetV2  采用增强训练策略(SegHead)。一共使用了5个(SegHead),所以配置损失函数的时候,数量为5。

#构建优化器,和loss
from paddleseg.models.losses import CrossEntropyLoss
import paddle
losses = {}
losses['types'] = [CrossEntropyLoss()] * 5
losses['coef'] = [1]* 5

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

#开始训练
from paddleseg.core import train
train(model=model,train_dataset=train_dataset,val_dataset=val_dataset,optimizer=optimizer,save_dir='Myoutput',iters=4800,batch_size=8,save_interval=120,log_iters=24,num_workers=0,losses=losses,
use_vdl=True)

图9 VisualDL可视化训练期间的Loss

处理推理结果实现快速定位

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

model = BiSeNetV2(num_classes=2)
model_path = '/home/aistudio/Myoutput/best_model/model.pdparams'
para_state_dict = paddle.load(model_path)
model.set_dict(para_state_dict)
model.eval()
data = np.expand_dims(data,axis=0).repeat(3,axis=0)
data = np.transpose(data, (1,2,0))
data,_ = transforms(data)
data = data[np.newaxis, ...]
data = paddle.to_tensor(data)
output = model(data)[0].numpy()
output = np.argmax(output,axis=1)
output = np.squeeze(output)

得到推理结果,通过OpenCV对结果进一步处理。先提取轮廓,然后根据提取出来的轮廓得到胼胝体的最左边和最右边的像素点坐标。根据左、右两点坐标求得两点的中心坐标。通过反正切函数求得最左边与中心点坐标连线与水平方向(X轴)的夹角,整体流程如图10所示。

points = list() #用来保存坐标点
#对预测的结果进行阈值分割
ret, binary = cv2.threshold(output,0,255,cv2.THRESH_BINARY)
#获取轮廓的所有坐标点
contours, hierarchy = cv2.findContours(binary,cv2.RETR_LIST,cv2.CHAIN_APPROX_SIMPLE)
for p in contours[0]:points.append(p.tolist()[0])
#根据坐标x轴从小到大排序
points = sorted(points)
#得到最左边的坐标点和最右边的坐标点
left_point = points[0] 
right_point = points[-1]
#计算最左和最右两个坐标点之间的中间坐标
center_point = [int((right_point[0] - left_point[0])/2)+left_point[0],int((right_point[1] - left_point[1])/2)+left_point[1]]
#计算最左边的坐标点和中间坐标点连线  与 X轴之间的夹角
dx1 = left_point[0] - center_point[0]
dy1 = left_point[1] - center_point[1]
#atan2函数计算线段与X轴夹角(弧度)
angle = math.atan2(dy1, dx1)

然后根据上述的中心坐标为中心创建一个矩形框。用来模拟磁共振在定位图上的扫描范围框。根据已得的角度,通过以下代码计算矩形框每个坐标经过旋转后的坐标。在原图上进行绘制旋转后的矩形框。即可快速自动实现平行胼胝体的前后缘的定位。具体实现代码这里不做详细展示,读者可以访问AI Studio项目查看。

rotationx = (x  - centerx)* math.cos(angle) - (y - centery)* math.sin(angle) + centerx
rotationy = (x  - centerx)* math.sin(angle) + (y - centery)* math.cos(angle) + centery

图10 项目流程图

总结

从观察到需要解决的问题,到思考如何解决问题,开始收集数据并标记数据,搭建Dataset、构建网络、训练、参数调优,到最后通过对推理结果进行处理。整个项目只要准备好数据和知道怎样处理推理结果,中间的分割部分,例如网络的搭建和训练代码。只需要结合PaddleSeg API很容易搭建一个完整的分割任务,实现想要的效果。

参考文献:

Yu, Changqian, et al. "BiSeNetV2: Bilateral Network with Guided Aggregation for Real-time Semantic Segmentation"(https://arxiv.org/abs/2004.02147)

飞桨开发者说直播

主题:基于PaddleSeg实现MR头部矢状位上快速自动定位

分享人:冯嘉骏,飞桨开发者技术专家 PPDE

如在使用过程中有问题,可加入官方QQ群进行交流:793866180。

如果您想详细了解更多飞桨的相关内容,请参阅以下文档。

·飞桨官网地址·

https://www.paddlepaddle.org.cn/

·飞桨开源框架项目地址·

GitHub: https://github.com/PaddlePaddle/Paddle 

Gitee: https://gitee.com/paddlepaddle/Paddle

????长按上方二维码立即star!????

飞桨(PaddlePaddle)以百度多年的深度学习技术研究和业务应用为基础,集深度学习核心训练和推理框架、基础模型库、端到端开发套件和丰富的工具组件于一体,是中国首个开源最早、技术领先的产业级深度学习平台。飞桨企业版针对企业级需求增强了相应特性,包含零门槛AI开发平台EasyDL和全功能AI开发平台BML。EasyDL主要面向中小企业,提供零门槛、预置丰富网络和模型、便捷高效的开发平台;BML是为大型企业提供的功能全面、可灵活定制和被深度集成的开发平台。

END

这篇关于基于PaddleSeg实现MR头部矢状位上快速自动定位的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/310265

相关文章

无人叉车3d激光slam多房间建图定位异常处理方案-墙体画线地图切分方案

墙体画线地图切分方案 针对问题:墙体两侧特征混淆误匹配,导致建图和定位偏差,表现为过门跳变、外月台走歪等 ·解决思路:预期的根治方案IGICP需要较长时间完成上线,先使用切分地图的工程化方案,即墙体两侧切分为不同地图,在某一侧只使用该侧地图进行定位 方案思路 切分原理:切分地图基于关键帧位置,而非点云。 理论基础:光照是直线的,一帧点云必定只能照射到墙的一侧,无法同时照到两侧实践考虑:关

hdu1043(八数码问题,广搜 + hash(实现状态压缩) )

利用康拓展开将一个排列映射成一个自然数,然后就变成了普通的广搜题。 #include<iostream>#include<algorithm>#include<string>#include<stack>#include<queue>#include<map>#include<stdio.h>#include<stdlib.h>#include<ctype.h>#inclu

电脑桌面文件删除了怎么找回来?别急,快速恢复攻略在此

在日常使用电脑的过程中,我们经常会遇到这样的情况:一不小心,桌面上的某个重要文件被删除了。这时,大多数人可能会感到惊慌失措,不知所措。 其实,不必过于担心,因为有很多方法可以帮助我们找回被删除的桌面文件。下面,就让我们一起来了解一下这些恢复桌面文件的方法吧。 一、使用撤销操作 如果我们刚刚删除了桌面上的文件,并且还没有进行其他操作,那么可以尝试使用撤销操作来恢复文件。在键盘上同时按下“C

【C++】_list常用方法解析及模拟实现

相信自己的力量,只要对自己始终保持信心,尽自己最大努力去完成任何事,就算事情最终结果是失败了,努力了也不留遗憾。💓💓💓 目录   ✨说在前面 🍋知识点一:什么是list? •🌰1.list的定义 •🌰2.list的基本特性 •🌰3.常用接口介绍 🍋知识点二:list常用接口 •🌰1.默认成员函数 🔥构造函数(⭐) 🔥析构函数 •🌰2.list对象

【Prometheus】PromQL向量匹配实现不同标签的向量数据进行运算

✨✨ 欢迎大家来到景天科技苑✨✨ 🎈🎈 养成好习惯,先赞后看哦~🎈🎈 🏆 作者简介:景天科技苑 🏆《头衔》:大厂架构师,华为云开发者社区专家博主,阿里云开发者社区专家博主,CSDN全栈领域优质创作者,掘金优秀博主,51CTO博客专家等。 🏆《博客》:Python全栈,前后端开发,小程序开发,人工智能,js逆向,App逆向,网络系统安全,数据分析,Django,fastapi

让树莓派智能语音助手实现定时提醒功能

最初的时候是想直接在rasa 的chatbot上实现,因为rasa本身是带有remindschedule模块的。不过经过一番折腾后,忽然发现,chatbot上实现的定时,语音助手不一定会有响应。因为,我目前语音助手的代码设置了长时间无应答会结束对话,这样一来,chatbot定时提醒的触发就不会被语音助手获悉。那怎么让语音助手也具有定时提醒功能呢? 我最后选择的方法是用threading.Time

Android实现任意版本设置默认的锁屏壁纸和桌面壁纸(两张壁纸可不一致)

客户有些需求需要设置默认壁纸和锁屏壁纸  在默认情况下 这两个壁纸是相同的  如果需要默认的锁屏壁纸和桌面壁纸不一样 需要额外修改 Android13实现 替换默认桌面壁纸: 将图片文件替换frameworks/base/core/res/res/drawable-nodpi/default_wallpaper.*  (注意不能是bmp格式) 替换默认锁屏壁纸: 将图片资源放入vendo

C#实战|大乐透选号器[6]:实现实时显示已选择的红蓝球数量

哈喽,你好啊,我是雷工。 关于大乐透选号器在前面已经记录了5篇笔记,这是第6篇; 接下来实现实时显示当前选中红球数量,蓝球数量; 以下为练习笔记。 01 效果演示 当选择和取消选择红球或蓝球时,在对应的位置显示实时已选择的红球、蓝球的数量; 02 标签名称 分别设置Label标签名称为:lblRedCount、lblBlueCount

Kubernetes PodSecurityPolicy:PSP能实现的5种主要安全策略

Kubernetes PodSecurityPolicy:PSP能实现的5种主要安全策略 1. 特权模式限制2. 宿主机资源隔离3. 用户和组管理4. 权限提升控制5. SELinux配置 💖The Begin💖点点关注,收藏不迷路💖 Kubernetes的PodSecurityPolicy(PSP)是一个关键的安全特性,它在Pod创建之前实施安全策略,确保P

hdu 4565 推倒公式+矩阵快速幂

题意 求下式的值: Sn=⌈ (a+b√)n⌉%m S_n = \lceil\ (a + \sqrt{b}) ^ n \rceil\% m 其中: 0<a,m<215 0< a, m < 2^{15} 0<b,n<231 0 < b, n < 2^{31} (a−1)2<b<a2 (a-1)^2< b < a^2 解析 令: An=(a+b√)n A_n = (a +