Datasets documentation

深度推定

Hugging Face's logo
Join the Hugging Face community

and get access to the augmented documentation experience

to get started

深度推定

深度推定データセットは、画像内の各ピクセルがカメラからどの程度の相対距離にあるか(深度とも呼ばれる)を近似するモデルの学習に使用されます。これらのデータセットが実現する応用は、主に視覚的機械知覚やロボティクスにおける知覚などの分野にあります。応用例としては、自動運転車向けの道路マッピングなどが挙げられます。このガイドでは、深度推定データセットにトランスフォーメーションを適用する方法を示します。

開始する前に、albumentationsの最新バージョンがインストールされていることを確認してください:

pip install -U albumentations 

Albumentationsは、コンピュータビジョンのためのデータ拡張を実行するためのPythonライブラリです。画像分類、物体検出、セグメンテーション、キーポイント推定など、さまざまなコンピュータビジョンタスクに対応しています。

このガイドでは、NYU Depth V2データセットを使用します。このデータセットは、RGBカメラと深度カメラで記録された、さまざまな屋内シーンからの動画シーケンスで構成されています。データセットは3つの都市のシーンからなり、画像とその深度マップをラベルとして提供します。

train スプリットのデータセットを読み込み、例を確認します:

>>> 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>}

データセットには2つのフィールドがあります:

  • image: uint8データ型を持つPIL PNG画像オブジェクト。
  • depth_map: 画像の深度マップであり、float32データ型を持つPIL Tiff画像オブジェクト。

ここでは、float32データを含む幅広いデータ型をサポートしているTIFF形式が深度マップに使用されています。 ただし、JPEG/PNG形式はuint8またはuint16データのみを保存できる点に注意が必要です。 したがって、JPEG/PNGとして保存された深度マップがある場合は、Image(mode="F")型を使用して、通常の深度マップと同様に単一チャネルのfloat32として読み込みます:

>>> from datasets import Image

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

次に、次のコマンドで画像を確認します:

>>> example["image"]

深度マップを確認する前に、PILはfloat32の画像を表示できないため、.convert('RGB')を使用してデータ型をuint8に変換する必要があります。次に、対応する深度マップを確認してください。

>>> example["depth_map"].convert("RGB")

すべて黒くなっています! 深度マップを適切に可視化するには、色を追加する必要があります。そのためには、plt.imshow() を使用して表示時に自動的に色を適用するか、plt.cm を使用してカラー化された深度マップを作成してから表示するかのいずれかの方法があります。この例では後者の方法を使用しています。これは、カラー化された深度マップを後で保存/書き出すことができるためです。(以下のユーティリティは 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"])

複数の異なる画像とそれに対応する深度マップを可視化することもできます。

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

次に、albumentationsでいくつかの拡張を適用します。拡張変換には以下が含まれます。

  • ランダムな水平方向の反転
  • ランダムクロッピング
  • ランダムな明るさとコントラスト
  • ランダムガンマ補正
  • ランダムな色相と彩度
>>> 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()
... ]

# 定義されたマッピングは、ターゲットのキー名をより正確に反映します。

>>> additional_targets = {"depth": "mask"}
>>> aug = A.Compose(transforms=transforms, additional_targets=additional_targets)

additional_targetsを定義すると、maskの代わりに、ターゲットの深度マップをaugのdepth引数に渡すことができます。この変更は、以下で定義されているapply_transforms()関数で確認できます。

画像とその深度マップにトランスフォーメーションを適用する関数を作成します:

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

set_transform() 関数を使用して、データセットのバッチにトランスフォーメーションをオンザフライで適用し、ディスク容量の消費を削減できます:

>>> train_dataset.set_transform(apply_transforms)

pixel_values と labels にインデックスを指定して、サンプル画像を確認することで、変換が正常に行われたことを検証できます。

>>> example = train_dataset[index]

>>> plt.imshow(example["pixel_values"])
>>> plt.axis("off")
>>> plt.show()

画像に対応する深度マップ上で同じ変換を可視化します:

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

random_indicesを再利用して、複数のトレーニングサンプルを可視化することもできます:

>>> 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")
Update on GitHub