深度学习三维图像数据增强——Monai实现

  • 一、前言
  • 二、数据类型
  • 三、Compose
  • 四、OneOf
  • 五、常见转换类型
    • 5.1裁减和填充
    • 5.2强度增强
    • 5.3空间增强
  • 六、注意(记录坑)
    • 6.1 RandRotate90

一、前言

笔者接触深度学习不久,跑过一些二维图像的深度学习代码,对于二维图像,深度学习数据增强可借助skimage、opencv、imgaug、Albumentations、Augmentor等多数主流的库实现,在这里放一个大神的链接,可供参考。但对于三维数据,能够借助的库便少了起来,常用的有TorchIO和Monai,而针对于医学领域,Monai是一个不错的选择。笔者通过自学,将Monia库总结以下要点。

详细可参考Monai官方文档:https://docs.monai.io/en/1.1.0/transforms.html

二、数据类型

对于Monai的调用数据类型,官方支持以下格式:

  1. 字符串 :需是数据文件的路径,通过LoadImage可加载数据;
  2. 数据 :数据类型为Numpy ndarray或PyTorch Tensor,数据的大小通常为(num_channels,spatial_dim_1[,spatial_dim_2,…])。在深度学习中,Dataset返回的数据类型通常是[C,D,H,W],C即代表通道数,D,H,W分别是三维数据的深度、高度、宽度;同样,在Monai中,即使通道是1,通道数也不可被省略官方推荐包含通道数,但在实际使用过程中,我发现并未有严格的限制,不包含也可正常运行

需要注意的是,无论输入是numpy.ndarray还是torch.tensor类型,多数转换输出为torch.tensor,

三、Compose

通常,在做数据增强时,我们需要用到批量操作,Monai也提供了相应的Compose批量转换操作。官方的解释是:Compose提供了以顺序方式将一系列可调用项链接在一起的能力。序列中的每个转换都必须接受一个参数并返回一个值。
Compose的调用有两种方式,如下:
1.通过一系列转换,接受并返回单个ndarray/tensor/类张量参数。
2.通过一系列转换,接受并返回包含一个或多个参数的字典。此类转换必须具有传递语义,即字典中未使用的值必须复制到返回字典。需要在每个变换的输入和输出之间复制字典。

对于监督学习,我们通常希望将图像数据和标签数据做同类型的转换,因此,Monai的第二种Compose调用方式极大地方便了我们使用。下面,以一串代码为例介绍该使用方式:

import torchfrom monai.transforms import Compose, RandHistogramShiftD, Flipd, Rotate90d#批量转换KEYS = ("image", "label")class aug():def __init__(self):self.random_rotated = Compose([Rotate90d(KEYS, k=1, spatial_axes=(2,3),allow_missing_keys=True),Flipd(KEYS, spatial_axis=(1,2,3),allow_missing_keys=True),RandHistogramShiftD(KEYS,prob=1, num_control_points=30, allow_missing_keys=True),# ToTensorD(KEYS),])def forward(self,x):x = self.random_rotated(x)return x

上述代码忽略了Compose的其余参数,Compose的完整调用是:

Compose([transformA, transformB, transformC], map_items=True, unpack_items=False, log_stats=False)

mapitems(bool)–如果数据是列表或元组,是否对输入数据中的每个项应用转换。默认为True。
unpackitems(bool)–是否使用*作为转换的可调用函数的参数来解压缩输入数据。默认为False。
log_stats(bool)–发生错误时是否记录数据和应用的转换的详细信息,对于NumPy数组和PyTorch Tensor,记录数据形状和值范围,对于其他元数据,直接记录值。默认为False。
在这里做一个提示:并非所有的转换都需要标签和图像一起转换,如图像的标准化,标签并不需要,标签仅需与图像一起进行旋转、平移、翻转或变形,因此,Compose需和其他一系列转换结合使用。

四、OneOf

有时我们需要进行多种转换中的一种即可,便可采用OneOf进行编写,以下是OneOf的各参数:

monai.transforms.OneOf(transforms=None, weights=None, map_items=True, unpack_items=False, log_stats=False)

transform即为可调用函数的序列;weights为对应于变换中每个函数的调用概率,概率归一化为1;其余参数不再详细介绍。

五、常见转换类型

Monai的转换分为Vanilla TransformsDictionary Transforms,顾名思义,Dictionary Transforms适用于指定数据中的字典进行转换,两种转换函数之间只差一个字母d,下面介绍常见的转换类型及两种转换函数。

5.1裁减和填充

Vanilla TransformsDictionary Transforms
指定值填充(可指定每个维度的值) padpadd
空间对称填充SpatialPadSpatialPadd
边缘填充(指定边框)BorderPadBorderPadd
指定区域裁减SpatialCropSpatialCropd

5.2强度增强

Vanilla TransformsDictionary Transforms
随机Guass噪声RandGaussianNoiseRandGaussianNoised
随机强度偏移RandShiftIntensityRandShiftIntensityd
MR图像的随机偏置场增强RandBiasFieldRandBiasFieldd
随机对比度调整RandAdjustContrastRandAdjustContrastd
图像锐化RandGaussianSharpenRandGaussianSharpend
强度归一化(标准化)NormalizeIntensityNormalizeIntensityd
Guass平滑GaussianSmoothGaussianSmoothd
直方图正态化HistogramNormalizeHistogramNormalized

5.3空间增强

Vanilla TransformsDictionary Transforms
随机旋转RandRotateRandRotated
随机指定轴翻转RandFlipRandFlipd
随机任意轴翻转RandAxisFlipRandAxisFlipd
随机仿射变换RandAffineRandAffined
随机3D弹性变形Rand3DElasticRand3DElasticd
随机旋转90度RandRotate90RandRotate90d

此外还有平滑处理和针对于MRI的处理,详见官方文档。

六、注意(记录坑)

6.1 RandRotate90

RandRotate90(prob=0.5, spatial_axes=(1, 2)),这里的spatial_axes=(1, 2)是针对数据格式为(z,y,x)设置的,如果你的数据格式为(x,y,z)那么就是spatial_axes=(0,1)

持续记载并更新中…

这里再放一些大神的文章及相关参考资料:
1.使用MONAI深度学习框架进行3D图像空间变换
2.医学图像深度学习3D数据增强之MONAI框架方法利用
3.Monai官方文档Transforms部分