Datasets documentation
Estimation de la profondeur
Estimation de la profondeur
Les jeux de données d’estimation de profondeur servent à entraîner un modèle à approximer la distance relative de chaque pixel d’une image par rapport à la caméra, également appelée profondeur. Les applications rendues possibles par ces jeux de données se situent principalement dans des domaines tels que la perception visuelle par machine et la perception en robotique. Des exemples d’applications incluent la cartographie des rues pour les voitures autonomes. Ce guide vous montre comment appliquer des transformations à un jeu de données d’estimation de profondeur.
Avant de commencer, assurez-vous d'avoir des versions à jour de albumentations installées :
pip install -U albumentations
Albumentations est une bibliothèque Python pour effectuer l’augmentation de données en vision par ordinateur. Elle prend en charge diverses tâches de vision par ordinateur, telles que la classification d’images, la détection d’objets, la segmentation et l’estimation de points clés.
Ce guide utilise le jeu de données NYU Depth V2, qui est composé de séquences vidéo de diverses scènes intérieures, enregistrées par des caméras RGB et de profondeur. Le jeu de données comprend des scènes de 3 villes et fournit des images ainsi que leurs cartes de profondeur en tant qu'étiquettes.
Chargez la partition train du jeu de données et examinez un exemple :
>>> from datasets import load_dataset
>>> train_dataset = load_dataset("sayakpaul/nyu_depth_v2", split="train")
>>> index = 17
>>> example = train_dataset[index]
>>> example
{'image': <PIL.PngImagePlugin.PngImageFile image mode=RGB size=640x480>,
'depth_map': <PIL.TiffImagePlugin.TiffImageFile image mode=F size=640x480>}Le jeu de données comporte deux champs :
image: un objet d'image PNG PIL avec le type de donnéesuint8.depth_map: un objet d’image Tiff PIL de type de donnéesfloat32représentant la carte de profondeur de l’image.
Ici, les cartes de profondeur utilisent le format TIFF car il prend en charge une large gamme de types de données, y compris les données float32.
Cependant, il est à noter que le format JPEG/PNG ne peut stocker que des données uint8 ou uint16.
Par conséquent, si vous avez des cartes de profondeur enregistrées en JPEG/PNG, utilisez le type Image(mode="F") pour les charger en float32 sur un seul canal, comme les cartes de profondeur normales :
>>> from datasets import Image
>>> train_dataset = train_dataset.cast_column("depth_map", Image(mode="F"))Ensuite, consultez une image avec :
>>> example["image"]
Avant d’examiner la carte de profondeur, il faut d’abord convertir son type de données en uint8 à l’aide de .convert('RGB'), car PIL ne peut pas afficher les images float32. Examinez maintenant sa carte de profondeur correspondante :
>>> example["depth_map"].convert("RGB")
Tout est noir ! Il faut ajouter de la couleur à la carte de profondeur pour la visualiser correctement. Pour ce faire, on peut soit appliquer automatiquement la couleur lors de l’affichage à l’aide de plt.imshow(), soit créer une carte de profondeur colorée à l’aide de plt.cm avant de l’afficher. Dans cet exemple, nous avons opté pour la seconde méthode, car elle permet d’enregistrer/écrire la carte de profondeur colorée ultérieurement. (l’utilitaire ci-dessous est issu du dépôt FastDepth).
>>> import numpy as np
>>> import matplotlib.pyplot as plt
>>> cmap = plt.cm.viridis
>>> def colored_depthmap(depth, d_min=None, d_max=None):
... if d_min is None:
... d_min = np.min(depth)
... if d_max is None:
... d_max = np.max(depth)
... depth_relative = (depth - d_min) / (d_max - d_min)
... return 255 * cmap(depth_relative)[:,:,:3]
>>> def show_depthmap(depth_map):
... if not isinstance(depth_map, np.ndarray):
... depth_map = np.array(depth_map)
... if depth_map.ndim == 3:
... depth_map = depth_map.squeeze()
... d_min = np.min(depth_map)
... d_max = np.max(depth_map)
... depth_map = colored_depthmap(depth_map, d_min, d_max)
... plt.imshow(depth_map.astype("uint8"))
... plt.axis("off")
... plt.show()
>>> show_depthmap(example["depth_map"])
Vous pouvez également visualiser plusieurs images différentes et leurs cartes de profondeur correspondantes.
>>> def merge_into_row(input_image, depth_target):
... if not isinstance(input_image, np.ndarray):
... input_image = np.array(input_image)
...
... d_min = np.min(depth_target)
... d_max = np.max(depth_target)
... depth_target_col = colored_depthmap(depth_target, d_min, d_max)
... img_merge = np.hstack([input_image, depth_target_col])
...
... return img_merge
>>> random_indices = np.random.choice(len(train_dataset), 9).tolist()
>>> plt.figure(figsize=(15, 6))
>>> for i, idx in enumerate(random_indices):
... example = train_dataset[idx]
... ax = plt.subplot(3, 3, i + 1)
... image_viz = merge_into_row(
... example["image"], example["depth_map"]
... )
... plt.imshow(image_viz.astype("uint8"))
... plt.axis("off")
Appliquez maintenant quelques augmentations avec albumentations. Les transformations d'augmentation incluent :
- Retournement horizontal aléatoire
- Recadrage aléatoire
- Luminosité et contraste aléatoires
- Correction gamma aléatoire
- Saturation de teinte aléatoire
>>> import albumentations as A
>>> crop_size = (448, 576)
>>> transforms = [
... A.HorizontalFlip(p=0.5),
... A.RandomCrop(crop_size[0], crop_size[1]),
... A.RandomBrightnessContrast(),
... A.RandomGamma(),
... A.HueSaturationValue()
... ]De plus, définissez une correspondance pour mieux refléter le nom de la clé cible.
>>> additional_targets = {"depth": "mask"}
>>> aug = A.Compose(transforms=transforms, additional_targets=additional_targets)Avec additional_targets défini, vous pouvez passer les cartes de profondeur cibles à l'argument depth de aug au lieu de mask. Vous remarquerez ce changement dans la fonction apply_transforms() définie ci-dessous.
Créez une fonction pour appliquer la transformation aux images ainsi qu’à leurs cartes de profondeur :
>>> def apply_transforms(examples):
... transformed_images, transformed_maps = [], []
... for image, depth_map in zip(examples["image"], examples["depth_map"]):
... image, depth_map = np.array(image), np.array(depth_map)
... transformed = aug(image=image, depth=depth_map)
... transformed_images.append(transformed["image"])
... transformed_maps.append(transformed["depth"])
...
... examples["pixel_values"] = transformed_images
... examples["labels"] = transformed_maps
... return examplesUtilisez la fonction set_transform() pour appliquer la transformation à la volée aux lots du jeu de données afin de réduire l’espace disque utilisé :
>>> train_dataset.set_transform(apply_transforms)Vous pouvez vérifier que la transformation a fonctionné en accédant aux pixel_values et labels d'une image d'exemple :
>>> example = train_dataset[index]
>>> plt.imshow(example["pixel_values"])
>>> plt.axis("off")
>>> plt.show()
Visualisez la même transformation sur la carte de profondeur correspondante de l’image :
>>> show_depthmap(example["labels"])
Vous pouvez également visualiser plusieurs exemples d’entraînement en réutilisant les random_indices précédents :
>>> plt.figure(figsize=(15, 6))
>>> for i, idx in enumerate(random_indices):
... ax = plt.subplot(3, 3, i + 1)
... example = train_dataset[idx]
... image_viz = merge_into_row(
... example["pixel_values"], example["labels"]
... )
... plt.imshow(image_viz.astype("uint8"))
... plt.axis("off")