2012年現在
デジタルデータを扱う場合、キーボード、マウス、その他スイッチ、ボタンといった
入力デバイスを利用します。
ブラインドタッチを覚えたり、マウスでクリックする場所や順番を覚えたりと
何かと覚えることが多くて、現実世界なら数秒で済む作業が
コンピュータ上では何十分、何時間とかかることがあります。
(操作さえ覚えてしまえば、コンピュータ上の方が何万倍も速くなることもありますが)
もっと直感的に…(もういいですね、以下略。)
そこで私は手指の姿勢推定問題に挑むことにしました。
あたかも画面内に手を突っ込んだかのような感覚を得られるようになること。
これをゴールとします。
現在最もこれを実現し得る可能性を持つデバイス Kinect
このセンサのデータを使ってアレコレ研究してみようと思います。
まずはその Kinect を買うことからですね。
2万5千円しました。(小学生のお年玉といったところ。)
新作ゲームソフト3本買えますね、高額な代物です。
まずは使えるように、次のページから最新版の SDK をダウンロードします。
Kinect for Windows software development kit (SDK)
SDK のほか Sample が付いている ToolKit もインストールします。
あとは Kinect を繋いで、サンプルが動作すれば OK です。
…
住宅事情により、全身を捉えるだけのスペースを確保できませんでした。
ここに誓う!次に住む場所、又は家を建てるなら最低でも Kinect で遊べる空間を作ると!
では簡単なアプリケーションを ToolKit を参考に作ってみたいと思います。
ToolKit に付いているサンプルをひと通り確認しましょう。
ちょっと感動のあまり涙が…この充実度、素晴らしすぎる!
それと、入門者は次の書籍を用意すると迷わず良いと思います。
KINECT for Windows SDKプログラミングC#編
とりあえず、ピクセルの距離値[mm]を最短で取得する手順を次に示します。
イベントにハンドラを登録して、イベント追加情報からフレームの情報を取得、後は良しなに…という流れです。
ピクセル座標もいいですが、3次元座標を取得する場合、ToolKit はどうやっているのか見てみます。
おお! Microsoft.Kinect.CoordinateMapper で面倒な座標変換は全て対応してくれる模様。
struct SkeletonPoint に格納されている情報は X, Y, Z 座標(m)となっており
センサごとに正確な情報が取得できるため、光軸やらピクセル幅やら気にせずに欲しい情報を取得できるとのこと。(やったね!)
SDK が面倒な仕事をすべて担当してくれることがわかったので、さっそく簡単な位置合わせアプリを作ろうと思います。
10指の姿勢推定の前に、1指から、もっと簡単な問題として
一関節の直方体の箱をセンシングして、これの姿勢推定ができるか挑戦してみます。
(というか…これさえ出来ないようなら、さっさと諦めて他のことをしようと思います。)
原理は KinectFusion の逆を行うだけなので特に解説はしません。
計算量はそこそこ多いので GPGPU を使用します。
と、いうことで DirectX 11 を使った ComputeShader というものをお勉強…
次のページの資料を参考にして、実装についての疑問が解消できました。(ありがとうございます!)
ですが、最初は並列演算なしの CPU オンリーでアルゴリズム最適化も特にせず
Kinect のケースのトラッキングプログラムだけ作ってみようと思います。
この時のパフォーマンスを測定し、どれだけ高速化できるか、これをモチベーションに作業を進めようと思います。
まだ本題に入っていませんが、DirectX 11 を使ってポイントスプライトを描画する仕組みを導入しました。
これにセンサの計測値を代入することでリアルタイム距離画像が表示できます。
実際に表示した結果を次に示します。
距離が0.5m付近でスプライトが赤色になるよう設定しています。
オマケ、両手を計測している絵を撮りたかったので足で PrintScreen …はい、ごめんなさい。
あと、トラッキングしている時にデモとして実際のオブジェクトを描画するので
Blender で Kinect のケースを作成します。
これを Kimberlite の3D空間で表示した結果を次に示します。
続いて、距離画像を表示している空間へ配置してみます。
任意の姿勢行列で、Kinect のケースを表示出来るようになっています。
さて、ここまでは誰でもできる内容ですが、ここから難易度が跳ね上がります。
ひとまず Kinect のケースの領域を決めて、領域重心のトラッキングをして
重心位置に Kinect のケースを描画する、というものを作ってみたいと思います。
…本日(2013/1/6)、父方の祖父が亡くなりました。
年末、年越しと一緒に過ごせたのは良かったです。
気を取り直して、続きを。
センサに対して最近となる点の位置に Kinect のケースを配置するように作ってみました。
全点検索して最近となる点を求めているのにリアルタイムで進行できたので、これだけで結構おもしろいです。
ただ、ガタガタと振動するのが確認できましたので、感じづらいノイズが結構あることに気付かされます。
コーディング作業中…ところで、2013/1/14 の成人の日、東京で雪が降りました。
…はい、ひと通り動作するところまで書きました。
(まだ玄関先に雪が残ってますよ。)
実際に動かしながらバグを取り、実行した結果を次に示します。
わかりやすくするためボックスの頂点と、距離画像における対応点に球体オブジェクトを配置しています。
対応点の間(ユークリッド距離)を最小にするよう姿勢行列を求めていますので
距離画像にフィットするように、実際の Kinect ケースの姿勢が求められていることを確認しました。
ここまでのことは頭の中でできていたので、それほどすごいとは思っていませんが
実際動くところを見ると感動するところがあります。
ということで、第一段階クリアですね。
高速化、関節の導入、手の姿勢推定と発展させていきます。
さて、もし本当に手の姿勢推定ができるのならば、これはすごいことです。
このまま、ここで作り方を示してしまうのはあまりに危険な(頭の悪い)おこないなので
次の更新は手の姿勢推定が成功してから行いたいと思います。
長らく更新をストップすることになりますが、また更新できるよう
密かに活動を続けていきます。
およそ半年ほどで結果が出る予定なので、その時にまた会いましょう。
閲覧、Web 拍手、コメントなど、ありがとうございました。(励みになりました。)
2012/12/16 初記。
2013/01/27 更新。