Kinectを使って、画面上の赤い輪をくぐるサンプル
ロジックコードを記述する
Option Strict On Imports Microsoft.Kinect Class MainWindow
一個のKinectセンサーを表すKinectSensorクラスのメンバ変数Kinectを宣言しておきます。
Dim Kinect As KinectSensor
整数四角形の幅、高さ、および位置を表すInt32Rect構造体のメンバ変数myScreenImageRectを宣言します。領域の指定に使用されます。
Dim myScreenImageRect As Int32Rect
Short型の配列メンバ変数myDepthPixelDataとByte型の配列メンバ変数myColorPixelDataを宣言しておきます。
※深度情報は、1ピクセルあたり2バイトのshort型。画像情報はフルカラーなので1ピクセルあたり4バイトのbyte型です。
Dim myDepthPixelData As Short() Dim myColorPixelData As Byte()
ピクセル深度を格納するためのDouble型のメンバ変数myDepthを宣言しておきます。
Private myDepth As Double
WriteableBitmapクラス型のHuman_Image1_Bitmap(楕円の輪より背面に来るプレイヤー)、Human_Image2_Bitmap(楕円の輪より前面に来るプレイヤー)、Room_Bitmap(一番奥に位置する部屋(背景))プロパティを定義しておきます。WriteableBitmapクラスは、書き込みおよび更新が可能なBitmapSourceを提供するクラスです。ここで定義したプロパティをImageコントロールのSourceプロパティにバインドしています。
Property Human_Image1_Bitmap As WriteableBitmap Property Human_Image2_Bitmap As WriteableBitmap 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自身のインスタンスを指定します。この処理を行わないとプレイヤーが表示されませんので注意してください。
Private Sub MainWindow_Loaded(sender As Object, e As System.Windows.RoutedEventArgs) Handles Me.Loaded myDepth = 2400 init_kinect() AddHandler CompositionTarget.Rendering, Sub(renderSender As Object, renderArgs As EventArgs) Using colorFrame As ColorImageFrame = Kinect.ColorStream.OpenNextFrame(100) Using depthFrame As DepthImageFrame = Kinect.DepthStream.OpenNextFrame(100) RenderScreen(colorFrame, depthFrame) End Using End Using End Sub DataContext = Me End Sub
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を動作させます。
Private Sub init_kinect() Try If KinectSensor.KinectSensors.Count = 0 Then MessageBox.Show("Kinectが接続されていません。") Exit Sub Else Kinect = KinectSensor.KinectSensors(0) End If Kinect.DepthStream.Enable(DepthImageFormat.Resolution640x480Fps30) Kinect.ColorStream.Enable(ColorImageFormat.RgbResolution640x480Fps30) Kinect.SkeletonStream.Enable() Dim depthStream = Kinect.DepthStream myDepthPixelData = New Short(Kinect.DepthStream.FramePixelDataLength - 1) {} myColorPixelData = New Byte(Kinect.ColorStream.FramePixelDataLength - 1) {} Room_Bitmap = New WriteableBitmap(depthStream.FrameWidth, depthStream.FrameHeight, 96, 96, PixelFormats.Bgra32, Nothing) Human_Image1_Bitmap = New WriteableBitmap(depthStream.FrameWidth, depthStream.FrameHeight, 96, 96, PixelFormats.Bgra32, Nothing) Human_Image2_Bitmap = New WriteableBitmap(depthStream.FrameWidth, depthStream.FrameHeight, 96, 96, PixelFormats.Bgra32, Nothing) myScreenImageRect = New Int32Rect(0, 0, CInt(Math.Ceiling(Human_Image2_Bitmap.Width)), CInt(Math.Ceiling(Human_Image2_Bitmap.Height))) Kinect.Start() Catch ex As Exception MessageBox.Show(ex.Message) Exit Sub End Try End Sub
Kinectで赤い輪をくぐるサンプル
連載バックナンバー
Think ITメルマガ会員登録受付中
全文検索エンジンによるおすすめ記事
- Kinectを使って、自分の手のひらに小さな分身を出現させてみる
- 人体の連続した動作を音声でキャプチャするKinectのサンプルプログラム
- Kinectで結成したマイ・ダンスチームを、サンプルを見ながら実際の背景に合成してみよう
- Kinectの音声認識を使って、プレイヤーを分離、結合させるデモを試してみる
- これであなたもダンスグループの一員!?Kinectで自分を分身させるプログラムを作る
- プレイヤーの身体パーツを判別するKinectサンプル
- Kinectで距離カメラの値を取得して、指定した距離で人物が背景に溶け込むサンプル
- 人物を切り抜いて画面に表示するKinectサンプル
- 人物特定に使える!?実際の映像で顔を認識するKinectプログラム
- Kinectを使って、顔の動きを認識して画面に表示する