# 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 :

```bash
pip install -U albumentations 
```

[Albumentations](https://albumentations.ai/) est une bibliothèque Python permettant d’effectuer l’augmentation de données pour la 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](https://huggingface.co/datasets/sayakpaul/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 :

```py
>>> 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ées `uint8`.
* `depth_map` : un objet d’image Tiff PIL de type de données `float32` repré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`. Il est toutefois à noter que les formats JPEG/PNG ne peuvent 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 classiques :

```python
>>> from datasets import Image

>>> train_dataset = train_dataset.cast_column("depth_map", Image(mode="F"))
```

Ensuite, consultez une image avec :

```py
>>> 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 :

```py
>>> 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](https://github.com/dwofk/fast-depth/blob/master/utils.py)).

```py 
>>> 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.

```py
>>> 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

```py 
>>> 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.

```py 
>>> 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 :

```py 
>>> 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 examples
```

Utilisez la fonction [set_transform()](/docs/datasets/v5.2.0/fr/package_reference/main_classes#datasets.Dataset.set_transform) pour appliquer la transformation à la volée aux lots du jeu de données afin de réduire l’espace disque utilisé :

```py
>>> 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 :

```py
>>> 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 :

```py 
>>> show_depthmap(example["labels"])
```

    

Vous pouvez également visualiser plusieurs exemples d’entraînement en réutilisant les `random_indices` précédents :

```py 
>>> 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")
```

    

