Гауссово размытое изображение в конвейере набора данных в тензорном потоке - PullRequest
0 голосов
/ 11 декабря 2019

Я хочу, чтобы часть моего дополнения данных применяла размытие по Гауссу к моим обучающим данным.

Для этого я создал собственный класс Initializer, который инициализирует DepthwiseConv2d для получения желаемого ядра Гаусса.

Но я получаю следующую ошибку:

tensorflow.python.framework.errors_impl.FailedPreconditionError:  {{function_node __inference_Dataset_map_<lambda>_67}} Error while reading resource variable _AnonymousVar0 from Container: localhost. This could mean that the variable was uninitialized. Not found: Resource localhost/_AnonymousVar0/class tensorflow::Var does not exist.
     [[{{node depthwise_conv2d/depthwise/ReadVariableOp}}]]
     [[IteratorGetNext]] [Op:__inference_distributed_function_694]

Вот простой рабочий пример:

import tensorflow as tf


class GaussianInitializer(tf.keras.initializers.Initializer):
    def __init__(self):
        super().__init__()
        self.sigma = 2

    def _gaussian_kernel(self, kernel_size, dtype):
        x = tf.range(-kernel_size // 2 + 1, kernel_size // 2 + 1, dtype=dtype)
        g = tf.math.exp(-(tf.pow(x, 2) / (2 * tf.pow(tf.cast(self.sigma, dtype), 2))))
        g_norm2d = tf.pow(tf.reduce_sum(g), 2)
        return tf.tensordot(g, g, axes=0) / g_norm2d

    def __call__(self, shape, dtype):
        kernel = tf.expand_dims(self._gaussian_kernel(shape[0], dtype), axis=-1)
        return tf.expand_dims(tf.tile(kernel, (1, 1, shape[2])), axis=-1)


def gaussian_blur_img(img):
    blur_layer = tf.keras.layers.DepthwiseConv2D(
        kernel_size=5, padding='same', use_bias=False,
        depthwise_initializer=GaussianInitializer(), dtype=img.dtype
    )
    blur_layer.trainable = False
    return tf.squeeze(blur_layer(tf.expand_dims(img, axis=0)), axis=0)


data = tf.data.Dataset.from_tensor_slices(
    (tf.ones((1, 10, 10, 3)), tf.ones((1, 10, 10, 1)))
).map(lambda x, y: (gaussian_blur_img(x), y)).repeat().batch(10)


x = tf.keras.layers.Input((10, 10, 3))
y = tf.keras.layers.Conv2D(filters=1, kernel_size=1, activation=tf.keras.activations.relu)(x)

model = tf.keras.models.Model(inputs=[x], outputs=[y])
model.compile(loss=tf.losses.binary_crossentropy)
model.fit(data, steps_per_epoch=10, epochs=10)

Как обойти эту проблему?

1 Ответ

0 голосов
/ 11 декабря 2019

Пока не уверен, что не так с кодом выше, поэтому я не приму мой собственный ответ в надежде, что кто-то другой даст лучший ответ, который объяснит, что не так ... Редактировать: из-за того, что никто не вмешивается, яЯ выбираю свой собственный ответ.

Однако мне удалось создать работающий фильтр размытия по Гауссу, и написать его еще проще, используя tf.nn вместо tf.keras.layers:

def _gaussian_kernel(kernel_size, sigma, n_channels, dtype):
    x = tf.range(-kernel_size // 2 + 1, kernel_size // 2 + 1, dtype=dtype)
    g = tf.math.exp(-(tf.pow(x, 2) / (2 * tf.pow(tf.cast(sigma, dtype), 2))))
    g_norm2d = tf.pow(tf.reduce_sum(g), 2)
    g_kernel = tf.tensordot(g, g, axes=0) / g_norm2d
    g_kernel = tf.expand_dims(g_kernel, axis=-1)
    return tf.expand_dims(tf.tile(g_kernel, (1, 1, n_channels)), axis=-1)


def apply_blur(img):
    blur = _gaussian_kernel(3, 2, 3, img.dtype)
    img = tf.nn.depthwise_conv2d(img[None], blur, [1,1,1,1], 'SAME')
    return img[0]

data = tf.data.Dataset.from_tensor_slices(
    (tf.pad(tf.ones((1, 1, 1, 2)), ((0, 0),(1, 1),(1, 1),(0,1))), tf.ones((1, 3, 3, 1)))
).map(lambda x, y: (apply_blur(x), y)).repeat().batch(10)

Работает как положено.

...