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)
2条答案
按热度按时间pw9qyyiw1#
您可以加载图像,可能是因为您使用特征类型
tf.train.BytesList()
保存了图像,并且整个图像数据是列表中的一个大字节值。如果我是对的,您将使用
tf.decode_raw
从TFRecord加载的图像中获取数据。关于示例用例:我使用
VarLenFeature
保存对象检测任务的数据集:每个图像的边界框数量可变(等于图像中的对象),因此我需要另一个功能objects_number
来跟踪对象数量(和边界框)。每个边界框本身是一个4浮动坐标列表我使用下面的代码来加载它:
注意,“image_raw”是一个固定长度的特征(只有一个元素),并且保存“bytes”类型的值,但是“bytes”类型的值本身可以有可变的大小(它是一个字节字符串,并且可以有很多符号),所以“image_raw”是一个列表,有一个“bytes”类型的元素,它可以非常大。
进一步详细说明它的工作原理:****特性是值列表,这些值具有特定的“类型”。
要素的数据类型是Tensor数据类型的子集,您有:
可以检查hereTensor数据类型。
所以你可以不用
VarLenFeatures
来存储可变长度的数据(实际上你做得很好),但是首先你需要把它转换成字节/字符串特征,然后解码它,这是最常用的方法。lh80um4z2#
@Xyz已经对此有所阐述,另外,
parse_example_v2
的文档字符串也很有帮助(见下面的摘录):附言:考虑到我们可以很容易地将数组转换为字节(
numpy.ndarray.tobytes
或tf.io.serialize_tensor
),我想知道在哪些情况下VarLenFeature
确实是首选。例如,如果期望
tf.float32
VarLenFeature
ft
,则提供三个串行化的Example
:则输出将如下所示:
如果改为使用
FixedLenSequenceFeature
以及default_value = -1.0
和shape=[]
,则输出将如下所示: