简体   繁体   中英

Tensorflow failed to decode jpeg bytes in tfrecords

I tried to write some images to a tfrecord file, but I found it is too large. Then I tried to write the origin jpeg bytes into The tfrecord file. but when I try to read it, there is exception: ValueError: Shape must be rank 0 but is rank 1 for 'DecodeJpeg' (op: 'DecodeJpeg') with input shapes: [32].

Followed is my code

import tensorflow as tf
import os


def write_features(example_image_paths, tf_records_path):
    with tf.python_io.TFRecordWriter(tf_records_path) as writer:
        for image_path in example_image_paths:
            with open(image_path, 'rb') as f:
                image_bytes = f.read()
            feautres = tf.train.Features(
                feautres={
                    'images':
                    tf.train.Feature(bytes_list=tf.train.BytesList(
                        value=image_bytes))
                })
            example = tf.train.Example(feautres)
            writer.write(example.SerializeToString())


def extract_features_batch(serialized_batch):
    """

    :param serialized_batch:
    :return:
    """
    features = tf.parse_example(
        serialized_batch,
        features={'images': tf.FixedLenFeature([], tf.string)})
    bs = features['images'].shape[0]
    images = tf.image.decode_image(features['images'], 3)
    w, h = (280, 32)
    images = tf.cast(x=images, dtype=tf.float32)
    images = tf.reshape(images, [bs, h, w, 3])

    return images


def inputs(tfrecords_path, batch_size, num_epochs, num_threads=4):
    """

    :param tfrecords_path:
    :param batch_size:
    :param num_epochs:
    :param num_threads:
    :return: input_images, input_labels, input_image_names
    """

    if not num_epochs:
        num_epochs = None

    dataset = tf.data.TFRecordDataset(tfrecords_path)

    dataset = dataset.batch(batch_size, drop_remainder=True)

    # The map transformation takes a function and applies it to every element
    # of the dataset.
    dataset = dataset.map(map_func=extract_features_batch,
                          num_parallel_calls=num_threads)
    dataset = dataset.shuffle(buffer_size=1000)
    dataset = dataset.repeat()

    iterator = dataset.make_one_shot_iterator()

    return iterator.get_next(name='IteratorGetNext')


if __name__ == '__main__':
    pass
    # img_names = os.listdir('./images')
    # img_paths = []
    # for img_name in img_paths:
    #     img_paths.append(os.path.join('./images', img_name))
    # write_features(img_paths, 'test.tfrecords')

    images = inputs('./test.tfrecords', 32, None)

How can I read and decode the jpeg bytes properly? Thanks!

You need to decode images before batching the dataset. In other words, in your inputs() function the 'correct' order would be:

dataset = dataset.map(map_func=extract_features_batch,
                      num_parallel_calls=num_threads) 

dataset = dataset.batch(batch_size, drop_remainder=True)

The documentation says ( https://www.tensorflow.org/api_docs/python/tf/io/decode_image ) that tf.io.decode_image expects an image in a form of a scalar or 0-dimensional string (0-D string is considered a scalar) while if you batch the dataset object first the tf.io.decode_image receives a list (or a batch) of images (represented as a list of batch_size times 0 dimensional strings). It then complains that it expected 0-dimensional array while received an array with the shape of [32] (which is the batch size in your case).

I have no idea about how we could optimize input pipeline for batch-processing other than inefficiently do batching after processing. As usual, there is nothing about it in docs on tf 2.0.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM