使用数据增强的Keras 3D体积图像生成器

11

由于Keras的ImageDataGenerator不适用于3D体积,因此我开始为Keras(语义分割而非分类!)编写自己的生成器。

1)如果有人已经将ImageDataGenerator代码适应于3D体积,请分享!这位已经为视频完成了这项工作。

2)根据这个教程,我编写了一个自定义生成器。


import glob
import os

import keras
import numpy as np
import skimage
from imgaug import augmenters as iaa


class DataGenerator(keras.utils.Sequence):
    """Generates data for Keras"""
    """This structure guarantees that the network will only train once on each sample per epoch"""

    def __init__(self, list_IDs, im_path, label_path, batch_size=4, dim=(128, 128, 128),
                 n_classes=4, shuffle=True, augment=False):
        'Initialization'
        self.dim = dim
        self.batch_size = batch_size
        self.list_IDs = list_IDs
        self.im_path = im_path
        self.label_path = label_path
        self.n_classes = n_classes
        self.shuffle = shuffle
        self.augment = augment
        self.on_epoch_end()

    def __len__(self):
        'Denotes the number of batches per epoch'
        return int(np.floor(len(self.list_IDs) / self.batch_size))

    def __getitem__(self, index):
        'Generate one batch of data'
        # Generate indexes of the batch
        indexes = self.indexes[index * self.batch_size:(index + 1) * self.batch_size]

        # Find list of IDs
        list_IDs_temp = [self.list_IDs[k] for k in indexes]

        # Generate data
        X, y = self.__data_generation(list_IDs_temp)

        return X, y

    def on_epoch_end(self):
        'Updates indexes after each epoch'
        self.indexes = np.arange(len(self.list_IDs))
        if self.shuffle == True:
            np.random.shuffle(self.indexes)

    def __data_generation(self, list_IDs_temp):

        if self.augment:
            pass

        if not self.augment:

            X = np.empty([self.batch_size, *self.dim])
            Y = np.empty([self.batch_size, *self.dim, self.n_classes])

            # Generate data
            for i, ID in enumerate(list_IDs_temp):
                img_X = skimage.io.imread(os.path.join(im_path, ID))
                X[i,] = img_X

                img_Y = skimage.io.imread(os.path.join(label_path, ID))
                Y[i,] = keras.utils.to_categorical(img_Y, num_classes=self.n_classes)

            X = X.reshape(self.batch_size, *self.dim, 1)
            return X, Y

params = {'dim': (128, 128, 128),
          'batch_size': 4,
          'im_path': "some/path/for/the/images/",
          'label_path': "some/path/for/the/label_images",
          'n_classes': 4,
          'shuffle': True,
          'augment': True}



partition = {}
im_path = "some/path/for/the/images/"
label_path = "some/path/for/the/label_images/"

images = glob.glob(os.path.join(im_path, "*.tif"))
images_IDs = [name.split("/")[-1] for name in images]

partition['train'] = images_IDs

training_generator = DataGenerator(partition['train'], **params)

我的图片尺寸为(128, 128, 128),加载后得到的是一个大小为(batch_size, depth, height, width, number_of_channels)的5D张量,例如(4, 128, 128, 128, 1)。对于标签图片(具有相同的维度并且是单通道编码(值1=标签1,值2=标签2,值3=标签3和值0=标签4或背景)),我使用keras的to_categorical()函数得到标签的二进制表示,最终得到一个5D张量,例如(4, 128, 128, 128, 4)。图像和标签图片具有相同的名称,但位于不同的文件夹中。

由于我的图像很少,我希望通过图像增强来扩展总数。如何在生成器中实现这一点?我已经成功测试了imgaug包,但是我只是转换现有图像(例如水平翻转),而没有将图像添加到我的数据集中。

编辑:我对数据增强存在误解。请参阅关于图像增强的这篇文章。将随机变换的图像传入(即时变换)。现在我只需要收集足够的数据,并使用imgaug设置参数。我会尽快更新。


你好 Johannes:请问你的问题是否已经解决?谢谢! - user11530462
您好,TensorFlow支持团队!我已经转向PyTorch,因为我发现了Elektronn3。基于此,我可以为我的自定义3D数据集编写高效的代码。可能很快会再次尝试使用Keras来比较这两个框架。 - Johannes Schmidt
2
我投票关闭这个问题,因为我似乎找不到你的问题,如果你有的话。 - Nicolas Gervais
1个回答

1

我找到了一个针对3D体积的Keras自定义数据生成器实现。这里是GitHub链接。该实现可以轻松扩展以包括新的增强技术。以下是我在我的项目(基于3D体积语义分割)中使用的最小工作示例,基于我在链接中分享的实现:

from generator import customImageDataGenerator

def generator(images, groundtruth, batch):
    """Load a batch of augmented images"""
  
    gen = customImageDataGenerator(mirroring=True, 
                                   rotation_90=True,
                                   transpose_axes=True
                                   )

    for b in gen.flow(x=images, y=groundtruth, batch_size=batch):
        yield (b[0], (b[1]).astype(float))

# images = (123, 48,48,48,1)
# groundtruth = (123, 48,48,48,1)
history = model.fit(
    x=generator(images, groundtruth, batchSize),
    validation_data=(imagesTest, groundtruthTest),
    steps_per_epoch=len(images) / batchSize,
    epochs=epochs,
    callbacks=[callbacks],
    )

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接