Ответ 1
Вы можете загружать изображения, вероятно, потому что вы сохранили их, используя тип функции tf.train.BytesList()
и данные всего изображения представляют собой одно большое значение байта внутри списка.
Если я прав, вы используете tf.decode_raw
чтобы получить данные из изображения, которое вы загружаете из TFRecord.
Что касается примеров использования: я использую VarLenFeature
для сохранения наборов данных для задачи обнаружения объектов: там переменное количество ограничивающих рамок на изображение (равное объекту на изображении), поэтому мне нужен другой объект objects_number
для отслеживания количества объектов (и bboxes). Каждый ограничивающий прямоугольник представляет собой список из 4-х координат с плавающей точкой
Я использую следующий код для загрузки:
features = tf.parse_single_example(
serialized_example,
features={
# We know the length of both fields. If not the
# tf.VarLenFeature could be used
'height': tf.FixedLenFeature([], tf.int64),
'width': tf.FixedLenFeature([], tf.int64),
'depth': tf.FixedLenFeature([], tf.int64),
# Label part
'objects_number': tf.FixedLenFeature([], tf.int64),
'bboxes': tf.VarLenFeature(tf.float32),
'labels': tf.VarLenFeature(tf.int64),
# Dense data
'image_raw': tf.FixedLenFeature([],tf.string)
})
# Get metadata
objects_number = tf.cast(features['objects_number'], tf.int32)
height = tf.cast(features['height'], tf.int32)
width = tf.cast(features['width'], tf.int32)
depth = tf.cast(features['depth'], tf.int32)
# Actual data
image_shape = tf.parallel_stack([height, width, depth])
bboxes_shape = tf.parallel_stack([objects_number, 4])
# BBOX data is actually dense convert it to dense tensor
bboxes = tf.sparse_tensor_to_dense(features['bboxes'], default_value=0)
# Since information about shape is lost reshape it
bboxes = tf.reshape(bboxes, bboxes_shape)
image = tf.decode_raw(features['image_raw'], tf.uint8)
image = tf.reshape(image, image_shape)
Обратите внимание, что "image_raw" имеет фиксированную длину Feature (имеет один элемент) и содержит значения типа "bytes", однако значение типа "bytes" само по себе может иметь переменный размер (это строка байтов и может содержать много символов внутри него).). Таким образом, "image_raw" - это список с ОДНЫМ элементом типа "байты", который может быть очень большим.
Для дальнейшего уточнения того, как это работает: объекты представляют собой списки значений, эти значения имеют определенный "тип".
Типы данных для объектов являются подмножеством типов данных для тензоров, у вас есть:
- int64 (64-битное пространство в памяти)
- байт (занимает столько байтов в памяти, сколько вы хотите)
- float (занимает 32-64 бита в idk памяти)
Вы можете проверить здесь типы данных тензоров.
Таким образом, вы можете хранить данные переменной длины VarLenFeatures
без VarLenFeatures
(на самом деле вы хорошо это делаете), но сначала вам нужно будет преобразовать их в байты/строковую функцию, а затем декодировать их. И это самый распространенный метод.