由于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
设置参数。我会尽快更新。