Reputation: 633
I applied the method in this github to write JPEG files into .tfrecords. But I have issues when parsing them.
Here's my code for writing the tfrecords, each x_img
is a numpy array, and each x_img[i]
contains fixed amount of img_bytes
img_bytes = open(join(frames_path, vid, img_list[current]),'rb').read()
...
"x_img": tf.train.Feature( bytes_list = tf.train.BytesList( value= x_img[i])),
When parsing, I did this:
def parse_func(example_proto):
# FEATURES
feature_description = {
"x_img": tf.io.VarLenFeature(tf.string),
}
feat = tf.io.parse_single_example(example_proto, feature_description)
x = {}
x_img = tf.sparse.to_dense(feat["x_img"])
x_img = tf.io.decode_jpeg(x_img, channels = 3)
x["x_img"] = x_img/255
return x
But it returns error:
ValueError: Shape must be rank 0 but is rank 1 for 'DecodeJpeg' (op: 'DecodeJpeg') with input shapes: [?].
What is the right way to decode a JPEG which was previously stored in bytes?
Upvotes: 1
Views: 338
Reputation: 633
tf.io.decode_jpeg
works fine. The reason I got the error is that I shaped the input as (n, width, height, 3)
. But the function decode_jpeg
only works on a single image instead of n images.
By writing:
x_img = tf.stack([
tf.io.decode_jpeg(x_images[0], channels = 3),
tf.io.decode_jpeg(x_images[1], channels = 3),
tf.io.decode_jpeg(x_images[2], channels = 3),
])
I could recover the bytes to JPEG. The more efficient way is using list comprehension, but unfortunately, list comprehension is not supported now (see here).
The reason for writing bytes into .tfrecords
instead of using plt.imread()
or cv2.imread()
is that it doesn't decompress the image, so the process would be much faster and space-efficient. I didn't calculate it precisely, but decompressing JPEG images leads ~6x increase in disk space.
Upvotes: 1