我正在尝试扩展ImageFolder生成器的功能(https://github.com/tensorflow/datasets/blob/master/tensorflow_datasets/core/folder_dataset/image_folder.py#L41-L173(
以包括并读取OpenImagesV6数据集中的.txt边界框文件。这是我的自定义数据集信息:
return dataset_info.DatasetInfo(
builder=self,
description='Generic image classification dataset.',
features=features_lib.FeaturesDict({
'image': features_lib.Image(
shape=self._image_shape,
dtype=self._image_dtype,
),
'label': features_lib.ClassLabel(num_classes=3),
'image/filename': features_lib.Text(),
'bbox_path': features_lib.Text(),
'bboxes': features_lib.Sequence({
'bbox': features_lib.BBoxFeature()
}),
}),
supervised_keys=('image', 'label'),
)
在_as_dataset函数中,我成功地用from_sensor_slices创建了一个数据集,但当我试图将_load_and_decode_fn映射到数据集以读取图像和bbox文件时,当_load_example试图返回dict时,我得到了以下错误:
TypeError: Could not build a TypeSpec for [BBox(ymin=<tf.Tensor 'while/StringToNumber_1:0' shape=() dtype=float32>, xmin=<tf.Tensor 'while/StringToNumber:0' shape=() dtype=float32>, ymax=<tf.Tensor 'while/StringToNumber_3:0' shape=() dtype=float32>, xmax=<tf.Tensor 'while/StringToNumber_2:0' shape=() dtype=float32>)] with type list
这是我修改的_load_example函数:
def _load_example(
path: tf.Tensor,
label: tf.Tensor,
bbox_path: tf.Tensor,
) -> Dict[str, tf.Tensor]:
bbox_values = tf.io.read_file(bbox_path)
bbox_values = tf.strings.split(bbox_values, sep='n')
bboxes = []
for line in bbox_values:
line = tf.strings.split(line, sep=' ')
if line[0] is not None:
xmin = tf.strings.to_number(line[1])
ymin = tf.strings.to_number(line[2])
xmax = tf.strings.to_number(line[3])
ymax = tf.strings.to_number(line[4])
bboxes.append(features_lib.BBox(
ymin=ymin,
xmin=xmin,
ymax=ymax,
xmax=xmax
))
img = tf.io.read_file(path)
return {
'image': img,
'label': tf.cast(label, tf.int64),
'image/filename': path,
'bbox_path': bbox_path,
'bboxes': {
'bbox': bboxes
}
}
我一定错过了一些基本的东西。也许我只是误解了map函数的工作原理?
我误解了张量在映射函数中的工作方式。我在创建数据集之前加载了bbox数据,然后将_as_dataset((更改为使用load_from_generator((而不是_load_from_tensor_slices((。这一点,以及对类型和形状的正确指定,解决了我的问题。