【问题标题】:Inconsistency between image resizing with Keras (PIL) and TensorFlow?使用 Keras (PIL) 和 TensorFlow 调整图像大小不一致?
【发布时间】:2019-06-27 01:42:51
【问题描述】:

我被以下之间明显的不一致所困扰:

  1. 来自 keras.preprocessing 的图像大小调整功能,它们是 PIL 函数的包装器
  2. TensorFlow 的tf.image 中的图像大小调整功能。

我正在使用 Keras 为计算机视觉任务训练一个深度学习模型(实际上是使用 tf.keras,但这并不重要)。然后我使用 TF Serving 为模型提供服务,这需要我将图像作为编码的字节字符串发送到模型,在通过模型图之前使用tf.image.decode_png 对其进行解码。

当我调整图像大小时出现问题。 使用双线性插值(或任何其他方法)调整大小与使用 tf.image 相比,使用 PIL 会产生不同的结果,以至于模型的分类会根据我使用的函数而改变。

下面的代码提供了一个可重现的示例。

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')

现在,让我们以两种方式加载图像。首先使用 Keras 的 PIL 包装器,如在模型训练期间,然后编码为二进制字符串并使用 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,因为 Keras 已将图像转换为 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 调整图像大小时相同的输出。这很烦人,因为它让我在训练和测试结果之间出现偏差。有没有人知道是什么导致了这种行为,或者如何解决它?

【问题讨论】:

    标签: python tensorflow keras deep-learning python-imaging-library


    【解决方案1】:

    所描述的行为完全符合本文中所写的内容:How Tensorflow’s tf.image.resize stole 60 days of my life

    简而言之:是的,PIL/sklearn/OpenCV 和其他用于图像处理的常用库具有正确的行为,而 tf.image.resize 具有不同的行为,不会为了不破坏旧的训练模型而改变。

    因此,您应该始终使用计算图之外的相同库对图像进行预处理。

    相关github线程链接:https://github.com/tensorflow/tensorflow/issues/6720

    【讨论】:

    猜你喜欢
    • 2017-04-01
    • 1970-01-01
    • 2012-12-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-09-29
    • 1970-01-01
    • 2016-10-04
    相关资源
    最近更新 更多