2012年8月28日火曜日

KINECTサンプル(C#) Depthカメラ for SDK1.5

今回はDepthカメラのデータを表示してみます。

RGBカメラのデータは色情報ですので、ほぼそのまま画像データとして利用できますが、Depthカメラのデータは距離データ+αなのでそれを画像データに変換することが必要になります。

MainWindow.xaml
------------------------------------------------------------------------------

<Window x:Class="KinectDepthforSDK15.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="MainWindow" Height="520" Width="700">
    <Grid>
        <Image Name="Depth" Stretch="Uniform" Height="480" Width="640" />
    </Grid>
</Window>
------------------------------------------------------------------------------

RGBカメラの時と同様にイメージコントロールを一つ配置しています。


MainWindow.xaml.cs
------------------------------------------------------------------------------

using System;
using System.Windows;
using System.Windows.Media;
using System.Windows.Media.Imaging;

using Microsoft.Kinect;

namespace KinectDepthforSDK15
{
    /// <summary>
    /// MainWindow.xaml の相互作用ロジック
    /// </summary>
    public partial class MainWindow : Window
    {
        KinectSensor kinect;

        public MainWindow()
        {
            InitializeComponent();

            //接続の確認
            if (KinectSensor.KinectSensors.Count == 0)
            {
                MessageBox.Show("KINECTが見つかりません。");
                Close();
            }

            kinect = KinectSensor.KinectSensors[0];

            //Depthカメラの設定
            kinect.DepthStream.Enable(DepthImageFormat.Resolution640x480Fps30);

            //イベントの登録
            kinect.DepthFrameReady += new EventHandler<DepthImageFrameReadyEventArgs>(kinect_DepthFrameReady);

            //KINECTのスタート
            kinect.Start();

        }

        void kinect_DepthFrameReady(object sender, DepthImageFrameReadyEventArgs e)
        {
            using (DepthImageFrame depthFrame = e.OpenDepthImageFrame())
            {
                if (depthFrame != null)
                {
                    //Depthカメラの深度データ
                    short[] depthPixel = new short[depthFrame.PixelDataLength];
                    depthFrame.CopyPixelDataTo(depthPixel);

                    //表示用画像データ配列(画像データは4チャンネル必要なので要素数は4倍になる)
                    byte[] colorPixel = new byte[depthFrame.Width*depthFrame.Height * 4];

                    //距離データから画像を生成するループ
                    int j = 0;

                    for (int i = 0; i < depthPixel.Length; i++)
                    {
                        //距離データの取り出し
                        short depth = (short)( depthPixel[i] >> DepthImageFrame.PlayerIndexBitmaskWidth);

                        //画素データに変換(距離データのうち下位1バイトで表現している)
                        //SDKのDepthサンプルを参考
                        byte dist = (byte)((depth + 1) & byte.MaxValue);    //byte.MaxValue=255

                        //距離データ(0-4095)を100分率で表現するなら次の式で
                        //byte dist = (byte)(255 - (255 * depth / 4095));

                        //距離データ 13ビットを4ビットシフトしてから8ビット分だけ取り出す場合
                        //byte dist = (byte)(depth + 1 >> 4 & byte.MaxValue);

                        //RGBイメージ配列に書込み
                        colorPixel[j] = dist;
                        colorPixel[j + 1] = dist;
                        colorPixel[j + 2] = dist;
                        j += 4;
                    }

                    //イメージコントロールに設定
                    Depth.Source = BitmapSource.Create(depthFrame.Width, depthFrame.Height, 96, 96, PixelFormats.Bgr32, null, colorPixel, depthFrame.Width * 4);

                }
            }
        }

    }
}


------------------------------------------------------------------------------

プログラムの前半はRGBカメラの時とほとんど変わりません。

Depthカメラからのデータは1ピクセルあたり2バイト(16ビット)になりますのでshort型配列に取り込みます。

表示用のイメージデータはBGR32タイプになるので画像サイズ(640*480)の4倍必要になります。

距離データは16ビット中上位13ビットで標準モードの場合0-4095(mm)の距離を表します。残り3ビットは認識しているプレイヤーのIDが入るのですが、今回は骨格認識を有効にしていないので利用できません。

 「depthPixel[i] >> DepthImageFrame.PlayerIndexBitmaskWidth」で3ビット右にシフトして距離データを取り出しています。

距離データは0-4095の値になるのでこれを0-255(画素データは8ビット)に収まるようにすれば距離に応じたイメージデータを得ることができます。
SDKのサンプルでは取り出した距離データに1を足して(計測できない距離データが-1になるのでそれを補正しているのだと思います。)から下位8ビットデータを取り出して画素データとしています。
ほかにもいろいろ表現の仕方はあると思います。

得られた画像を見てみると人物などに影ができていますが、これはDepthカメラの仕様(赤外線を利用している)でどうしてもできてしまうようです。





0 件のコメント:

コメントを投稿