I'm trying to decode images that I have encoded (tf.io.serialize_tensor(object).numpy()) as ByteFeatures within a TFRecord. I've narrowed down the error to the decoding of the image and mask fields but am unable to find a solution.
Troubleshooting steps:
- Perform encoding and decoding outside of the functions. This performed as intended.
- Attempted to reshape the images (seen commented out below). Failed
- Attempted tf.ensure_shape. Failed due to the shape not conforming.
Observations:
- When printing the shape of the tf.io.parse_tensor within the function, the shape returns unknown
- Error message shows the shape as [640, 3] instead of [640,640,3]
- I'm surprised my desk isn't broken
Any guidance?
def decode_tfrecord(record):
features = tf.io.parse_single_example(
record,
{
'age': tf.io.FixedLenFeature([], tf.float32),
'image': tf.io.FixedLenFeature([], tf.string),
'mask': tf.io.FixedLenFeature([], tf.string),
'organ': tf.io.FixedLenFeature([], tf.string),
'sex': tf.io.FixedLenFeature([], tf.string)
}
)
image = tf.ensure_shape(tf.io.parse_tensor(features['image'], out_type=tf.float32), (640,640,3))
# image = tf.reshape(image, [640,640,3])
mask = tf.io.parse_tensor(features['mask'], out_type=tf.float32)
# print(mask.shape)
# mask = tf.reshape(mask, [640, 640, 1])
# mask = tf.cast(mask, tf.uint8)
organ = features['organ']
age = features['age']
sex = features['sex']
return image, mask, organ, age, sex
def get_train_ds(ds):
FNAMES_TRAIN_TFRECORDS = tf.io.gfile.glob('tfrecords/*.tfrecords')
train_ds = tf.data.TFRecordDataset(
FNAMES_TRAIN_TFRECORDS,
num_parallel_reads=1
)
train_ds = train_ds.map(
decode_tfrecord,
num_parallel_calls=multiprocessing.cpu_count()
)
train_ds = train_ds.batch(ds)
return train_ds
def show_batch(ds, rows=10, cols=3):
images, masks, organs, age, sex = next(iter(ds))
fig, ax = plt.subplots(nrows=rows, ncols=cols, figsize=(cols*6, rows*6))
for r in range(rows):
ax[r, 0].imshow(images[r])
organ = organs[r].numpy().decode('UTF-8')
ax[r, 0].set_title(f'Image {r} - Organ: {organ}')
ax[r, 0].axis('off')
ax[r, 1].imshow(masks[r])
ax[r, 1].set_ have a strong desktitle(f'Mask {r}')
ax[r, 1].axis('off')
ax[r, 2].imshow(images[r])
ax[r, 2].imshow(masks[r], alpha=0.5)
ax[r, 2].set_title(f'Image {r} + Mask {r}')
ax[r, 2].axis('off')
When ran I get the following error code:
---------------------------------------------------------------------------
InvalidArgumentError Traceback (most recent call last)
/home/kyle/Desktop/kaggle/eda.ipynb Cell 31 in <cell line: 2>()
1 train_ds = get_train_ds(10)
----> 2 show_batch(train_ds)
/home/kyle/Desktop/kaggle/eda.ipynb Cell 31 in show_batch(ds, rows, cols)
44 def show_batch(ds, rows=10, cols=3):
---> 45 images, masks, organs, age, sex = next(iter(ds))
47 fig, ax = plt.subplots(nrows=rows, ncols=cols, figsize=(cols*6, rows*6))
48 for r in range(rows):
File ~/anaconda3/envs/tensorflow/lib/python3.9/site-packages/tensorflow/python/data/ops/iterator_ops.py:766, in OwnedIterator.__next__(self)
764 def __next__(self):
765 try:
--> 766 return self._next_internal()
767 except errors.OutOfRangeError:
768 raise StopIteration
File ~/anaconda3/envs/tensorflow/lib/python3.9/site-packages/tensorflow/python/data/ops/iterator_ops.py:749, in OwnedIterator._next_internal(self)
746 # TODO(b/77291417): This runs in sync mode as iterators use an error status
747 # to communicate that there is no more data to iterate over.
748 with context.execution_mode(context.SYNC):
--> 749 ret = gen_dataset_ops.iterator_get_next(
750 self._iterator_resource,
...
7163 e.message += (" name: " + name if name is not None else "")
-> 7164 raise core._status_to_exception(e) from None
InvalidArgumentError: Shape of tensor ParseTensor [640,3] is not compatible with expected shape [640,640,3].
[[{{node EnsureShape}}]] [Op:IteratorGetNext]