How can I save and read variable size images in TensorFlow's protobuf format
<p>I'm trying to write variable size images in TensorFlow's protobuf format with the following code:</p>

<pre><code>img_feature = tf.train.Feature(
    bytes_list=tf.train.BytesList(value=[
        img.flatten().tostring()]))
# Define how the sequence length is stored
seq_len_feature = tf.train.Feature(
    int64_list=tf.train.Int64List(value=[seq_len]))
# Define how the label list is stored
label_list_feature = tf.train.Feature(
    int64_list=tf.train.Int64List(value=label_list))
# Define the feature dictionary that defines how the data is stored
feature = {
    IMG_FEATURE_NAME: img_feature,
    SEQ_LEN_FEATURE_NAME: seq_len_feature,
    LABEL_LIST_FEATURE_NAME: label_list_feature}
# Create an example object to store
example = tf.train.Example(
    features=tf.train.Features(feature=feature))
</code></pre>

<p>Where the images <code>img</code> that I save has a fixed height but variable length.</p>

<p>Now if I want to parse this image with the following code:</p>

<pre><code># Define how the features are read from the example
features_dict = {
  IMG_FEATURE_NAME: tf.FixedLenFeature([], tf.string),
  SEQ_LEN_FEATURE_NAME: tf.FixedLenFeature([1], tf.int64),
  LABEL_LIST_FEATURE_NAME: tf.VarLenFeature(tf.int64),
}
features = tf.parse_single_example(
    serialized_example,
    features=features_dict)
# Decode string to uint8 and reshape to image shape
img = tf.decode_raw(features[IMG_FEATURE_NAME], tf.uint8)
img = tf.reshape(img, (self.img_shape, -1))
seq_len = tf.cast(features[SEQ_LEN_FEATURE_NAME], tf.int32)
# Convert list of labels
label_list = tf.cast(features[LABEL_LIST_FEATURE_NAME], tf.int32)
</code></pre>

<p>I get the following error: 
<code>ValueError: All shapes must be fully defined: [TensorShape([Dimension(28), Dimension(None)]), TensorShape([Dimension(1)]), TensorShape([Dimension(3)])]</code></p>

<p>Is there a way to store images with variable size (more specifically variable width in my case) and read them with <code>TFRecordReader</code>?</p>

<p>First, I was not able to reproduce the error. The following code works just fine:</p>

<pre><code>import tensorflow as tf
import numpy as np

image_height = 100
img = np.random.randint(low=0, high=255, size=(image_height,200), dtype='uint8')
IMG_FEATURE_NAME = 'image/raw'

with tf.Graph().as_default():
  img_feature = tf.train.Feature(
      bytes_list=tf.train.BytesList(value=[
          img.flatten().tostring()]))
  feature = {IMG_FEATURE_NAME: img_feature}

  example = tf.train.Example(features=tf.train.Features(feature=feature))
  serialized_example = example.SerializeToString()

  features_dict = {IMG_FEATURE_NAME: tf.FixedLenFeature([], tf.string)}
  features = tf.parse_single_example(serialized_example, features=features_dict)
  img_tf = tf.decode_raw(features[IMG_FEATURE_NAME], tf.uint8)
  img_tf = tf.reshape(img_tf, (image_height, -1))

  with tf.Session() as sess:
    img_np = sess.run(img_tf)

  print(img_np)

print('Images are identical: %s' % (img == img_np).all())
</code></pre>

<p>It outputs:</p>

<blockquote>
  <p>Images are identical: True</p>
</blockquote>

<p>Second, I'd recommend to store images encoded as PNG instead of RAW and read them using tf.VarLenFeature+tf.image.decode_png. It will save you a lot of space and naturally supports variable size images.</p>

python tensorflow protocol-buffers