PR

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

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

カラーフレーム到着時のイベント

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

Private Sub myColorFrameReader_FrameArrived(sender As Object, e As ColorFrameArrivedEventArgs)
        Dim colorFrameProcessed As Boolean = False
        Using myColorFrame As ColorFrame = e.FrameReference.AcquireFrame   (1)
            If myColorFrame Is Nothing = False Then
                Dim myColorFrameDescription As FrameDescription = myColorFrame.FrameDescription   (2)
                If myColorFrameDescription.Width = colorBitmap.PixelWidth AndAlso myColorFrameDescription.Height = colorBitmap.PixelHeight Then
                    If myColorFrame.RawColorImageFormat = ColorImageFormat.Bgra Then   (3)
                        myColorFrame.CopyRawFrameDataToArray(ColorImagePixelData)
                    Else
                        myColorFrame.CopyConvertedFrameDataToArray(ColorImagePixelData, ColorImageFormat.Bgra)
                    End If
                    colorFrameProcessed = True   (4)
                End If
            End If
        End Using
        If colorFrameProcessed = True Then
            colorBitmap.WritePixels(New Int32Rect(0, 0, colorBitmap.PixelWidth, colorBitmap.PixelHeight), ColorImagePixelData, colorBitmap.PixelWidth * BytesPerPixel, 0)    (5)
            roomImage.Source = colorBitmap   (6)
        End If
End Sub
  1. e.FrameReference.AcquireFrameメソッドでカラーフレームを取得し、myColorFrameで参照します。
  2. myColorFrameにデータがあった場合、KinectSensor から、イメージフレームのプロパティを取得し、変数myColorFrameDescriptionで参照します。
    取得したプロパティの幅と高さが、colorBitmapのPixelWidth、PixelHeightと同じであった場合、以下の処理を実行します。
  3. カラーフレームデータの形式がBgraであった場合は、CopyRawFrameDataToArrayメソッドで、Raw フレームのデータ指定された配列(ColorImagePixelData)にコピーします。
    そうでない場合は、CopyConvertedFrameDataToArrayメソッドで、フレームから「BGRA形式」のバイト列に変換し、バイト配列に格納します。書式は下記の通りです。
    CopyConvertedFrameDataToArray(frameData,colorFomat)
    「frameData」には格納する配列、この場合はバイト配列のColorImagePixelDataを指定しています。「colorFormat」には色の形式を指定します。この場合は「Bgra形式」を指定しています。
  4. Boolean型で宣言していた変数colorFrameProcessedをTrueで初期化します。
  5. 変数colorFrameProcessed変数がTrueであった場合は、colorBitmap(WriteableBitmapクラス)のWritePixelsメソッドで、ビットマップの指定した領域内のピクセルを更新します。書式は下記の通りです。
    WritePixels(sourecRect,pixels,stride,offset)
    「sourceRect」には更新するWriteableBitmapの四角形を表す「Int32Rect型」を指定します。「pixels」にはビットマップの更新に使用する「ピクセル配列」を指定します。この場合は、ColorImagePixelDataのバイト列を指定しています。「stride」にはpixels内の更新領域の「ストライド」を指定します。今回はcolorBitmapのPixelWidthにメンバー変数BytesPerPixel(値は4)の4をかけた値を指定しています。「ストライド」とは、画像データのX座標横一列あたりに用いられるバイト数を示す値です。「offset」には入力バッファのオフセットを指定します。今回は「0」を指定しています。
  6. roomImageのSourceプロパティにcolorBitmapオブジェクトを指定します。これでRGBカメラからの画像が表示されます。

プレイヤーの手の形によって条件分岐を行う処理

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

Private Sub DrawHandState(joint As Joint, state As HandState, myTrackingConfidence As TrackingConfidence)
        If myTrackingConfidence <> TrackingConfidence.High Then
            Return
        End If
        If state = HandState.Open Then
            Index = 0   (1)
        ElseIf state = HandState.Closed Then
            If point.X > Image1.GetValue(Canvas.LeftProperty) And point.X < Image1.GetValue(Canvas.LeftProperty) + Image1.Width AndAlso point.Y > Image1.GetValue(Canvas.TopProperty) And point.Y < Image1.GetValue(Canvas.TopProperty) + Image1.Height Then
                Index = 1
            End If
            If point.X > Image2.GetValue(Canvas.LeftProperty) And point.X < Image2.GetValue(Canvas.LeftProperty) + Image2.Width AndAlso point.Y > Image2.GetValue(Canvas.TopProperty) And point.Y < Image2.GetValue(Canvas.TopProperty) + Image2.Height Then
                Index = 2
            End If
        End If
End Sub

手がパーの状態なら、Indexの値を0で初期化します。手がグーの状態の場合は、まず太鼓とドラムの位置を取得します。太鼓の位置を取得できたらIndexを1に、ドラムの位置が取得できたらIndexを2に初期化します。
リスト8で、ここで取得したIndexの値で条件分岐を行い、Indexが1で太鼓、Indexが2でドラムの音が鳴るようにしています。

ウインドウが閉じられる場合の処理

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

Private Sub MainWindow_Closing(sender As Object, e As CancelEventArgs) Handles Me.Closing
        If myKinect Is Nothing = False Then
            myKinect.Close()
            myKinect = Nothing
        End If
End Sub

Kinectが動作している場合はKinectを閉じ、全ての関連付けから解放します。

関節の位置に透明の円を表示する処理

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

Private Sub DrawEllipse(myJoint As Joint, R As Integer, myBrush As Brush)
        Dim myEllipse = New Ellipse
        With myEllipse   (1)
            .Width = R
            .Height = R
            .Fill = myBrush
        End With
        point = myKinect.CoordinateMapper.MapCameraPointToDepthSpace(myJoint.Position) (2)
        If point.X < 0 OrElse point.Y < 0 Then
            Return
        End If
        Canvas.SetLeft(myEllipse, point.X - (R / 2))   (3)
        Canvas.SetTop(myEllipse, point.Y - (R / 2))
        If myJoint.JointType = JointType.HandRight Then
            'TextBlock1.Text = Index
            Select Case Index
                Case 1
                    MediaElement1.Play()
                Case 2
                    MediaElement2.Play()
            End Select
        End If
        CanvasBody.Children.Add(myEllipse)
End Sub
  1. 透明な半径10pixelの円を作成します。半径は呼び出し時に引数で指定しています。
  2. CoordinateMapper.MapCameraPointToDepthSpaceメソッドで、関節の位置を、カメラ空間から距離空間へのポイントにマップし、メンバー変数pointで参照します。
  3. SetLeftとSetTopメソッドに透明な円を指定し、XとY軸に描きます。
  4. メンバー変数Indexが1の場合はMediaElement1(太鼓)、2の場合はMediaElement2(ドラム)を再生します。

音の再生が終わった時の処理

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

Private Sub MediaElement1_MediaEnded(sender As Object, e As RoutedEventArgs) Handles MediaElement1.MediaEnded
        MediaElement1.Close()
End Sub

Private Sub MediaElement2_MediaEnded(sender As Object, e As RoutedEventArgs) Handles MediaElement2.MediaEnded
        MediaElement2.Close()
End Sub
End Class

実際に動かしてみた様子を動画に示します。

Think IT会員限定特典
  • 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のWebサイトにログインすることでさまざまな限定特典を入手できるようになります。

Think IT会員サービスの概要とメリットをチェック

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

Kinect v2で実現する打楽器のバーチャル演奏 | Think IT(シンクイット)

Think IT(シンクイット)

サイトに予期せぬエラーが起こりました。しばらくたってから再度お試しください。