如何在 Tensorflow 2.0 中将 imgaug 增强应用到 tf.dataDataset

how to apply imgaug augmentation to tf.dataDataset in Tensorflow 2.0

我有一个带有输入管道的应用程序,该管道使用 tf.data.Dataset 图像和标签。现在我想使用扩充,并且我正在尝试使用 imgaug 库来达到这个目的。但是,我不知道该怎么做。我找到的所有示例都使用 Keras ImageDataGeneratorSequence.

在代码中,给定一个像这样的顺序增强器

  self.augmenter = iaa.Sequential([
        iaa.Fliplr(config.sometimes),
        iaa.Crop(percent=config.crop_percent),
        ...
        ], random_order=config.random_order)

我正在尝试将该增强器应用于我的数据集中的成批图像,但没有成功。似乎我无法评估张量,因为我是 运行 我在 map 函数中的扩充。

def augment_dataset(self, dataset):
    dataset = dataset.map(self.augment_fn())
    return dataset

def augment_fn(self):
    def augment(images, labels):
        img_array = tf.make_ndarray(images)
        images = self.augmenter.augment_images(img_array) 
        return images, labels
    return augment

例如,如果我尝试使用 make_ndarray,我会得到一个 AttributeError'Tensor' object has no attribute 'tensor_shape'

这是因为 Dataset.map 没有使用 eager 模式吗?。关于如何处理这个问题的任何想法?

更新#1

我试过建议tf.numpy_function,如下

def augment_fn(self):
    def augment(images, labels):
        images = tf.numpy_function(self.augmenter.augment_images,
                                   [images],
                                   images.dtype)
        return images, labels
    return augment

但是,生成的图像具有未知形状,这会导致以后出现其他错误。如何保持图像的原始形状?在应用增强功能之前,我的一批图像的形状为 (batch_size, None, None, 1),但之后的形状为 <unknown>

更新 #2

我通过首先找到图像的动态(真实)形状然后重塑应用增强的结果解决了未知形状的问题

def augment_fn(self):
    def augment(images, labels):
        img_dtype = images.dtype
        img_shape = tf.shape(images)
        images = tf.numpy_function(self.augmenter.augment_images,
                                   [images],
                                   img_dtype)
        images = tf.reshape(images, shape = img_shape)
        return images, labels
    return augment

Is this due to non using eager mode? I thought Eager mode was default in TF2.0. Any ideas on how to approach this?

是的,数据集预处理不在eager模式下执行。我认为,如果您认为数据集可以表示任意大(甚至无限)的数据流,那么这是经过深思熟虑的并且肯定是有意义的。

假设你不possible/practical将你正在做的增强转化为tensorflow操作(这将是第一选择!)那么你可以使用tf.numpy_function执行任意python 代码(这是现在已弃用的 tf.py_func 的替代品)

请转至 TF Dataset documentation 了解为什么在使用 tf.py_function

时需要 return 图像形状
def tf_random_rotate_image(image, label):
    im_shape = image.shape
    [image,] = tf.py_function(random_rotate_image, [image], [tf.float32])
    image.set_shape(im_shape)
    return image, label