Kinect v2で実現する打楽器のバーチャル演奏

2014年12月22日(月)
薬師寺 国安

プログラムコード

次に、ソリューションエクスプローラー内のMainWindow.xamlを展開して表示される、MainWindow.xaml.vbにリスト2のコードを記述します。

名前空間の読み込みとメンバー変数の宣言

リスト2:(MainWindow.xaml.vbの一部)

Imports Microsoft.Kinect
Imports System.ComponentModel
Public Class MainWindow

Private myKinect As KinectSensor
Private myBodyFrameReader As BodyFrameReader
Private myBodies As Body()
Private myHandPositionX As Double
Private myHandPositionY As Double
Private myColorSpacePoint As ColorSpacePoint   (1)

Private myBytesPerPixel As Integer = 4
Private myColorFrameReader As ColorFrameReader = Nothing
Private colorBitmap As WriteableBitmap = Nothing
Private ColorImagePixelData As Byte()
Private BytesPerPixel As Integer = 4
Private commonJoint As Joint   (2)
Private point As DepthSpacePoint   (3)

Private Index As Integer = 0
Private no As Integer = 0

名前空間の読み込みとメンバー変数の宣言については、ほとんどが第2回目と同じですので、ここでは異なるメンバー変数の主なものだけ解説しておきます。

  1. カラー空間における2Dの位置を表す構造体のメンバー変数、myColorSpacePointを宣言します。
  2. 身体の関節の位置を表すJoint構造体のメンバー変数、commonJointを宣言します。
  3. 距離空間における2Dの位置を表す構造体のメンバー変数、pointを宣言します。

ウインドウが読み込まれた時の処理

リスト3:(MainWindow.xaml.vbの一部、リスト2の続き)

Private Sub MainWindow_Loaded(sender As Object, e As RoutedEventArgs) Handles Me.Loaded
        myKinect = KinectSensor.GetDefault   (1)
        If myKinect Is Nothing = False Then
             Dim myDepthDescription = myKinect.DepthFrameSource.FrameDescription   (2)
            myKinect.Open()   (3)
            myBodyFrameReader = myKinect.BodyFrameSource.OpenReader (4)
            AddHandler myBodyFrameReader.FrameArrived, AddressOf myBodyFrameReader_FrameArrived   (5)
            myBodies = New Body(myKinect.BodyFrameSource.BodyCount - 1) {}   (6)
            myColorFrameReader = myKinect.ColorFrameSource.OpenReader (7)
            Dim myColorFrameDescripton As FrameDescription = myKinect.ColorFrameSource.CreateFrameDescription(ColorImageFormat.Bgra)
            ColorImagePixelData = New Byte(myColorFrameDescripton.Width * myColorFrameDescripton.Height * BytesPerPixel - 1) {}   (8)
            colorBitmap = New WriteableBitmap(myColorFrameDescripton.Width, myColorFrameDescripton.Height, 96.0, 96.0, PixelFormats.Bgr32, Nothing) (9)
            AddHandler myColorFrameReader.FrameArrived, AddressOf myColorFrameReader_FrameArrived   (10)
        End If
End Sub
  1. 最初に、Kinectセンサーを使用可能にします。Kinectセンサーが使用可能な状態にある場合は、以下の処理を行います。
  2. 距離フレームプロパティの形式を取得し、変数myDepthDescriptionで参照します。
  3. Kinectを動作させます。
  4. BodyFrameSource.OpenReaderで、ボディフレームのソースフレームのリーダーを作成し、変数myBodyFrameReaderで参照します。
  5. myBodyFrameReader.FrameArrivedで、新しいボディフレームの準備ができているときに発生するイベント処理を実行します。
  6. ボディフレームソースのボディの個数を引数に持った、新しいBodyの配列をmyBodiesに格納します。
  7. myKinect.ColorFrameSource.OpenReaderで、カラーフレームのソースフレームのリーダーを作成し、myColorFrameReaderメンバー変数で参照します。
  8. 配列変数ColorImagePixelDataを確保します。
  9. ピクセル データを格納するビットマップを作成し、変数colorBitmapで参照します。
  10. myColorFrameReader.FrameArrivedでカラーフレーム到着時のイベントを実行します。

新しいボディフレームの準備ができているときに発生するイベント処理

リスト4:(MainWindow.xaml.vbの一部、リスト3の続き)

Private Sub myBodyFrameReader_FrameArrived(sender As Object, e As BodyFrameArrivedEventArgs)
        Using myBodyFrame = e.FrameReference.AcquireFrame   (1)
            If myBodyFrame Is Nothing = True Then
                Return
            End If
            myBodyFrame.GetAndRefreshBodyData(myBodies)   (2)
        End Using
        CanvasBody.Children.Clear()   (3)
        For Each body In myBodies
            For Each joint In body.Joints   (4)
                If joint.Value.TrackingState = TrackingState.Tracked Then
                    DrawEllipse(joint.Value, 10, Brushes.Transparent)   (5)
                    If joint.Value.JointType = JointType.HandRight Then
                        If body.Joints(JointType.HandTipRight).TrackingState = TrackingState.Tracked Then
                            myColorSpacePoint = myKinect.CoordinateMapper.MapCameraPointToColorSpace(body.Joints(JointType.HandTipRight).Position)   (6)
                            myHandPositionX = CInt(myColorSpacePoint.X * 0.5)
                            myHandPositionY = CInt(myColorSpacePoint.Y * 0.5)   (7)
                            DrawHandState(body.Joints(JointType.HandRight), body.HandRightState, body.HandRightConfidence)   (8)
                        End If
                    End If
                 End If
            Next
        Next
End Sub
  1. e.FrameReference.AcquireFrameメソッドで、ボディフレームを取得し、myBodyFrameで参照します。myBodyFrameに何もなかった場合は、何も行いません。
  2. GetAndRefreshBodyDataメソッドで、更新されたボディデータを取得します。
  3. Canvas内を一度クリアしておきます。
  4. ボディデータの中で反復処理を行いながら、繰り返し変数jointで関節の位置を反復処理して、関節位置を取得していきます。
  5. 関節が追跡されている場合は、関節の位置と関節の位置を表す円の大きさ、関節の位置を描く色に透明を指定して、DrawEllipseを実行します。
  6. 右手が追跡されている場合は、CoordinateMapper.MapCameraPointToDepthSpaceメソッドで関節の位置をカメラ空間から距離空間へのポイントにマップし、変数myColorSpacePointで参照します。
  7. 手のXとY軸の位置を取得して、メンバー変数myHandPositionXとmyHandPositionYに格納します。
  8. 右手の位置と、右手の状態と、右手を追跡している精度を引数にして、DrawHandStateを実行します。
  • Kinect v2で実現する打楽器のバーチャル演奏のサンプル

    『作りながら学ぶKinect v2プログラミング開発』 第3回のサンプルプログラムです。
薬師寺国安事務所

薬師寺国安事務所代表。Visual Basic プログラミングと、マイクロソフト系の技術をテーマとした、書籍や記事の執筆を行う。
1950年生まれ。事務系のサラリーマンだった40歳から趣味でプログラミングを始め、1996年より独学でActiveXに取り組む。1997年に薬師寺聖とコラボレーション・ユニット PROJECT KySS を結成。2003年よりフリーになり、PROJECT KySS の活動に本格的に参加、.NETやRIAに関する書籍や記事を多数執筆する傍ら、受託案件のプログラミングも手掛ける。Windows Phoneアプリ開発を経て、現在はWindows ストア アプリを多数公開中

Microsoft MVP for Development Platforms - Client App Dev (Oct 2003-Sep 2012)。Microsoft MVP for Development Platforms - Windows Phone Development(Oct 2012-Sep 2013)。Microsoft MVP for Development Platforms - Client Development(Oct 2013-Sep 2014)。Microsoft MVP for Development Platforms-Windows Platform Development (Oct 2014-Sep 2015)。

連載バックナンバー

Think ITメルマガ会員登録受付中

Think ITでは、技術情報が詰まったメールマガジン「Think IT Weekly」の配信サービスを提供しています。メルマガ会員登録を済ませれば、メルマガだけでなく、さまざまな限定特典を入手できるようになります。

Think ITメルマガ会員のサービス内容を見る

他にもこの記事が読まれています