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/*.png | Jetカラーマップ付き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)まで。
コメント