【MediaPipe】Multi Hand TrackingのGraphを解析してみた

2020.05.27

カフェチームの山本です。

前回は、Multi Hand Trackingのプログラムの動作を解析しました。

【MediaPipe】Multi Hand Trackingのプログラムを解析してみた

今回は、Multi Hand TrackingのGraphを解析していきます。

(MediaPipeに関連する記事はこちらにまとめてあります。)

【MediaPipe】投稿記事まとめ

Multi Hand TrackingのGraph構造

前回、mediapipe/graphs/hand_tracking/multi_hand_tracking_desktop_live.pbtxt からGraphの構成が読み込まれて、実行されていることがわかりました。ここから、Multi Hand TrackingのGraphの構造と動作を見ていきます。

今回の内容は、DocGitHubに記載されている画像や解説を参考にさせていただいています。(公開されているVisualizerにpbtxtファイルの内容をコピペすることで図示/可視化できます。ただし、そのままだとSubgraphは青色で表示されません。別タブでSubgraphをコピペすることでリンクされ、青色で表示されるようになります。)

Graph全体(multi_hand_tracking_desktop_live.pbtxt)

Graphの構成として以下のようになっていることがわかります。

  • 入力Streamと出力Streamを1つずつもち、それぞれ"input_video"・"output_video"と名前である(この名前は呼び出すプログラムと同一になっていて、ImageFrameが入出力される)
  • Nodeとして、4つのCalculator(白色のNode)と3つのSubgraph(青色のNode)がある。
  • 大まかな処理の流れとして、
    • MultiHandDetectionSubgraphで、手そのものの検出を行う
    • MultiHandLandmarkSubgraphで、検出した手のRectに対して、手の骨格(Landmark)検出を行う
    • MultiHandRendererSubgraphで、検出結果を描画する
    • MultiHandLandmarkで手の骨格を検出できた手のRectを、次のフレームで利用するためにフィードバックさせる(MultiHandLandmarkから出てる点線部)
    • NormalizedRectVectorHasMinSizeCalculatorで、前のフレームで検出した手の数が、設定された検出最小数よりも多いか判定し、多ければ手の検出を行わないように、GateCalculatorに指示を出す
    • AssociationNormRectCalculatorで、前のフレームと現在のフレームで検出して手のRect同士で、重なりが大きいものを統合する

MultiHandLandmarkSubgraph(subgraph/multi_hand_landmark.pbtxt)

次に、MultiHandLandmarkSubgraphを見てみると、以下のことがわかります。

  • 入力として、対象画像とMultiHandDetectionで検出された手のRect情報を受け取り、出力として、検出した骨格(landmark)情報と、骨格を検出できなかったものをフィルタリングした手のRect情報を返している。
  • 入力の手のRectは複数受け取ることができ、BeginLoopNormalizedRectCalculatorが1つ1つ分解してPacket化して出力し、最後にBATCH_ENDを出力することで、ループ処理を可能にしている。
  • HandLandmarkSubgraphで、画像を1つのRectを入力として受け取る。Rectで指定されたの画像内の領域に対して手の骨格検出を行い、その領域に手が存在するかどうか、骨格情報を出力する
  • EndLoop---Calculatorで、BeginLoopNormalizedRectCalculatorで分解されて、それぞれのPacketに対してHandLandmarkSubgraphが出力する結果を保持する。BATCH_ENDを受け取ったら、保持していた結果を1つにまとめて、次のNodeに出力する。

HandLandmarkSubgraph(subgraph/hand_landmark_cpu.pbtxt)

HandLandmarkSubgraphを見てみると、以下のようになっています。

  • ImageCroppingCalculatorによって、画像中のrectの部分を切り出す
  • ImageTransformationCalculatorによって、予め設定されたサイズになるよう、切り出した画像を変形する
  • TfLiteConverterCalculatorによって、画像をTensorに変換する
  • TfLiteInferenceCalculatorによって、骨格を検出する
  • (以降、検出した結果に対して、後処理を行う)

まとめ

Multi Hand TrackingがGraph構成を解析しました。Graphは大きく3段階に分かれた複雑な構成をしており、メインとなる骨格検出処理はTfLiteInferenceCalculatorによって行われていることがわかりました。

次回は、プログラムとGraphを変更し、検出されたデータを取り出します。

参考にさせていただいたページ

Multi-Hand Tracking on Desktop(MediaPipe Doc) https://mediapipe.readthedocs.io/en/latest/multi_hand_tracking_desktop.html

Multi-Hand Tracking (GPU) https://github.com/google/mediapipe/blob/master/mediapipe/docs/multi_hand_tracking_mobile_gpu.md

MediaPipe Visualizer https://viz.mediapipe.dev/