ブラウザ上での姿勢推定に関する情報をいくつかざっくり見てみる（MediaPipe JavaScript版、TensorFlow.js、BlazePose、MoveNet）

Twitter で「MoveNet」というキーワード等を見かけて、以前試したことがあった MediaPipe（JavaScript版）の姿勢推定との違いが気になったので、少し調べてみたというものです。

ちなみに、↓こちらのツイートの中で見かけました。
<blockquote class="twitter-tweet" data-conversation="none"><p lang="en" dir="ltr">Huge congratulations! Been following your progress for a while now and super excited to see this. Thank you for being part of the <a href="https://twitter.com/hashtag/TensorFlowJS?src=hash&amp;ref_src=twsrc%5Etfw">#TensorFlowJS</a> community 🙏 really great work! PS have you tried <a href="https://twitter.com/hashtag/MoveNet?src=hash&amp;ref_src=twsrc%5Etfw">#MoveNet</a> with this too?</p>&mdash; Jason Mayes (@jason_mayes) <a href="https://twitter.com/jason_mayes/status/1415105520478736387?ref_src=twsrc%5Etfw">July 14, 2021</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>

## MediaPipe（JavaScript版）の姿勢推定
MediaPipe の JavaScript版は、以下の[公式ページの内容にあるとおり 2021年7月14日時点で 6つの処理を扱えます](https://google.github.io/mediapipe/getting_started/javascript.html)。

![MediaPipeのJavaScript版.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/50868/a288d6f8-e43a-60d7-98de-656c80df3b96.jpeg)

今回取り上げるのは、6つの中の 1つである [MediaPipe Pose](https://google.github.io/mediapipe/solutions/pose) です。

ちなみに他の 5つはどのようなものがあるかというと、人の顔・手などを認識するものや、人と背景の分離を行うものなどです。
実際に試してみて、その様子を動画にしたものもあるので、この記事の最後のほうにいくつか掲載してみようと思います。

### MediaPipe Pose で使われている BlazePose
[MediaPipe Pose](https://google.github.io/mediapipe/solutions/pose) のページを見ると、そこで使われているものの名前として「BlazePose」が出てきます。
![BlazePose.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/50868/b926df51-94f4-0807-5f0e-7aeb4f1d865c.jpeg)

BlazePose でググると、例えば以下のようなページへのリンクが出てきます。

1. [BlazePose: On-device Real-time Body Pose tracking](https://arxiv.org/abs/2006.10204)
2. [Google AI Blog: On-device, Real-time Body Pose Tracking with MediaPipe BlazePose](https://ai.googleblog.com/2020/08/on-device-real-time-body-pose-tracking.html)

1つ目のほうは、arXiv のページへのリンクで、コンピュータービジョン関連で有名な国際学会である CVPR（Computer Vision and Pattern Recognition）に投稿された論文の情報が出ているようです。

2つ目のほうは Google AI Blog の記事で、「デバイス上でリアルタイムな姿勢推定ができる MediaPipe BlazePose」といったタイトルの記事のようです。
そして、2つ目の記事の中などに、どのような認識結果が得られるかが図をまじえて紹介されていたりします。
![ランドマーク.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/50868/5222a5f1-9cdc-b4ea-e8c4-07c09ea9ccef.jpeg)

文章でも書いてありますが、体の中の 33箇所のキーポイントを検出してくれます。
上記のブログ記事内や MediaPipe Pose の公式ページの中で実例を見ることができるので、それをご覧いただくのが一番分かりやすいかと思います。

## MoveNet について
それでは、冒頭にも書いていた「MoveNet」について、ググって出てきた内容を見ていこうと思います。

以下は、公式のチュートリアルのページの URL です。

●MoveNet: 超高速で正確な姿勢検出モデル。  |  TensorFlow Hub
　https://www.tensorflow.org/hub/tutorials/movenet

冒頭には、以下のような記載がありました。
> MoveNetは、身体の 17 のキーポイントを検出する超高速で正確なモデルです。このモデルは、ライトニングとサンダーとして知られる 2 つのバリアントを備えたTF Hubで提供されます。 Lightning は遅延が重要なアプリケーションを対象としており、Thunder は高精度を必要とするアプリケーションを対象としています。どちらのモデルも、最新のデスクトップ、ラップトップ、および電話のほとんどでリアルタイム (30+ FPS) よりも高速に実行されます。

BlazePose では体の中の 33箇所のキーポイントをとっていましたが、こちらは 17箇所のキーポイントになるようです。
また、Lightning と Thunder という 2種類があり、それぞれ速度重視か精度重視かという違いがあるようです。

以下は、公式のブログ記事です。

●Next-Generation Pose Detection with MoveNet and TensorFlow.js — The TensorFlow Blog
　https://blog.tensorflow.org/2021/05/next-generation-pose-detection-with-movenet-and-tensorflowjs.html

記事の中で、ブラウザで動かした時のパフォーマンスの話が出ていました。
複数のデバイスのデータで、WebGL のものと WASM のものが掲載されており、ざっと見た感じでは、フレームレートは良い感じの数値が出ているようです。
![スクリーンショット_2021_07_16_0_21.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/50868/3c950c08-33aa-9faa-1a97-13c3b6a76708.jpeg)

また記事の中を見ていると、ライブデモ用のリンクが掲載されていました。
　https://storage.googleapis.com/tfjs-models/demos/pose-detection/index.html?model=movenet

その URL のページを開いてみると、設定をいろいろ変えられる部分（画面右側）や、認識結果が表示される部分などが含まれるデモ用ページが出てきました。
![MoveNetのデモページ](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/50868/44e5a5b7-990d-1358-d567-e0592cf99f19.jpeg)
上の画像は顔しかうつってないので、表示されているキーポイントが5つしかないですが...

先ほどのパフォーマンスの表に書いてあったとおり、フレームレートは 30fps を軽く超えた値が出ていたようでした（※ 上の画像の画面左上に表示されてたりします）。

ソースコードなどもチェックしてみたかったところですが、それはまた別の機会に進めてみようと思います。

## おわりに
Twitter で見かけた姿勢推定が行える MoveNet について、MediaPipe JavaScript版の姿勢推定（BlazePose）との違いを軽く調べてみて、いくつかの情報をピックアップしてみました。

まだ、ソースコードに手を入れることができていないため、そのあたりを今後進めてみられればと主言っています。

## 余談： MediaPipe の JavaScript版で試しに実装してみたあれこれ（一部のみ）
記事の中で書いていた JavaScript版の MediaPipe の 6種類ある処理のうち、「Hands」・「Selfie Segmentation」を利用して HTML＋JavaScript で実装した、ブラウザ上で動くお試し的作品があるので、その一部を紹介してみようと思います。

ちなみに、これらをやり始めたのは、ある時にブラウザ上で動く MediaPipe Hands の JavaScript版のデモを試したのがきっかけでした。
その際に、サクサク高精度に両手が認識される様子に驚いて、「何か楽しいことに活用していきたい」と思いました。そしてまずは自分で書いた処理を混ぜ込んで動かしてみよう、と手をつけたのが以下に掲載した内容です。

### MediaPipe Hands と p5.js による矩形描画の組み合わせ
MediaPipe Hands で両手を認識させて、それぞれの手の人差し指の先を起点に矩形を描画しています。
また、その矩形の大きさを、親指の指先と人差し指の指先の距離に応じて変化させる、という処理も実装しました。

<iframe width="560" height="315" src="https://www.youtube.com/embed/vlZRC8iDqjE" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe>

### MediaPipe Hands と p5.js による画像描画の組み合わせ
某アニメに出てくる敵キャラが使う禁呪っぽいものを試しに作ってみたものです。
仕組みの概要については、以下の記事で書いていたりします。
　●某アニメの悪役が使う「とっておきの手品」っぽい呪文が使えた気になる（かもしれない）Webアプリを作った話【技術概要】
　　https://zenn.dev/youtoy/articles/8900adadd996caf643a5

<iframe width="560" height="315" src="https://www.youtube.com/embed/EkzZNFuWYNk" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe>

### MediaPipe Selfie Segmentation と p5.js による画像描画・オブジェクト描画の組み合わせ
Google I/O 2021 で発表され、MediaPipe に新しく追加された「Selfie Segmentation」を使ったものです。

Selfie Segmentation で人物領域のマスク画像が取得できるのですが、それで背景分離をするために、マスク画像を p5.js で取り込んでから、p5.js側でカメラ映像とマスク画像を組み合わせる処理を行いました。
そして、人物と背景の間の領域に画像を表示させて自前バーチャル背景処理みたいなことを試したり、動く2D・3Dオブジェクトを表示させてみたりということを試しました。

<iframe width="560" height="315" src="https://www.youtube.com/embed/V56motax-8A" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe>

### MediaPipe Hands と p5.js によるカメラ映像表示の組み合わせ
こちらは、p5.js を組み合わせて 2重にカメラ映像を表示させ、小さいほうのカメラ映像を、大きい方のカメラ映像の指先の位置に合わせて画面内を動かせるようにしてみたものです。

<iframe width="560" height="315" src="https://www.youtube.com/embed/lLZof_dds4o" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe>