MediaPipeのZ座標と深度推定の違いを検証した
MediaPipe HandsのZ座標と、MiDaSの深度推定を比較するシステムを作った。
手の特徴点にはXYZ情報があるけど、そのZ座標と、深度推定のZ座標は別物。2つを比較して、どっちが正確か検証した。
やりたかったこと
MediaPipeの手のランドマークには、Z座標が含まれてる。
これって、深度情報じゃないのか。深度推定モデル(MiDaS)を使わなくても、Z座標で深度が分かるんじゃないか。
実際に比較してみたかった。MediaPipeのZ座標と、MiDaSの深度推定。
MediaPipeのZ座標
MediaPipeの手のランドマークは、21個の3D座標(x, y, z)。
const landmarks = results.multiHandLandmarks[0];
// 各ランドマークのZ座標
const wristZ = landmarks[0].z; // 手首
const indexTipZ = landmarks[8].z; // 人差し指の先
const middleTipZ = landmarks[12].z; // 中指の先
Z座標は、手首(ランドマーク0)からの相対距離。
手首が0.0で、指の先が0.1とか0.2。単位はメートルじゃなくて、手のサイズに対する相対値。
最初は、これが深度だと思ってた。でも、違った。
MiDaSの深度推定
MiDaSは、画像全体の深度マップを生成する。
const result = await inferenceManager.runInference(videoElement);
const depthData = result.outputData; // 512×512の深度マップ
// 手の位置の深度値を取得
const x = Math.floor(landmark.x * 512);
const y = Math.floor(landmark.y * 512);
const depth = depthData[y * 512 + x];
深度マップは、各ピクセルの深度値。カメラからの距離を表してる。
2つの違い
MediaPipeのZ座標と、MiDaSの深度推定は、全く別物だった。
| 項目 | MediaPipe Z座標 | MiDaS深度推定 |
|------|----------------|--------------|
| 基準 | 手首からの相対距離 | カメラからの絶対距離 |
| 範囲 | 0.0〜0.3(手のサイズ) | 0.0〜1.0(正規化) |
| 精度 | 手の形状に依存 | シーン全体で一貫 |
| 用途 | 手のポーズ推定 | 物体の距離測定 |
MediaPipeのZ座標は、手のポーズを推定するためのもの。手首から指先までの距離。
MiDaSの深度推定は、カメラからの距離。シーン全体の深度を測定する。
全然違う。
実際に比較してみた
手を前後に動かして、2つの値を比較した。
// MediaPipeのZ座標
const mediapipeZ = landmarks[8].z; // 人差し指の先
// MiDaSの深度値
const x = Math.floor(landmarks[8].x * 512);
const y = Math.floor(landmarks[8].y * 512);
const midasDepth = depthData[y * 512 + x];
console.log(`MediaPipe Z: ${mediapipeZ}, MiDaS Depth: ${midasDepth}`);
手を前に出すと:
- MediaPipeのZ座標:0.15 → 0.18(少し増加)
- MiDaSの深度値:0.7 → 0.3(大きく減少)
手を後ろに引くと:
- MediaPipeのZ座標:0.15 → 0.12(少し減少)
- MiDaSの深度値:0.3 → 0.8(大きく増加)
MediaPipeのZ座標は、手の形状が変わると値も変わる。指を伸ばすとZ座標が増える。
MiDaSの深度値は、手の形状に関係なく、カメラからの距離だけで変わる。
どっちを使うべきか
用途によって使い分ける。
MediaPipeのZ座標を使う場合
- 手のポーズ推定(指の曲げ具合)
- 手の形状の分析
- ジェスチャー認識
MiDaSの深度推定を使う場合
- カメラからの距離測定
- 物体の配置(手前/奥)
- AR表示の位置調整
今回は、ARインターフェースを作りたかった。手がカメラからどれくらい離れてるかを知りたい。
だから、MiDaSの深度推定を使う。MediaPipeのZ座標じゃダメだった。
ハマったところ
MediaPipeのZ座標の誤解
最初、MediaPipeのZ座標が深度だと思ってた。
でも、手を前後に動かしても、Z座標があまり変わらない。手のポーズを変えると、Z座標が変わる。
おかしい。
ドキュメントを読んだら、「手首からの相対距離」だった。深度じゃなかった。
座標系の違い
MediaPipeとMiDaSで、座標系が違う。
MediaPipeのZ座標は、手首を基準に、指先に向かってプラス。
MiDaSの深度は、カメラを基準に、遠くに向かってプラス。
方向が逆。比較する時に、片方を反転させる必要があった。
パフォーマンス
PCでの動作を測定した。
| 処理 | 時間 |
|------|------|
| MediaPipe Hands推論(Z座標含む) | 約15ms |
| MiDaS深度推定(512×512) | 約20ms |
| 並行実行の合計 | 約20ms |
並行実行で約50fps。
MediaPipeのZ座標だけ使うなら、MiDaSは不要。約15msで済む。約67fps。
でも、今回はカメラからの距離が欲しかったから、MiDaSも使った。
結果
MediaPipeのZ座標と、MiDaSの深度推定は、全く別物だと分かった。
- MediaPipe Z座標:手首からの相対距離、手のポーズ推定に使う
- MiDaS深度推定:カメラからの絶対距離、物体の配置に使う
用途によって使い分ける必要がある。ARインターフェースには、MiDaSの深度推定が必要。
MediaPipeのZ座標だけでは、カメラからの距離が分からない。
深度を体験してみてください:
全体の処理フロー:
まとめ
今回は、MediaPipeのZ座標とMiDaSの深度推定を比較する実験を行いました。
ポイントは以下の3つ:
- MediaPipe Z座標は手首からの相対距離(手のポーズ推定用)
- MiDaS深度推定はカメラからの絶対距離(物体の配置用)
- ARインターフェースには深度推定が必要
MediaPipeのZ座標を深度だと誤解していたけど、実験して違いが分かった。
複数のAI推論を組み合わせる時の参考になれば嬉しいです。
さらに深く学ぶには
この記事で興味を持った方におすすめのリンク:
自分の関連記事:
最後まで読んでくださり、ありがとうございました。