1 简介
在上一篇文章中,我们 手把手演练了transforms模块下的LoadImaged,EnsureChannelFirstd和Resized函数,实现了图像和掩模数据的加载、通道优先和尺寸缩放三个基本操作。本文将在之前的基础上继续介绍其他常用的基本变换函数,包括旋转和强度变化等。除了这些基本操作之外,作为MONAI医学影像处理框架下的图像预处理模块,transforms还有裁剪、滤波等其他操作,相信大家能够做到触类旁通。
2 具体实现
2.1 图像旋转
经过前面的缩放操作,我们得到了字典变量tr,其图像尺寸已经缩小为(256,256)。通过transforms模块的Rotated函数,可以对字典变量进行旋转操作。Rotated函数有两个参数keys和angle:keys用来明确对哪些键值操作,angle指定顺时针旋转的角度。图像旋转的代码及注解如下:
# 确保通道优先
# 导入transforms模块下的Rotated函数
from monai.transforms import Rotated
# 对字典变量tr进行旋转变换,图像和掩模图像同时变换,顺时针旋转角度为30°
trt= Rotated(keys=['image','label'],angle=3.14/180*30)(tr)
# 核查旋转后图像的尺寸
trt['image'].shape,trt['label'].shape
代码成功运行后,结果显示如下:
可以看出,旋转函数与缩放函数不同,没有改变图像的尺寸。
接下来,通过旋转操作后结果的可视化,直观看看旋转函数对图像的影响。旋转操作代码及详解如下:
#可视化 fis
plt.figure("image",(8,4))# 创建4×8英寸的图像窗口
plt.subplot(1,2,1) # 在1×2的绘图布局第一个区域,开始绘图
plt.imshow(trt['image'][0],cmap='gray')#绘制数据图像,灰度模式显示
plt.xlabel(f'{trt["image"].shape}')#把数据推向的形状添加到横坐标上
plt.subplot(1,2,2)# 在1×2的绘图布局第二个区域,开始绘图
plt.imshow(trt['label'][0],cmap='gray')#绘制掩模图像 ,灰度模式显示
plt.xlabel(f'{trt["label"].shape}')#把掩模推向的形状添加横坐标轴上
plt.show()
代码成功运行结果如下图所示。
可以看出,CT图像和掩模图像都旋转了30°,验证了Rotated的功能。
2.2 强度变换
MONAI框架下transforms比较有用个强度变换函数有两个:一个是ScaleIntensityd函数,把图像强度线性变换到(0,1)范围内;另一个是ScaleIntesityRanged函数,把原图像(amin,amax)范围内图像线性变换到(bmin,bmax)区间,(amin,amax)范围之外的强度置为0。下面分别介绍两种函数的实现。
(1)ScaleIntensityd
相当于对整个图像数据进行标准化,所有强度值变换到(0,1)范围内。代码及注释如下所示:
# 从monai.transforms模块导入 ScaleIntensityd函数
from monai.transforms import ScaleIntensityd
# 对图像数据和掩模数据同时进行强度变换
ts = ScaleIntensityd(keys=['image','label'])(trt)
ts['image'].max(),ts['image'].min()
代码成功运行结果如下图所示:
可以看出,亮度归一化之后图像的最小值为0.0,最大值为1.0。
随后,对归一化的数据字典进行可视化,代码及注释如下所示:
#可视化 fis
plt.figure("image",(8,4))# 创建4×8英寸的图像窗口
plt.subplot(1,2,1) # 在1×2的绘图布局第一个区域,开始绘图
plt.imshow(ts['image'][0],cmap='gray')#绘制数据图像,灰度模式显示
plt.xlabel(f'{trt["image"].shape}')#把数据图像的形状添加到横坐标上
plt.subplot(1,2,2)# 在1×2的绘图布局第二个区域,开始绘图
plt.imshow(ts['label'][0],cmap='gray')#绘制掩模图像 ,灰度模式显示
plt.xlabel(f'{trt["label"].shape}')#把掩模图像的形状添加横坐标轴上
plt.show()
代码成功运行结果如图所示:
(2)ScaleIntensityRanged
ScaleIntensityRanged函数的作用类似于开窗变换(Windowing),可以把感兴趣组织的灰度窗口映射到一个灰度范围去,该函数有a_min,a_max,b_min,b_max,Clip等参数,其中a_min/max用来确定原图像灰度观察范围,b_min/max是变换后图像的灰度范围,Clip=True时,在灰度观察范围之外的像素强度都置0。CT值的范围一般是-1000~3000左右,空气是-1000,水是0,致密骨骼达到2000多,而脾脏的CT值范围大概在-300到300之间,因此可以设定合适观察范围,突出脾脏组织的成像效果。代码及注释如下所示:
#从monai.transforms 导入ScaleIntensityRanged函数
from monai.transforms import ScaleIntensityRanged
# 观察窗口范围设置为-300到300,变换后图像范围为0到1,观察窗口范围外的像素强度置位0
tsr = ScaleIntensityRanged(keys='image',a_min=-300.0,a_max=300.0,
b_min=0.0,b_max=1.0,clip=True)(trt)
tsr['image'].min(), tsr['label'].max()
代码成共运行结果如下:
对变换结果进行可视化的代码与前面类似,只是把字典变量ts更换为tsr,这就就不再贴出代码。代码成功运行结果如下所示:
与前面的结果对比可以看出,通过ScaleInensityRanged函数,设置合理的观察窗口,能够提升脾脏器官组织成像对比度,有助于后续的图像识别与分割。
2.3 变换组合
上面介绍了transforms模块下,LoadImaged,EnsureChannelFirstd,Resized,Rotated,ScaleIntensityd,以及ScaleIntensityRanged等基本操作函数的用法。在实际应用中,我们很少单独使用各个函数进行图像变换。MONAI提供了Compose函数,能够通过列表的方式把所需的图像处理函数串接起来,组成一个集成变换,便于程序的编写与阅读。
组合变换的代码及注释如下所示:
# 通过Compose列表把组合在一起使用
# 加载图像,通道优先,缩放,旋转,亮度归一化LERRS
# 加载Compose,LoadImaged等图像处理函数
from monai.transforms import (Compose,
LoadImaged,
EnsureChannelFirstd,
Resized,
Rotated,
ScaleIntensityd)
# 定义组合变换函数,通过Compose函数把图像处理函数按照先后顺序组合起来
trans = Compose([
LoadImaged(keys=['image','label']),
EnsureChannelFirstd(keys=['image','label']),
Resized(keys=['image','label'],spatial_size=(128,128)),
Rotated(keys=['image','label'],angle=3.14/180*45),
ScaleIntensityd(keys=['image','label'])
])
# 定义字典变量,指定数据和掩模文件名
inputs = {"image": "/kaggle/input/monaitransfomdata/spleen_10trans.nii",
"label": "/kaggle/input/monaitransfomdata/spleen_10mask.nii"}
# 变换输出
outputs = trans(inputs)
# 核对输出图像的形状
outputs['image'].shape
代码成功运行输出结果如下:
可视化代码与前面给出的示例几乎相同,只需要修改字典变量,把ts更换为outputs,不在贴出代码。运行结果图下图所示。
因为我们在Compose中组合的变换包括ImageLoad、EnsureChannelFirstd,Resized等,执行Compose操作相当于把上述变换依次执行,最终图像也跟单独执行各个操作得到的图像是一致的。
2.4 图像保存
monai.transforms模块提供了SaveImaged函数,用来将字典数据保存为图像和掩模文件。具体代码如下:
from monai.transforms import SaveImaged #导入图像保存函数
SaveImaged(keys=['image','label'])(outputs)#把字典数据分别保存为图像和掩模文件
代码运行结果如下图所示:
可以看出,在工作目录下建立了图像和掩模文件。
3 试一试
如果要求对图像放大为(1024,1024),并顺时针旋转60°,上述代码该如何修改?相信大家很容易就能实现。
4 总结
MONAI的transforms模块提供了功能强大的图像预处理函数,这些函数既可以单独使用,也可以组合在一起使用。本文介绍了LoadImaged,EnsureChannelFirstd,Resized等基本函数的使用方法,大家跟着练习后能够很快掌握这些函数,也能为理解和运用官方提供的其他函数打下良好的基础,因为这些函数的应用模式都是相似的。另外,轻松上手transforms代码文件已上传至资料区,如有需要大家也可以下载比对。
参考
[1]基于Kaggle学习MONAI(二)轻松上手 transforms(上)-CSDN博客