【Python × Depth Anything】RGB動画からDepthマップを自動生成

マニアック

depthデータは、kinectやrealsenseを使うと直接的に計測することが可能ではありますが、簡便性でいうと見慣れなかったりする点から使いにくいイメージがあります。

近年では、depth-anythingモデルと呼ばれるRGB画像から深度情報を出力する方法が出現しました。githubのリンクはこちらです(https://github.com/LiheYoung/Depth-Anything)。

今回は、Transformersのdepth-anythingモデルを使って、RGB動画からDepthマップを生成・可視化する方法を紹介します。
処理は1フレームずつ行われ、Depthの可視化(カラーマップ)付き動画と**グレースケール画像(16bit)**が出力されます!


✅ 使用モデル&ツール

利用するモデルや処理フロー、必要なライブラリはこちらになります。Anacondaからパッケージをインストールする方法はこちらの記事で詳細書いています(記事URL:http://ktr-project.net/?p=25)。

  • モデルLiheYoung/depth-anything-base-hf(Hugging Face)
  • 処理フロー:動画 → フレーム → 深度推定 → PNG保存&動画生成
  • ライブラリ
    • transformers
    • accelerate
    • opencv-python
    • Pillow
    • numpy

✅ 環境構築

pip install transformers accelerate opencv-python pillow numpy

※モデルのDL時にHugging Faceのトークンが必要な場合があります。


✅ 動画 → Depthマップ生成コード(フレームごと)

import os
import cv2
import numpy as np
from PIL import Image
from transformers import pipeline

# ===== ファイルパスを自分の環境に合わせて調整 =====
video_path = "./video_raw/video.mp4"  # 入力動画(ここは個人によって違います)
output_video_path = "depth_colormap_output.mp4"  # 出力動画
output_gray_dir = "depth_gray"  # グレースケール保存先
output_color_dir = "depth_color"  # カラーマップ保存先

os.makedirs(output_gray_dir, exist_ok=True)
os.makedirs(output_color_dir, exist_ok=True)

# モデルロード(CPU)
depth_pipe = pipeline("depth-estimation", model="LiheYoung/depth-anything-base-hf", device=-1)

# 動画情報の取得
cap = cv2.VideoCapture(video_path)
fps = cap.get(cv2.CAP_PROP_FPS)
width = int(cap.get(cv2.CAP_PROP_FRAME_WIDTH))
height = int(cap.get(cv2.CAP_PROP_FRAME_HEIGHT))

fourcc = cv2.VideoWriter_fourcc(*"mp4v")
video_writer = cv2.VideoWriter(output_video_path, fourcc, fps, (width, height))

frame_idx = 0
while cap.isOpened():
    ret, frame = cap.read()
    if not ret:
        break

    frame_rgb = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB)
    frame_pil = Image.fromarray(frame_rgb)

    result = depth_pipe(frame_pil)
    depth = np.array(result["depth"])

    # 16bitグレースケール
    depth_16bit = (depth / depth.max() * 65535).astype(np.uint16)
    Image.fromarray(depth_16bit).save(os.path.join(output_gray_dir, f"depth_{frame_idx:05d}.png"))

    # カラーマップ(8bit Jet)
    depth_8bit = cv2.normalize(depth, None, 0, 255, cv2.NORM_MINMAX).astype(np.uint8)
    depth_color = cv2.applyColorMap(depth_8bit, cv2.COLORMAP_JET)
    depth_color_resized = cv2.resize(depth_color, (width, height))
    cv2.imwrite(os.path.join(output_color_dir, f"depth_{frame_idx:05d}_color.png"), depth_color_resized)

    video_writer.write(depth_color_resized)

    print(f" Processed frame {frame_idx}")
    frame_idx += 1

cap.release()
video_writer.release()
print("全処理完了!")

✅ 実行後に生成されるファイル

実際に出力される動画は添付のような感じになります。背景と人間はくっきりと分けることができていますね。細かい関節とかはもうちょい課題がありそう。

ファイル名内容
depth_gray/*.pngフレームごとの16bitグレースケール深度マップ
depth_color/*.pngJetカラーマップ付きDepth画像
depth_colormap_output.mp4上記画像を繋げたDepth動画

✅ 注意点

この処理はCPUでも動かすことができますが、処理の関係で下記の要素には注意が必要です。

  • 動画全フレームにAI処理を行うため、処理はやや重いです(短い動画推奨)
  • 解像度が高い場合はRAM使用量に注意
  • device=-1 はCPU指定。GPUがある場合は device=0 へ変更可だが、CUDAや機械学習のパッケージとの互換など調整が必要なので、個人的には特段早い処理を求めないなら動画を短くしてCPU版を使うのが無難だと思います。

✅ まとめ

項目内容
処理対象RGB動画(.mp4 など)
出力Depth付き動画+画像
必要ライブラリtransformers / opencv-python / pillow など
処理時間動画の長さ・PC性能に依存(1分動画で数分)

RGBからDepthに変換するのは比較的短いコードで行うことができますが、まだ使い道という点ではまだ未知数かなと思います。背景差分をとったり、骨格推定の学習用素材にしたりなどに使えそうというのがKTRの実感です。

質問などあればX(https://x.com/shimitaro_108)まで。

コメント

タイトルとURLをコピーしました