【问题标题】:Why does tensorflow decode jpeg images differently from scipy imread?为什么 tensorflow 解码 jpeg 图像与 scipy imread 不同?
【发布时间】:2017-07-19 16:13:26
【问题描述】:

Tensorflow 的tf.image.decode_jpeg() 函数对jpg 图像给出的数值结果与scipy.misc.imread() 不同。虽然图像看起来相似,但像素值不同。

import numpy as np
import scipy
import tensorflow as tf
import matplotlib.pyplot as plt
def minimal_example():
    def _bytes_feature(value):
        return tf.train.Feature(bytes_list=tf.train.BytesList(value=[value]))

    tffilename = 'astronaut.tfrecords'
    writer = tf.python_io.TFRecordWriter(tffilename)
    #image_source = 'https://upload.wikimedia.org/wikipedia/commons/8/88/Astronaut-EVA.jpg'
    image_path = 'astronaut.jpg'
    image_file = open(image_path,'rb')
    image = image_file.read()
    image_scipy = scipy.misc.imread(image_path)
    example = tf.train.Example(features=tf.train.Features(feature={'image':_bytes_feature(image)}))
    writer.write(example.SerializeToString())
    writer.close()

    record_iterator = tf.python_io.tf_record_iterator(path=tffilename)
    example = tf.train.Example()
    example.ParseFromString(next(record_iterator))
    image = example.features.feature['image'].bytes_list.value[0]
    image_tf = tf.image.decode_jpeg(image).eval(session=tf.Session())
    fig = plt.figure()
    ax1 = fig.add_subplot(121)
    ax2 = fig.add_subplot(122)
    ax1.imshow(image_scipy)
    ax2.imshow(image_tf)
    print('Reconstruction Error', np.sum(np.abs(image_tf - image_scipy)))
    plt.show()

结果:

Reconstruction Error 3420883624

这是一个错误还是我做错了什么?

【问题讨论】:

    标签: python-3.x tensorflow scipy


    【解决方案1】:

    差异是由于 Tensorflow 使用的不准确但快速的默认离散余弦变换引起的

    根据Source code

    // TensorFlow 选择的 jpeg 解码默认是 IFAST,牺牲

    // 速度的图像质量。

    flags_.dct_method = JDCT_IFAST;

    为了获得准确的解码,可以设置属性dct_method = 'INTEGER_ACCURATE',如下例所示

    def minimal_example():
        #image_source = 'https://upload.wikimedia.org/wikipedia/commons/8/88/Astronaut-EVA.jpg'
        image_path = 'astronaut.jpg'
        image_file = open(image_path,'rb')
        image_raw = image_file.read()
        image_scipy = scipy.misc.imread(image_path)
        image_tf = tf.image.decode_jpeg(image_raw).eval(session=tf.Session())
        image_tf_accurate = tf.image.decode_jpeg(image_raw,dct_method="INTEGER_ACCURATE").eval(session=tf.Session())
        print('Error For Default: ', np.sum(np.abs(image_tf - image_scipy)))
        print('Error For Accurate: ', np.sum(np.abs(image_tf_accurate - image_scipy)))
        #Error For Default:  3420883624
        #Error For Accurate:  0
    

    【讨论】:

      【解决方案2】:

      The JPEG standard does not require bit-to-bit identical decoding。因此,不同的实现之间会出现一些差异。

      不过还是需要

      每个像素分量最多相差 1 位。

      因此,两个输出之间的距离不应超过一个。对吧?

      print('max diff: ', np.max(np.abs(image_tf.astype(float) - image_scipy.astype(float))))
      # max diff:  17.0
      

      哎呀,至少有一个实现不符合标准……

      【讨论】:

      • 第一次听说。很有意思! scipy 似乎使用 libjpeg-dev(通过 PIL/Pillow),而 tensorflow 可能使用 libjpeg-turbo
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2019-04-23
      • 2019-01-30
      • 2020-03-17
      • 2020-10-02
      • 1970-01-01
      • 2018-04-28
      • 1970-01-01
      相关资源
      最近更新 更多