L' tfds.decode
API vous permet de passer outre le décodage de fonction par défaut. Le cas d'utilisation principal est de sauter le décodage de l'image pour de meilleures performances.
Exemples d'utilisation
Sauter le décodage de l'image
Pour garder un contrôle total sur le pipeline de décodage, ou pour appliquer un filtre avant que les images ne soient décodées (pour de meilleures performances), vous pouvez ignorer complètement le décodage de l'image. Cela fonctionne aussi bien avec tfds.features.Image
et tfds.features.Video
.
ds = tfds.load('imagenet2012', split='train', decoders={
'image': tfds.decode.SkipDecoding(),
})
for example in ds.take(1):
assert example['image'].dtype == tf.string # Images are not decoded
Filtrer / mélanger l'ensemble de données avant que les images ne soient décodées
De même à l'exemple précédent, vous pouvez utiliser tfds.decode.SkipDecoding()
pour insérer plus tf.data
personnalisation du pipeline avant le décodage de l'image. De cette façon, les images filtrées ne seront pas décodées et vous pourrez utiliser un plus grand tampon de lecture aléatoire.
# Load the base dataset without decoding
ds, ds_info = tfds.load(
'imagenet2012',
split='train',
decoders={
'image': tfds.decode.SkipDecoding(), # Image won't be decoded here
},
as_supervised=True,
with_info=True,
)
# Apply filter and shuffle
ds = ds.filter(lambda image, label: label != 10)
ds = ds.shuffle(10000)
# Then decode with ds_info.features['image']
ds = ds.map(
lambda image, label: ds_info.features['image'].decode_example(image), label)
Recadrage et décodage en même temps
Pour remplacer la valeur par défaut tf.io.decode_image
opération, vous pouvez créer un nouveau tfds.decode.Decoder
objet en utilisant l' tfds.decode.make_decoder()
décorateur.
@tfds.decode.make_decoder()
def decode_example(serialized_image, feature):
crop_y, crop_x, crop_height, crop_width = 10, 10, 64, 64
return tf.image.decode_and_crop_jpeg(
serialized_image,
[crop_y, crop_x, crop_height, crop_width],
channels=feature.feature.shape[-1],
)
ds = tfds.load('imagenet2012', split='train', decoders={
# With video, decoders are applied to individual frames
'image': decode_example(),
})
Ce qui équivaut à :
def decode_example(serialized_image, feature):
crop_y, crop_x, crop_height, crop_width = 10, 10, 64, 64
return tf.image.decode_and_crop_jpeg(
serialized_image,
[crop_y, crop_x, crop_height, crop_width],
channels=feature.shape[-1],
)
ds, ds_info = tfds.load(
'imagenet2012',
split='train',
with_info=True,
decoders={
'image': tfds.decode.SkipDecoding(), # Skip frame decoding
},
)
ds = ds.map(functools.partial(decode_example, feature=ds_info.features['image']))
Personnalisation du décodage vidéo
Vidéo sont Sequence(Image())
. Lors de l'application de décodeurs personnalisés, ils seront appliqués à des images individuelles. Cela signifie que les décodeurs d'images sont automatiquement compatibles avec la vidéo.
@tfds.decode.make_decoder()
def decode_example(serialized_image, feature):
crop_y, crop_x, crop_height, crop_width = 10, 10, 64, 64
return tf.image.decode_and_crop_jpeg(
serialized_image,
[crop_y, crop_x, crop_height, crop_width],
channels=feature.feature.shape[-1],
)
ds = tfds.load('ucf101', split='train', decoders={
# With video, decoders are applied to individual frames
'video': decode_example(),
})
Ce qui équivaut à :
def decode_frame(serialized_image):
"""Decodes a single frame."""
crop_y, crop_x, crop_height, crop_width = 10, 10, 64, 64
return tf.image.decode_and_crop_jpeg(
serialized_image,
[crop_y, crop_x, crop_height, crop_width],
channels=ds_info.features['video'].shape[-1],
)
def decode_video(example):
"""Decodes all individual frames of the video."""
video = example['video']
video = tf.map_fn(
decode_frame,
video,
dtype=ds_info.features['video'].dtype,
parallel_iterations=10,
)
example['video'] = video
return example
ds, ds_info = tfds.load('ucf101', split='train', with_info=True, decoders={
'video': tfds.decode.SkipDecoding(), # Skip frame decoding
})
ds = ds.map(decode_video) # Decode the video
Décoder uniquement un sous-ensemble des fonctionnalités.
Il est également possible d'ignorer entièrement certaines fonctionnalités en spécifiant uniquement les fonctionnalités dont vous avez besoin. Toutes les autres fonctionnalités seront ignorées/sautées.
builder = tfds.builder('my_dataset')
builder.as_dataset(split='train', decoders=tfds.decode.PartialDecoding({
'image': True,
'metadata': {'num_objects', 'scene_name'},
'objects': {'label'},
})
TFDS sélectionne le sous - ensemble de builder.info.features
qui correspond à la donnée tfds.decode.PartialDecoding
structure.
Dans le code ci - dessus, la vedette sont extraits implicitement correspondre builder.info.features
. Il est également possible de définir explicitement les fonctionnalités. Le code ci-dessus équivaut à :
builder = tfds.builder('my_dataset')
builder.as_dataset(split='train', decoders=tfds.decode.PartialDecoding({
'image': tfds.features.Image(),
'metadata': {
'num_objects': tf.int64,
'scene_name': tfds.features.Text(),
},
'objects': tfds.features.Sequence({
'label': tfds.features.ClassLabel(names=[]),
}),
})
Les métadonnées d'origine (noms des étiquettes, forme de l'image,...) sont automatiquement réutilisées, il n'est donc pas nécessaire de les fournir.
tfds.decode.SkipDecoding
peut être passé à tfds.decode.PartialDecoding
, par la PartialDecoding(..., decoders={})
kwargs.