我试图将不同大小的图像保存到tf记录中。我发现,即使图像大小不同,我仍然可以使用FixedLenFeature
加载它们。
通过检查FixedLenFeature
和VarLenFeature
上的文档,我发现区别似乎是VarLenFeauture
返回稀疏张量。
有人能举例说明一些应该使用FixedLenFeature
或VarLenFeature
的情况吗?
您可以加载图像,可能是因为您使用功能类型tf保存了图像。火车BytesList()
和整个图像数据是列表中的一个大字节值。
如果我是对的,你使用的是tf。解码_raw
以从从TFRecord加载的图像中获取数据。
关于示例用例:我使用VarLenFeature
保存对象检测任务的数据集:每个图像的边界框数量可变(等于图像中的对象),因此我需要另一个功能objects\u number
来跟踪对象(和b框)的数量。每个边界框本身是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是固定长度的特征(有一个元素),并持有类型字节的值,但是字节类型的值本身可以具有可变大小(它是一个字节串,可以有很多符号)。所以“image_raw”是一个包含“字节”类型的一个元素的列表,它可以非常大。
为了进一步说明它是如何工作的:特征是值的列表,这些值具有特定的“类型”。
要素的数据类型是张量数据类型的子集,您有:
您可以在这里检查张量数据类型。
因此,您可以存储可变长度的数据,而无需VarLenFeature(实际上你做得很好),但首先您需要将其转换为字节/字符串特性,然后对其进行解码。这是最常见的方法。