ロジックコードを記述する
2 | Imports Microsoft.Kinect |
一個のKinectセンサーを表すKinectSensorクラスのメンバ変数Kinectを宣言しておきます。
1 | Dim Kinect As KinectSensor |
整数四角形の幅、高さ、および位置を表すInt32Rect構造体のメンバ変数myScreenImageRectを宣言します。領域の指定に使用されます。
1 | Dim myScreenImageRect As Int32Rect |
Short型の配列メンバ変数myDepthPixelDataとByte型の配列メンバ変数myColorPixelDataを宣言しておきます。
※深度情報は、1ピクセルあたり2バイトのshort型。画像情報はフルカラーなので1ピクセルあたり4バイトのbyte型です。
1 | Dim myDepthPixelData As Short() |
3 | Dim myColorPixelData As Byte() |
ピクセル深度を格納するためのDouble型のメンバ変数myDepthを宣言しておきます。
1 | Private myDepth As Double |
WriteableBitmapクラス型のHuman_Image1_Bitmap(楕円の輪より背面に来るプレイヤー)、Human_Image2_Bitmap(楕円の輪より前面に来るプレイヤー)、Room_Bitmap(一番奥に位置する部屋(背景))プロパティを定義しておきます。WriteableBitmapクラスは、書き込みおよび更新が可能なBitmapSourceを提供するクラスです。ここで定義したプロパティをImageコントロールのSourceプロパティにバインドしています。
1 | Property Human_Image1_Bitmap As WriteableBitmap |
2 | Property Human_Image2_Bitmap As WriteableBitmap |
3 | Property Room_Bitmap As WriteableBitmap |
ウィンドウが読み込まれた時の処理
ピクセル深度の値を2400(2m40cm)で初期化しておきます。Kinectセンサーを取得し、ビットマップデータを初期化し、プレイヤーの画層(レイヤー)を初期化するinit_kinectプロシージャを実行します。
構成ツリーのオブジェクトがレンダリングされる直前に発生する、CompositionTarget.Renderingイベントにイベントハンドラを指定します。イベントハンドラ内では以下の処理を行います。
OpenNextFrame(100)メソッドで、KinectからRGBデータの次のフレームを開きます。次のフレームがなかった場合のタイムアウトを100ミリセコンドと指定しています。同様に、Kinectから深度データの次のフレームを開きます。次のフレームがなかった場合のタイムアウトを100ミリセコンドと指定しています。
背景を描画し距離データを取得するRenderScreenプロシージャを実行します。引数として、Kinectのストリーミング用RGBデータのバッファと深度データのバッファを含んでいる、colorFrameとdepthFrameを渡しています。DataContextプロパティにMainWindow自身のインスタンスを指定します。この処理を行わないとプレイヤーが表示されませんので注意してください。
01 | Private Sub MainWindow_Loaded(sender As Object, e As System.Windows.RoutedEventArgs) Handles Me.Loaded |
05 | AddHandler CompositionTarget.Rendering, Sub(renderSender As Object, renderArgs As EventArgs) |
06 | Using colorFrame As ColorImageFrame = Kinect.ColorStream.OpenNextFrame(100) |
07 | Using depthFrame As DepthImageFrame = Kinect.DepthStream.OpenNextFrame(100) |
08 | RenderScreen(colorFrame, depthFrame) |
Kinectデバイスを取得し、ビットマップデータを初期化し、プレイヤーの画層(レイヤー)を初期化する処理
Kinectセンサーを取得します。DepthStream.Enableメソッドで距離カメラの表示サイズを640×480、1秒あたり30フレームで、動作を開始します。同様にColorStream.Enableメソッドで、RDBカメラを、RGBフォーマット、表示サイズ640×480、1秒あたり30フレームで、動作を開始します。プレイヤーおよびスケルトンの認識も開始します。
骨格生成を行う場合は、深度センサー(距離カメラ)を有効にする必要があります。Dim depthStream As DepthImageStream = Kinect.DepthStreamで、距離カメラの処理を行うクラスのインスタンスを取得します。Short配列変数myDepthPixelDataに距離カメラのピクセルデータのバイト長分の配列を作成します。640×480の表示サイズの場合は、myDepthPixelData=New Short(307200-1){}分の配列を確保することになります。-1しているのは配列のインデックスは0から始まるためです。
バイト配列変数myColorPixelDataにRGBカメラのピクセルデータのバイト長分の配列を作成します。
WriteableBitmapクラス型のRoom_Bitmapを下記の書式で初期化します。
New WriteableBitmap(距離カメラのフレーム幅,距離カメラのフレーム高さ, ビットマップの水平値, ビットマップの垂直値,ビットマップのピクセルフォーマット,ビットマップのビットマップパレット)
「ビットマップのピクセルフォーマット」には、PixelFormats.Bgra32を指定します。Bgra32 は、bits per pixel(BPP)が 32 の sRGB 形式です。各カラー チャネル(青、緑、赤、およびアルファ)に割り当てられるbits per pixel(BPP)は 8 です。ここに、Brg32を指定すると背景が透明化されず真っ黒になってしまいますので注意してください。
ここは、Room_Bitmap = New WriteableBitmap(640, 480, 96, 96, PixelFormats.Bgra32, Nothing)
と指定しても同じです。
同様に、Human_Image1_Bitmap、Human_Image2_BitmapについてもWriteableBitmapの書式で初期化しておきます。
IntRect32構造体のmyScreenImageRectを下記の書式で初期化し、領域を指定します。
New IntRect32(新しいInt32Rect のインスタンスの X座標,新しいInt32Rect のインスタンスの Y座標, 四角形の幅を指定した新しい Int32Rect のインスタンスの幅, 四角形の高さを指定した新しい Int32Rect のインスタンスの高さ)
「新しいInt32Rect のインスタンスの X座標」と「新しいInt32Rect のインスタンスの Y座標」には0を指定します。「四角形の幅を指定した新しい Int32Rect のインスタンスの幅」には、Human_Image2_Bitmapオブジェクトの幅を指定し、「Int32Rect のインスタンスの高さ」には、Human_Image2_Bitmapオブジェクトの高さを指定します。
結局は、
myScreenImageRect = New Int32Rect(0, 0, 640, 480)
と指定しても同じことです。
Kinectを動作させます。
01 | Private Sub init_kinect() |
03 | If KinectSensor.KinectSensors.Count = 0 Then |
04 | MessageBox.Show("Kinectが接続されていません。") |
07 | Kinect = KinectSensor.KinectSensors(0) |
10 | Kinect.DepthStream.Enable(DepthImageFormat.Resolution640x480Fps30) |
11 | Kinect.ColorStream.Enable(ColorImageFormat.RgbResolution640x480Fps30) |
12 | Kinect.SkeletonStream.Enable() |
14 | Dim depthStream = Kinect.DepthStream |
15 | myDepthPixelData = New Short(Kinect.DepthStream.FramePixelDataLength - 1) {} |
16 | myColorPixelData = New Byte(Kinect.ColorStream.FramePixelDataLength - 1) {} |
19 | Room_Bitmap = New WriteableBitmap(depthStream.FrameWidth, depthStream.FrameHeight, 96, 96, PixelFormats.Bgra32, Nothing) |
20 | Human_Image1_Bitmap = New WriteableBitmap(depthStream.FrameWidth, depthStream.FrameHeight, 96, 96, PixelFormats.Bgra32, Nothing) |
21 | Human_Image2_Bitmap = New WriteableBitmap(depthStream.FrameWidth, depthStream.FrameHeight, 96, 96, PixelFormats.Bgra32, Nothing) |
23 | myScreenImageRect = New Int32Rect(0, 0, CInt(Math.Ceiling(Human_Image2_Bitmap.Width)), CInt(Math.Ceiling(Human_Image2_Bitmap.Height))) |
26 | MessageBox.Show(ex.Message) |