KinectのデータからOpenGLで立体表示する

きっかけ

  • まだWindows SDK for Kinectが公開される前、Kinect Hackの一例としてとても有名になった3D Video Capture with Kinect みたいな事をやってみたいと思った。


方法

気軽にOpenGLアプリを作りたい。その場合、有名なのはGLUTです。

でも、GLUTでは Projection Matrix の設定やマウスによるビューの回転操作など、全て自分で作り込まなくてはなりません。 ヒスイは完成されたビューを持っているため、Projection Matrix やマウス操作を自分で作る必要はありません。 だからといってプログラマから自由を奪うことはなく、OpenGLのコードを自由にシーン中に埋め込むことが出来ます。 また、ポリゴンのデータ構造も持っていますので、ポリゴンのデータを扱うのにも便利です。

ヒスイは C# により .NET Framework 上に構築されています。つまり、.NET Framework のパワーをフルに活かした 本格的なアプリケーションの開発にも使用することが出来ます。GLUTは本格的なアプリケーションには向きませんが、 ヒスイならばそれが可能です。

ヒスイは、GLUT以上の気軽さで、より本格的なOpenGLアプリケーションの開発を支援します。

ヒスイ

Kinectの画像処理

  • カメラの復習はKinect for Windows SDK 入門3:カメラ基礎から。
  • kinectは32bitビットマップを使ってるため、用意する配列のサイズはWidth×Height×4
  • CopyPixelsを使って、BitmapSourceから配列にコピー。
    • strideは、単純にWidth×4
bitmapSource.CopyPixels(imageArray, bitmapSource.PixelWidth * bitmapSource.PixelWidth * 4, 0);
  • コピーした配列から、OpenGLで利用する新しい配列を作る。
    • それぞれのピクセルに対して4ビット。
    • 1ビット目にBlue、2ビット目にGreen、3ビット目にRedが0〜255の値で入っている。(4ビット目は0)
    • OpenGLではこれを0〜1までの値で扱うため、それぞれの値を求める。
    • 気をつけないといけないのは、それぞれのカラービットは左下から右上方向に格納されていること。(詳しくはこちら
  • カメラのイメージは640×480に対して、Kinectの深度データは320×240だったので、一個ずつ飛ばして同じサイズにした。
float[][] color = new float[320 * 240][];
int count = 0;
for (int y = 480 - 1; y >= 0; y-=2)
{
    for (int x = 0; x < (640 * 4); x+=8)
    {
        int indexFrom = x + (479 - y) * (640 * 4);
        color[count] = new byte[3];
        color[count][0] = data[indexFrom] / 255.0;
        color[count][1] = data[indexFrom + 1] / 255.0;
        color[count][2] = data[indexFrom + 2] / 255.0;
        count++;
    }
}
  • 深度データは、x=index%360, y=index/360, z=depth[index]という感じに。
  • それでヒスイで表示。

デモ(オリジナルにミスがあったので修正(2011/07/14))

  • 元データ

  • 3Dデータ

  • 違う角度から(1)

  • 違う角度から(2)

  • 動画はこんな感じ

  • いいんだけど、youtubeのやつの劣化版コピーみたいになって残念

改善点

  • わざわざカメラのイメージを320×240に縮小する必要なかった。4個ずつ同じ深度に置けば良かった。
  • 単純に点を描写するのではなく、triangulateとかしてもうすこし画面をスムーズにした方がいいのかな。要勉強

Kinect関連記事

  • Kinect関連記事