卒論時期にKinect V2で「おもちゃ」を作った話
お疲れ様です、まーぼうです。 この記事はrogy Advent Calendar 2018の15日目の記事となります。
今回はKinect V2で何か作った話をしようと思います。スゴーく雑な卒論の進め方みたいな読み物でもあります。見返してみると非常に読みづらいですがご勘弁ください。
作ったもの
スポーツのフォームを分析するためのツールを作りました。
Kinect V2でアスリートの動きを撮影して、体の関節点(厳密には関節ではないですが)がどのような動きをしているかを棒人間アニメーションやグラフで確認できます。
Kinect V2で撮影しているので、体の関節点の3次元座標が取れてます。なので「前かがみな姿勢を取っているか」みたいな、身体の様子を細かく認識できます。
他にも、
- 撮影したデータのグラフをカットして、複数のフォームの情報を並べて比較する
- 関節点の位置の他に「3関節点によってできる角の大きさ」「2関節点のベクトルのxyz要素や距離」などもグラフ化できる
- 簡単に関節点を指定できるUI
など実装してみました。
なぜ作ろうと思ったのか
「卒論のために作った」が1番の理由です。 研究分野は「教育工学」だったのですが、11月下旬頃に「テニスをする人がサービス動作を自学自習するためのツールを作って評価しよう」という話になりました。グッダグダです。とりあえず、カメラで自分の姿を横から撮って学習するというのはされていたので、
- 身体の動きを3次元的に把握する
- 身体の動きをグラフとしてみせる(大半はラケットの速度とかボールの速度とかだけだった)
をして新規性を出そうという事になりました。先行研究調査がとても足りていなかったので、ホンマに新規性があるかは怪しい気がするけども。
とにかく、人の動きを3次元的に把握したかったので、Kinect使うか~~と単純に考えた結果、Kinect V2でアプリケーションを作ることになりました。
卒論時期のパワポを見返してみたら、こんな感じで考えていたみたいです。
テニスボールを撮ってみよう
最初は、テニスの試合の経過を用いて振り返り学習がやれたらいいなと思っていたので、試合経過判定のためにテニスボールを撮ってみました。rogyの先輩にKinectでの画像認識に詳しい人がいたので、Kinectを貸してもらいながら色々やってみました。
ちょっと無理だなと思ったので、テニスボールを撮ることを諦めました。後で知ったことですが、Kinectは素早く動く物の認識が苦手なので、ボールが高速で行き来するテニスボールを撮影するのは些か無謀でした。
じゃあフォームに特化してみよう
試合経過は無理だと分かったので、フォームを撮ることにしました。テニスのサービスであれば、撃つ場所が大体決まっているので、撮影するのに都合が良いなと思ったのでサービスに絞ることに。
人の認識がだいたいできてるし、この方針で行ってみることにしました。
作り方
肝心の作り方です。完成物のgithubはこちら。
環境を整える
自分の場合はたまたま上手くいきましたが、意外と大変な場所な気がします。 まず、PCで開発するとなると、以下が必要な気がします。
他OSで動くかは調べてませんが、動かない気がします。何より厄介なのは、去年12月の時点でアダプターが生産終了していたはずです。
これらが用意できたら、プログラミングの環境と、SDKを用意します。PCの要件を満たしているか確認してから、インストールしましょう。
Download Kinect for Windows SDK 2.0 from Official Microsoft Download Center
SDKをインストールすると、「SDK Browser」が使えるようになり、サンプルプログラムが動かせるので、Kinectにつないで動作確認しましょう。
これだけで楽しい!サンプルプログラムもあるので、色々見てみると良いです。
体を認識する
色々ググってみて、こちらのコードがだいぶ参考になったので、これをベースに書いてみましたら1週間くらいで認識まで出来ました。
自分のコードで言うと、「BodySimulator.cpp」「BodyPhotographer.cpp」でKinectの準備と認識・撮影の機能を書いていました。ぶっちゃけ1年前のコードなので思い出すのが大変です。
録画したりグラフ化したりしてみる
気合で書きます。オレオレフォーマットを実装して撮影したデータを読み書きし、DXライブラリを用いて描画するだけです。 と思ったのですが、Kinectの座標系であったり、マクロであったりが分からなかったりしたので色々調べていました。こっちも1週間くらいで出来た記憶があります。
座標系
kazunori-ohmori.blog.so-net.ne.jp
Depth画像によって取得できる範囲
関節点についての列挙体名JointTypeについて
Kinect V2 C++ Programming with OpenCV on Windows10
作ってみて
重大な欠陥1
作ったものの段階で、嫌な予感をした人がいたと思います。この装置、重大な欠陥があるんですね。それは、
解像度が足りず素早い動きが撮れない
です。なぜこんな事に気付かなかったんだ……(理由は簡単で、締切に殺されてたからです)。
サーブの時の腕の動きはもう訳わからんことになってました。30fpsのKinectではスポーツの動きは撮るのは難しいですね……
重大な欠陥2
さらに問題となる点があって、「Kinectは人が奥を向いているのか手前を向いているのか分からない」というのがありました。これだと意味がわからないと思うので図にしてみました。
(黒字が人にとっての左右、赤字がKinectにとっての左右)
そもそもKinectはKinectの方を見て使うものなので、人は大抵Kinectを見ています。そのため人の向きを考慮する必要がないので、Kinectは人の右手左手の判定を「Kinectから見て右手か左手か」で判定するからだと思います。(あくまで推測です)
普段使いだと問題ないのですが、スポーツの動きは「体をねじる」という事をすることが多く、その動きをされると一発で右手と左手が入れ替わります。キレそうになりました。
OpenPoseでやれという話
もっともです。ベータ版が公開されたのは去年だったはず。ぶっちゃけKinect V2でやる必要はなかったんや……
なおOpenPoseとは、画像認識オンリーで人の姿勢を3次元座標で認識するためのライブラリです。
結局どうしたか
素早く入れ替わる腕の動きを撮るのを断念し、動きが比較的ゆっくりな足や膝のデータを見て「フォームの改善のための指摘ができるんじゃないのか?」という提案をした段階で卒論が終わりました。闇を見たので結局修士ではこのテーマで研究をしていません。
ただ、Kinectアプリ自体は面白かったので、また何か作ってみたいですね。
あと、せっかくなので工大祭で展示してみたところ、見せものとしてはそれなりにウケが良かったです。
まとめ
読みにくい文章だったと思いますが、ここまで読んでくださりありがとうございました。