Datasets documentation
Estimativa de profundidade
Estimativa de profundidade
Conjuntos de dados de estimativa de profundidade são usados para treinar um modelo a aproximar a distância relativa de cada pixel em uma imagem em relação à câmera, também conhecida como profundidade. As aplicações habilitadas por esses conjuntos de dados estão principalmente em áreas como percepção visual de máquinas e percepção em robótica. Exemplos de aplicações incluem o mapeamento de ruas para carros autônomos. Este guia mostrará como aplicar transformações a um conjunto de dados de estimativa de profundidade.
Antes de começar, verifique se você tem as versões mais recentes de albumentations instaladas:
pip install -U albumentations
Albumentations é uma biblioteca em Python para realizar aumento de dados para visão computacional. Ela suporta diversas tarefas de visão computacional, como classificação de imagens, detecção de objetos, segmentação e estimativa de pontos-chave.
Este guia utiliza o conjunto de dados NYU Depth V2, que é composto por sequências de vídeo de diversas cenas internas, gravadas por câmeras RGB e de profundidade. O conjunto de dados consiste em cenas de 3 cidades e fornece imagens juntamente com seus mapas de profundidade como rótulos.
Carregue o split train do conjunto de dados e veja um exemplo:
>>> 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>}O conjunto de dados possui dois campos:
image: um objeto de imagem PNG da PIL com tipo de dadosuint8.depth_map: um objeto de imagem PIL Tiff com tipo de dadosfloat32, que é o mapa de profundidade da imagem.
Aqui, os mapas de profundidade usam o formato TIFF, pois ele suporta uma ampla variedade de tipos de dados, incluindo dados float32.
No entanto, vale mencionar que o formato JPEG/PNG só pode armazenar dados uint8 ou uint16.
Portanto, se você tiver mapas de profundidade salvos como JPEG/PNG, use o tipo Image(mode="F") para carregá-los como float32 de canal único, como os mapas de profundidade normais:
>>> from datasets import Image
>>> train_dataset = train_dataset.cast_column("depth_map", Image(mode="F"))A seguir, verifique uma imagem com:
>>> example["image"]
Antes de analisarmos o mapa de profundidade, precisamos primeiro converter seu tipo de dados para uint8 usando .convert('RGB'), pois o PIL não consegue exibir imagens float32. Agora, observe o mapa de profundidade correspondente:
>>> example["depth_map"].convert("RGB")
Tudo está preto! Você precisará adicionar alguma cor ao mapa de profundidade para visualizá-lo corretamente. Para isso, podemos aplicar a colorização automaticamente durante a exibição usando plt.imshow() ou criar um mapa de profundidade colorido usando plt.cm e, em seguida, exibi-lo. Neste exemplo, usamos a segunda opção, pois podemos salvar/escrever o mapa de profundidade colorido posteriormente. (a utilidade abaixo foi retirada do repositório 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"])
Você também pode visualizar várias imagens diferentes e seus mapas de profundidade correspondentes.
>>> 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")
Agora aplique algumas aumentações com albumentations. As transformações de aumento incluem:
- Inversão horizontal aleatória
- Recorte aleatório
- Brilho e contraste aleatórios
- Correção gama aleatória
- Saturação de matiz aleatória
>>> 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()
... ]Além disso, defina um mapeamento para refletir melhor o nome da chave de destino.
>>> additional_targets = {"depth": "mask"}
>>> aug = A.Compose(transforms=transforms, additional_targets=additional_targets)Com additional_targets definido, você pode passar os mapas de profundidade de destino para o argumento depth de aug em vez de mask. Você notará essa mudança na função apply_transforms() definida abaixo.
Crie uma função para aplicar a transformação às imagens, bem como aos seus mapas de profundidade:
>>> 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 examplesUse a função set_transform() para aplicar a transformação em tempo real aos lotes do conjunto de dados, consumindo menos espaço em disco:
>>> train_dataset.set_transform(apply_transforms)Você pode verificar se a transformação funcionou indexando os pixel_values e labels de uma imagem de exemplo:
>>> example = train_dataset[index]
>>> plt.imshow(example["pixel_values"])
>>> plt.axis("off")
>>> plt.show()
Visualize a mesma transformação no mapa de profundidade correspondente à imagem:
>>> show_depthmap(example["labels"])
Você também pode visualizar várias amostras de treinamento reutilizando o random_indices anterior:
>>> 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")