Kinect v2で実現する打楽器のバーチャル演奏
2014年12月22日(月)

プログラムコード
次に、ソリューションエクスプローラー内のMainWindow.xamlを展開して表示される、MainWindow.xaml.vbにリスト2のコードを記述します。
名前空間の読み込みとメンバー変数の宣言
リスト2:(MainWindow.xaml.vbの一部)
01 | Imports Microsoft.Kinect |
02 | Imports System.ComponentModel |
03 | Public Class MainWindow |
04 |
05 | Private myKinect As KinectSensor |
06 | Private myBodyFrameReader As BodyFrameReader |
07 | Private myBodies As Body() |
08 | Private myHandPositionX As Double |
09 | Private myHandPositionY As Double |
10 | Private myColorSpacePoint As ColorSpacePoint (1) |
11 |
12 | Private myBytesPerPixel As Integer = 4 |
13 | Private myColorFrameReader As ColorFrameReader = Nothing |
14 | Private colorBitmap As WriteableBitmap = Nothing |
15 | Private ColorImagePixelData As Byte() |
16 | Private BytesPerPixel As Integer = 4 |
17 | Private commonJoint As Joint (2) |
18 | Private point As DepthSpacePoint (3) |
19 |
20 | Private Index As Integer = 0 |
21 | Private no As Integer = 0 |
名前空間の読み込みとメンバー変数の宣言については、ほとんどが第2回目と同じですので、ここでは異なるメンバー変数の主なものだけ解説しておきます。
- カラー空間における2Dの位置を表す構造体のメンバー変数、myColorSpacePointを宣言します。
- 身体の関節の位置を表すJoint構造体のメンバー変数、commonJointを宣言します。
- 距離空間における2Dの位置を表す構造体のメンバー変数、pointを宣言します。
ウインドウが読み込まれた時の処理
リスト3:(MainWindow.xaml.vbの一部、リスト2の続き)
01 | Private Sub MainWindow_Loaded(sender As Object, e As RoutedEventArgs) Handles Me.Loaded |
02 | myKinect = KinectSensor.GetDefault (1) |
03 | If myKinect Is Nothing = False Then |
04 | Dim myDepthDescription = myKinect.DepthFrameSource.FrameDescription (2) |
05 | myKinect.Open() (3) |
06 | myBodyFrameReader = myKinect.BodyFrameSource.OpenReader (4) |
07 | AddHandler myBodyFrameReader.FrameArrived, AddressOf myBodyFrameReader_FrameArrived (5) |
08 | myBodies = New Body(myKinect.BodyFrameSource.BodyCount - 1) {} (6) |
09 | myColorFrameReader = myKinect.ColorFrameSource.OpenReader (7) |
10 | Dim myColorFrameDescripton As FrameDescription = myKinect.ColorFrameSource.CreateFrameDescription(ColorImageFormat.Bgra) |
11 | ColorImagePixelData = New Byte(myColorFrameDescripton.Width * myColorFrameDescripton.Height * BytesPerPixel - 1) {} (8) |
12 | colorBitmap = New WriteableBitmap(myColorFrameDescripton.Width, myColorFrameDescripton.Height, 96.0, 96.0, PixelFormats.Bgr32, Nothing) (9) |
13 | AddHandler myColorFrameReader.FrameArrived, AddressOf myColorFrameReader_FrameArrived (10) |
14 | End If |
15 | End Sub |
- 最初に、Kinectセンサーを使用可能にします。Kinectセンサーが使用可能な状態にある場合は、以下の処理を行います。
- 距離フレームプロパティの形式を取得し、変数myDepthDescriptionで参照します。
- Kinectを動作させます。
- BodyFrameSource.OpenReaderで、ボディフレームのソースフレームのリーダーを作成し、変数myBodyFrameReaderで参照します。
- myBodyFrameReader.FrameArrivedで、新しいボディフレームの準備ができているときに発生するイベント処理を実行します。
- ボディフレームソースのボディの個数を引数に持った、新しいBodyの配列をmyBodiesに格納します。
- myKinect.ColorFrameSource.OpenReaderで、カラーフレームのソースフレームのリーダーを作成し、myColorFrameReaderメンバー変数で参照します。
- 配列変数ColorImagePixelDataを確保します。
- ピクセル データを格納するビットマップを作成し、変数colorBitmapで参照します。
- myColorFrameReader.FrameArrivedでカラーフレーム到着時のイベントを実行します。
新しいボディフレームの準備ができているときに発生するイベント処理
リスト4:(MainWindow.xaml.vbの一部、リスト3の続き)
01 | Private Sub myBodyFrameReader_FrameArrived(sender As Object, e As BodyFrameArrivedEventArgs) |
02 | Using myBodyFrame = e.FrameReference.AcquireFrame (1) |
03 | If myBodyFrame Is Nothing = True Then |
04 | Return |
05 | End If |
06 | myBodyFrame.GetAndRefreshBodyData(myBodies) (2) |
07 | End Using |
08 | CanvasBody.Children.Clear() (3) |
09 | For Each body In myBodies |
10 | For Each joint In body.Joints (4) |
11 | If joint.Value.TrackingState = TrackingState.Tracked Then |
12 | DrawEllipse(joint.Value, 10, Brushes.Transparent) (5) |
13 | If joint.Value.JointType = JointType.HandRight Then |
14 | If body.Joints(JointType.HandTipRight).TrackingState = TrackingState.Tracked Then |
15 | myColorSpacePoint = myKinect.CoordinateMapper.MapCameraPointToColorSpace(body.Joints(JointType.HandTipRight).Position) (6) |
16 | myHandPositionX = CInt(myColorSpacePoint.X * 0.5) |
17 | myHandPositionY = CInt(myColorSpacePoint.Y * 0.5) (7) |
18 | DrawHandState(body.Joints(JointType.HandRight), body.HandRightState, body.HandRightConfidence) (8) |
19 | End If |
20 | End If |
21 | End If |
22 | Next |
23 | Next |
24 | End Sub |
- e.FrameReference.AcquireFrameメソッドで、ボディフレームを取得し、myBodyFrameで参照します。myBodyFrameに何もなかった場合は、何も行いません。
- GetAndRefreshBodyDataメソッドで、更新されたボディデータを取得します。
- Canvas内を一度クリアしておきます。
- ボディデータの中で反復処理を行いながら、繰り返し変数jointで関節の位置を反復処理して、関節位置を取得していきます。
- 関節が追跡されている場合は、関節の位置と関節の位置を表す円の大きさ、関節の位置を描く色に透明を指定して、DrawEllipseを実行します。
- 右手が追跡されている場合は、CoordinateMapper.MapCameraPointToDepthSpaceメソッドで関節の位置をカメラ空間から距離空間へのポイントにマップし、変数myColorSpacePointで参照します。
- 手のXとY軸の位置を取得して、メンバー変数myHandPositionXとmyHandPositionYに格納します。
- 右手の位置と、右手の状態と、右手を追跡している精度を引数にして、DrawHandStateを実行します。
連載バックナンバー
Think ITメルマガ会員登録受付中
Think ITでは、技術情報が詰まったメールマガジン「Think IT Weekly」の配信サービスを提供しています。メルマガ会員登録を済ませれば、メルマガだけでなく、さまざまな限定特典を入手できるようになります。
全文検索エンジンによるおすすめ記事
- Kinect v2を使って、机の上のリンゴをつかんで移動してみる
- Kinect v2の音声認識で「仮面」を選んで変身してみる
- Kinect v2のジェスチャーでBing Mapsを未来的に直感操作する
- Kinect v2のカメラから画像を取り込んで表示する基本プログラム
- Kinect v2を使った「じゃんけんゲーム」を作る
- Kinectで手の動きに合わせてモニタ上の画像を動かすサンプル
- Kinect v2のIRセンサーから赤外線画像を読み込む
- Kinectで人体を認識して棒人間を動かすサンプル
- 声で選んだアイテムをプレイヤーの身体に装着・連動させるKinectサンプル
- Kinect v2の深度センサーから取り込んだ画像を表示する