Interfejs API tfds.decode
umożliwia zastąpienie domyślnego dekodowania funkcji. Głównym przypadkiem użycia jest pominięcie dekodowania obrazu w celu uzyskania lepszej wydajności.
Przykłady użycia
Pomijanie dekodowania obrazu
Aby zachować pełną kontrolę nad potokiem dekodowania lub zastosować filtr przed dekodowaniem obrazów (w celu uzyskania lepszej wydajności), możesz całkowicie pominąć dekodowanie obrazu. Działa to zarówno z tfds.features.Image
jak i 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
Filtruj/tasuj zbiór danych, zanim obrazy zostaną zdekodowane
Podobnie jak w poprzednim przykładzie, możesz użyć tfds.decode.SkipDecoding()
w celu wstawienia dodatkowego dostosowania potoku tf.data
przed zdekodowaniem obrazu. W ten sposób przefiltrowane obrazy nie zostaną zdekodowane i będzie można użyć większego bufora losowego.
# 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)
Przycinanie i dekodowanie w tym samym czasie
Aby zastąpić domyślną operację tf.io.decode_image
, możesz utworzyć nowy obiekt tfds.decode.Decoder
za pomocą dekoratora tfds.decode.make_decoder()
.
@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(),
})
Co jest równoważne:
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']))
Dostosowywanie dekodowania wideo
Wideo to Sequence(Image())
. W przypadku stosowania niestandardowych dekoderów zostaną one zastosowane do poszczególnych klatek. Oznacza to, że dekodery obrazów są automatycznie kompatybilne z wideo.
@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(),
})
Co jest równoważne:
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
Dekoduj tylko podzbiór cech.
Można także całkowicie pominąć niektóre funkcje, określając tylko te, których potrzebujesz. Wszystkie inne funkcje zostaną zignorowane/pominięte.
builder = tfds.builder('my_dataset')
builder.as_dataset(split='train', decoders=tfds.decode.PartialDecoding({
'image': True,
'metadata': {'num_objects', 'scene_name'},
'objects': {'label'},
})
TFDS wybierze podzbiór builder.info.features
pasujący do podanej struktury tfds.decode.PartialDecoding
.
W powyższym kodzie wyróżnione elementy są domyślnie wyodrębniane w celu dopasowania do builder.info.features
. Możliwe jest także wyraźne zdefiniowanie cech. Powyższy kod jest równoważny:
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=[]),
}),
})
Oryginalne metadane (nazwy etykiet, kształt obrazu itp.) są automatycznie ponownie wykorzystywane, więc ich podawanie nie jest wymagane.
tfds.decode.SkipDecoding
można przekazać do tfds.decode.PartialDecoding
za pomocą kwargs PartialDecoding(..., decoders={})
.