ヨガポーズの認識と表現
ヨガポーズの認識をさせてみた
KinectV2で取得したスケルトンを、CNNで学習させたモデルでポーズ推定して、ヨガポーズと一致していたらパーティクルを出すというものをvvvvで作ってみました。
KinectでBodyを認識して、背景をセグメンテーションし、ヨガスタジオの背景画像に重ねました。実際は、とっ散らかった自宅で撮影してます。
ウッティタ・トリコーナーサナというポーズです。
事前に学習したポーズと一致した場合、パーティクルが出てくるようにしました。
上級者用の裏面を用意しました。
ポーズの一致度が90%以上かつ5秒以上キープできた場合に、このステージに遷移します。
ヨガのポーズはたくさんあります。8400万とも言われてます。
僕が今回学習させたのはたかだか10種類。とても上級者のヨギーには満足してもらえません。なので、このモードでは、同じ姿勢をキープ出来ていると判定したら、丹田のあたりからパーティクルを出すようにしました。
表現について考える
基本的な機能を実装できたあと、「オシャレにしていこう!」と思っていろいろ付け加いったんですが、正直、力不足でした。
こんな感じにしてみたいと思っても、vvvvでうまく表現できない。他の作品みたいに細かいパーティクルをシュワシュワしたいのに、、、とか。これは練習をするしかないな、と。
それ以上に悩んだのは「何を表現するべきか」ということ。
別に新しいことをしているつもりは無いけど、では逆になぜ自分は今この作品?を作っているんだろう、と。どのようにパーティクルを出すか、どこから出すかっていうだけでも、最初は「適当にオシャレになればいいや」と思っていたけど、ある本を読んでいるときに、ストーリーが大切、という一言を読んで、目が覚めました。
僕はなんでヨガのポーズを認識させたいんだろうか、ヴィジュアライズして何を表現したのだろう。
そういう観点から考え直した後、ヨガをして深く集中したときの世界を表現し、それをいろんな人に知ってもらえたらなぁ、と思って裏面を作りました。
もっと力をつけたら、もう一度ヨガポーズの作品に取り組みたいと思います。
次はタブラにチャレンジします。
ヨガポーズの認識(仮まとめ)
いったん一区切りして、ここまでに作ったものをアップします。
作ったもの
・OpenPoseで画像からスケルトン座標の推定
・Kerasでスケルトン座標によるヨガポーズの推定
・KinectV2のvvvvプラグインカスタマイズ
・vvvvで上記の結合
提出物1
vvvvでKinectからのデータを取り込み、TCPでKerasのバックエンドとデータ通信し、結果をもとに画像にエフェクトかけてます。パーツ作りは大変だったけど、vvvvで繋げるのはすごい簡単。
提出物2
Kerasに学習させた3つのポーズとマッチすると、手の位置からパーティクルが出るようにしてみました。パーティクルが出てくる位置がちょっとずれてますが。。。
ここまではパーツ作りを一気にやってきたので、次は完成度を高める作業をやっていこうと思います。
ヨガポーズのクラス分類
ヨガのポーズを機械学習させて、自動で識別させるようにしました。
入力データの準備
ヨガのポーズは実にたくさんあるのですが、まずは識別し易い以下の3ポーズをチョイス。
これらのポーズの画像を10枚ずつ収集して、OpenPoseでスケルトンの座標を取得しました。
ちなみに、OpenPoseとKinectV2で取得できるスケルトンは、以下のようになってます。(OpenPoseはこちらが元ネタです。)
>OpenPose
>KinectV2
KinectV2で取得できない目、耳、背中の位置は使用せず、14点のx,y座標を入力データとしました。また、学習のための前処理として、以下の2つを行いました。
・頭の位置を原点とする
・頭から喉(0番と1番)の距離をもとにリサイズする
こうして得られた入力データを、ちょっと加工して各ポーズ400個に水増ししました。合計1200個なので、まぁまだ少ないですが、いったん進みます。
機械学習
利用したのはKerasで、バックエンドはTensorFlowです。
環境構築は、このサイトにお世話になりました(ありがとうございます)。
Keras、マニュアルも分かりやすかったので、無知でしたが割合すぐに使うことができました。
ただし、無知なのでネットワークをどう組めばいいかは、よく分かりません。
なので、MNISTのサンプルをそのまま使うことにしました。
MNISTは32x32の画像を入力としています。なので、行列サイズを16x16に変更して、各行に14カ所のx,y座標をマッピングしてみました。
半信半疑の感はありましたが、学習させたモデルを使って自分のヨガポーズを分類させてみると、見事に識別できてました。
すーごーいー。
(けもふれ再放送中)
えっと、、、
Kinectに手を出しました(*´ω`*)
雑な感想・・・
- 大きい。RealSenseが驚異的に小さく感じる。
- 機能は豊富。
- ライブラリの使い方がとても似ている。
(RealSense使っていたら、なんなく使えた)
Kinectに手を出したのは、RealSenseを使っていて、背景のセグメンテーションするのが大変だったのと、vvvvのプラグインがすでに用意されてたから。つまり、今後の開発に必要なものが用意されてたから。
やっぱり世の中的にはまだKinectのほうが色々と充実している感はある。
ただ、RealSenseの小ささと、近距離(0.2m~)測位は、アプリケーションの広がりを期待ができるように思う。そう考えていると、スマホに3Dセンサが載るまでにいろいろと準備しているといいかも。あまり時間なさそうですが。
Tangoが載ったスマホはLenovoが出したし、iPhone8にも載りそうと噂されているし、この時流に乗っていけるように、がんばろ。
セグメンテーション
R200はセグメンテーション機能が使えないので、depthを使って自分で実装することにしました。
自力でセグメンテーション
- カラー画像とDepth画像を取得する
- Depth画像をカラー座標系に座標変換する
- パーソントラッキング機能で、カラー画像から人物の中心位置を取得する
- 人物の中心位置のdepthをもとに、前後50cm以外の箇所をカラー画像から取り除く
ざっくりですが、こんな感じになりました。
エッジ部分があらい、ブロブの内部も除去されてる、遅い。このあたりを改善したいです。
座標変換
カラー画像とDepth画像はカメラの位置がずれてるので、併せて使う場合は座標変換をする必要があります。今回はDepth画像の座標系をカラー画像に変換しました。
座標変換用のクラス「PXCProjection」を使います。
使い方は、こちらのサイトが参考になりました。
あと、RSDKのサンプルにある「Projection」も参考になります。