Top > Kinect > KinectForWindowsSDK > Basics > SharpDX > ShowColorImage
Last-modified: Fri, 18 Jul 2014 15:47:58 JST
Counter:4061 Today:1 Yesterday:0 Online:3
このエントリーをはてなブックマークに追加

SharpDX と KinectV2 を使ってカメラ画像を表示する

About

遅ればせながら Kinect-V2 と KinectSDK-2.0 とを入手したので、SharpDX でカメラ画像の表示をしてみました。Kinect-V2 では解像度が格段に向上しているので、画像処理などを含めたアプリケーションを作りたい場合には、シェーダないし、DirectCompute の形で GPU を活用することになりそうです。

SharpDX や KinectV2 の詳細についてはここで解説しません。 SDK のバージョンアップによって仕様が変更されたり、ソースコードの配布先を変更したり停止したりする可能性が十分にあります。

簡単な解説

Kinect-V1 と比較して設定が可能な項目は増えていますが、最小のソースコードはむしろシンプルになった印象を受けます。

フィールドに Kinect への参照を用意しておいて、GetDefault メソッドによってインスタンスを取得、代入します。次いで Open メソッドによって Kinect の動作を開始します。

private KinectSensor kinect;
…
this.kinect = KinectSensor.GetDefault();
this.kinect.Open();

Kinect-V2 になってもイベントドリブン型とポーリング型と実装形態は2パターンあります。ただし SharpDX ではポーリング型を利用する方が良いです。これはカメラ画像などを表示するために利用する Texture2D のインスタンスを生成する際に、GPU 領域を用意することに起因します。これについては続く項目で解説します。

厳密には SharpDX でかつ DirectX 10 以降を利用する場合です。さらに SharpDX.Toolkit を使わない場合にはこの限りではありません。

カメラから取得したデータを流し込むテクスチャを用意しておきます。Texture2D のインスタンスを更新の度に毎回生成することは良くありません。Texture2D のインスタンスの生成時に、GPU(VRAM) にそのインスタンスが必要とする領域を確保してしまうからです。特に少ない VRAM の場合には、解放が追いつかずにすぐにアクセス違反が発生します。したがって、予めテクスチャを用意して、その領域を更新する手法を取ります。

そのテクスチャの更新ですが、ポーリングによって行われるべきです。イベントドリブン型で実装してしまうと、VRAM の書き換え中に、描画命令が発生する可能性があり、やはりアクセス違反が発生します。

protected override void LoadContent()
{
    this.spriteBatch = new SpriteBatch(GraphicsDevice);

    this.tex2d_ColorImage = Texture2D.New(this.GraphicsDevice,
                     this.colorFrameDescription.Width,
                     this.colorFrameDescription.Height,
                                          PixelFormat.B8G8R8A8.UNorm);
    base.LoadContent();
}

というわけで、Update メソッド内で Kinect からデータを受け取り、テクスチャを更新します。データが含まれている ColorFrame を取得するには、ColorFrameReader を取得します。予め ColorFrameReader への参照をフィールドあたりに用意しておくのも良いです。ここでは分かり易さのために、Update メソッド内で取得しています。AcquireLatestFrame メソッドによって、ColorFrame を取得します。

protected override void Update(GameTime gameTime)
{
    ColorFrame colorFrame
        = this.kinect.ColorFrameSource.OpenReader().AcquireLatestFrame();
    
    if (colorFrame == null)
    {
        return;
    }
   
    byte[] colorDataArray = new byte[colorFrameDescription.Width
                                     * colorFrameDescription.Height
                                     * colorFrameDescription.BytesPerPixel];

    colorFrame.CopyConvertedFrameDataToArray(colorDataArray, ColorImageFormat.Bgra);

    this.tex2d_ColorImage.SetData<byte>(colorDataArray);

    colorFrame.Dispose();

    base.Update(gameTime);
}

取得した ColorFrame からカメラ画像を取得します。カメラ画像は byte 配列として取得します。予めデータを受け取るのに必要な領域(配列)を用意しておき、CopyConvertedFrameDataToArray メソッドによってその領域に複製します。メソッド名の通り、変換先のフォーマットも指定しています。ここでは Bgra です。

後は受け取ったデータを用意したテクスチャに流して、このテクスチャを描画すれば良いです。