深度学习三维图像数据增强——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的调用数据类型,官方支持以下格式:
- 字符串 :需是数据文件的路径,通过LoadImage可加载数据;
- 数据 :数据类型为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 Transforms
和Dictionary Transforms
,顾名思义,Dictionary Transforms
适用于指定数据中的字典进行转换,两种转换函数之间只差一个字母d,下面介绍常见的转换类型及两种转换函数。
5.1裁减和填充
Vanilla Transforms | Dictionary Transforms | |
---|---|---|
指定值填充(可指定每个维度的值) | pad | padd |
空间对称填充 | SpatialPad | SpatialPadd |
边缘填充(指定边框) | BorderPad | BorderPadd |
指定区域裁减 | SpatialCrop | SpatialCropd |
5.2强度增强
Vanilla Transforms | Dictionary Transforms | |
---|---|---|
随机Guass噪声 | RandGaussianNoise | RandGaussianNoised |
随机强度偏移 | RandShiftIntensity | RandShiftIntensityd |
MR图像的随机偏置场增强 | RandBiasField | RandBiasFieldd |
随机对比度调整 | RandAdjustContrast | RandAdjustContrastd |
图像锐化 | RandGaussianSharpen | RandGaussianSharpend |
强度归一化(标准化) | NormalizeIntensity | NormalizeIntensityd |
Guass平滑 | GaussianSmooth | GaussianSmoothd |
直方图正态化 | HistogramNormalize | HistogramNormalized |
5.3空间增强
Vanilla Transforms | Dictionary Transforms | |
---|---|---|
随机旋转 | RandRotate | RandRotated |
随机指定轴翻转 | RandFlip | RandFlipd |
随机任意轴翻转 | RandAxisFlip | RandAxisFlipd |
随机仿射变换 | RandAffine | RandAffined |
随机3D弹性变形 | Rand3DElastic | Rand3DElasticd |
随机旋转90度 | RandRotate90 | RandRotate90d |
此外还有平滑处理和针对于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部分