Несоответствие между изменением размера изображения с помощью Keras (PIL) и TensorFlow? - PullRequest
0 голосов
/ 02 февраля 2019

Я обнаружил несоответствие между:

  1. функциями изменения размера изображения из keras.preprocessing, которые являются обертками для функций PIL
  2. функциями изменения размера изображения в tf.image TensorFlow.

Я тренирую модель глубокого обучения для задачи по компьютерному зрению с Керасом (на самом деле, с tf.keras, но здесь это не имеет значения).Затем я обслуживаю модель с помощью TF Serving, что требует от меня отправки изображений в модель в виде закодированных байтовых строк, где они декодируются с использованием tf.image.decode_png перед прохождением графа модели.

Проблема возникает, когда яизменить размер изображения. Изменение размера с помощью билинейной интерполяции (или любого другого метода) дает разные результаты с PIL по сравнению с tf.image, до такой степени, что классификация по модели изменяется в зависимости от того, какую функцию я использую.

Код ниже предоставляет воспроизводимый пример.

import numpy as np 
from PIL import Image
from keras.preprocessing.image import load_img, img_to_array
import tensorflow as tf

# Generate an 'image' with numpy, save as png
np.random.seed(42)
image = np.random.randint(0, 255, size=(256, 256, 3)).astype(np.uint8)
Image.fromarray(image).convert("RGB").save('my_image.png')

Теперь давайте загрузим изображение двумя способами.Сначала с оболочками PIL от Keras, как во время обучения модели, затем кодируются в виде двоичной строки и декодируются с помощью функций TensorFlow, как на моем сервере моделей.

# Using Keras PIL wrappers
keras_image = img_to_array(load_img('./my_image.png')) 

# Using TF functionalities
with tf.Session() as sess:
    with open('./my_image.png', 'rb') as f:
        tf_image_ = tf.image.decode_png(f.read())
    tf_image = sess.run(tf_image_)

Пока все хорошо, так как оба изображенияточно так же (кроме dtype, когда Керас преобразовал изображение в float32):

# Assert equality
np.array_equal(keras_image, tf_image)
> True

Повторение этого кода с изменением размера, однако, дает другой результат:

# Using Keras PIL wrappers, with resizing
keras_image_rs = img_to_array(load_img('./my_image.png',
                             target_size=(224, 224),
                             interpolation='bilinear'))

# Using TF functionalities, with resizing
with tf.Session() as sess:
    with open('./my_image.png', 'rb') as f:
        tf_image_ = tf.image.decode_png(f.read())
        # Add and remove dimension
        # As tf.image.resize_* requires a batch dimension
        tf_image_ = tf.expand_dims(tf_image_, 0)
        tf_image_ = tf.image.resize_bilinear(tf_image_,
                                            [224, 224], 
                                             align_corners=True)
        tf_image_ = tf.squeeze(tf_image_, axis=[0])

    tf_image_rs = sess.run(tf_image_)

# Assert equality
np.array_equal(keras_image_rs, tf_image_rs)
> False

Среднееабсолютная разница между двумя изображениями не является ничтожной:

np.mean(np.abs(keras_image_rs - tf_image_rs))
7.982703

Я играл с аргументом align_corners и пробовал и другие доступные методы интерполяции.Ни один из них не дает такой же вывод, как при изменении размера изображения с помощью PIL.Это довольно раздражает, поскольку дает мне перекос между тренировками и результатами тестирования.Кто-нибудь имеет представление о том, что вызывает такое поведение, или о том, как это исправить?

1 Ответ

0 голосов
/ 02 февраля 2019

Описанное поведение полностью соответствует написанному в этой статье: Как Tensorflow's tf.image.resize украл 60 дней моей жизни

Короче говоря: да, PIL / sklearn / OpenCV идругие распространенные библиотеки для работы с изображениями имеют правильное поведение, в то время как tf.image.resize имеет другое поведение, которое не будет изменено, чтобы не сломать старые обученные модели.

Следовательно, вы всегда должны предварительно обрабатывать свое изображениеиспользуя ту же библиотеку за пределами вычислительного графа.

Ссылка на соответствующий поток github: https://github.com/tensorflow/tensorflow/issues/6720

...