sdc*_*cbr 12 python python-imaging-library deep-learning keras tensorflow
我被以下两者之间的明显不一致所困扰:
keras.preprocessing,它们是PIL函数的包装器tf.image.我正在为Keras的计算机视觉任务培训深度学习模型(实际上,有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')
Run Code Online (Sandbox Code Playgroud)
现在,让我们以两种方式加载图像.首先从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_)
Run Code Online (Sandbox Code Playgroud)
到目前为止一切都那么好,因为两个图像完全相同(除了dtype,因为Keras将图像转换为float32):
# Assert equality
np.array_equal(keras_image, tf_image)
> True
Run Code Online (Sandbox Code Playgroud)
但是,通过调整大小重复此代码会产生不同的结果:
# 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
Run Code Online (Sandbox Code Playgroud)
两幅图像之间的平均绝对差异是不可忽略的:
np.mean(np.abs(keras_image_rs - tf_image_rs))
7.982703
Run Code Online (Sandbox Code Playgroud)
我玩了这个align_corners参数,并尝试了其他可用的插值方法.无提供与使用PIL调整图像大小时相同的输出.这非常令人讨厌,因为它让我在训练和测试结果之间产生了偏差.有没有人知道导致这种行为的原因,或者如何解决这个问题?
所描述的行为完全符合本文所写的内容:Tensorflow的tf.image.resize如何偷走了我生命中的60天
简而言之:是的,PIL/sklearn/OpenCV和其他用于图像处理的公共库具有正确的行为,而tf.image.resize具有不同的行为,为了不破坏旧的训练模型而不会改变.
因此,您应始终使用计算图外部的相同库预处理图像.
链接到相关的github线程:https://github.com/tensorflow/tensorflow/issues/6720
| 归档时间: |
|
| 查看次数: |
824 次 |
| 最近记录: |