asus4 / tf-lite-unity-sample

TensorFlow Lite Samples on Unity
858 stars 252 forks source link

BlazePose for video use cases #78

Closed ganaware closed 3 years ago

ganaware commented 3 years ago

すみません、日本語で失礼します。

tf-lite-unity-sample をとても参考にさせていただいております。ありがとうございます。 BlazePose についていくつか質問などさせてください。

BlazePose の認識があまり安定しない点について

まとめ

経緯

これは私の環境 (PC と Pixel 4a) のせいなのかもしれませんが tf-lite-unity-sample での BlazePose での認識が安定せず、 MediaPipe のサイトで体験できるデモで安定して認識できるのと比べると かなり精度が劣るという印象でした。

そこで、ソースを詳しく眺めたところ、実装されている two-step detector-tracker ML pipeline が、 MediaPipe で実装されているものとは少し実装が異なることに気が付きました。

MediaPipe のドキュメントによれば、ビデオに対して適用する場合は detector (PoseDetect.cs) を実行するのは 最初のフレームや tracker (PoseLandmarkDetect.cs) で姿勢を認識できなかった時のみとし、 通常は tracker のみで認識を行うようです。

そこで試しにそのように実装してみたところ https://github.com/ganaware/tf-lite-unity-sample/commit/2758b47071105c22bf226cf226432be173194f30 、とても安定して認識できるようになったと思います。 (この差分内では、いくつかの定数をデモで使用されている値へ変更してあります)

全身認識時の定数の出どころについて

まとめ

1.8 という値の出どころを教えていただけないでしょうか? また、全身の認識をしているコードのソースなどご存じでしたら教えていただけないでしょうか?

経緯

上記 ※1 のように修正したところ、上半身の認識は安定して行うことができるのですが、 全身の認識がなかなかうまくいかず、 tracker から得られる keypoint に妙なスケールをかける必要が出てきました。 (※2)

                if (mode == Mode.FullBody)
                {
                    p.x = (p.x - 0.5f) * 0.84f + 0.5f; // WHY?
                    p.y = (p.y - 0.5f) * 0.84f + 0.5f; // WHY?
                }

これは、tf-lite-unity-sample で実装されている CalcCropMatrix() などの座標変換を 私があまり理解できていないせいかもしれません。

上半身の場合は MediaPipe のサイトで体験できるデモ のコードと MediaPipe 自体のソースを読むことで理解できたと思うのですが、全身の場合のコードを見つけることができず、 なぜ ※2 のような事態になってしまったのか、解決にたどり着けませんでした。

そこで 1.8 という値の出どころや、 全身の認識をしているコードのソースなどご存じでしたら教えていただけないでしょうか?

asus4 commented 3 years ago

@ganaware

two-step detector-tracker ML pipeline

はい。MediaPipeのすべてのグラフを実装できたわけではなく、最低限の部分だけ移植した実装になってます。ほぼ同じ仕組みのFaceMeshのサンプルではtwo-stepに対応してます。似た仕組みでBlazePoseの方も対応できると思います。対応することで処理速度も結構早くなります。

https://github.com/asus4/tf-lite-unity-sample/blob/e8eb8af10bc0471e96898be958dd1497430195f6/Assets/Samples/FaceMesh/FaceMeshSample.cs#L99

全身認識時の定数の出どころについて

Full Bodyのモデルはapache license 2.0ですが、MLKitのソースは非公開なので、PoseScaleの値は私が決めています。環境に合わせて変えてみ見てください。 妙なスケールについては、私の方ではうまく動いていたので、ちょっと別の問題かもしれません…。

ganaware commented 3 years ago

素早いお返事ありがとうございます。

なるほど、MLKitはソースが非公開だったのですね。(探しても見つからないわけです)

そこで、全身の方の PoseScale を 1.8 から、上半身と同じ 1.5 へ変更したところ、 「妙なスケール」をかける必要もなくなり、 速く安定して全身を認識できるようになりました。

ありがとうございました!