Kinect v2のジェスチャーでBing Mapsを未来的に直感操作する

2015年1月14日(水)
薬師寺 国安

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

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

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

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

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

01Private Sub DrawHandState(joint As Joint, state As HandState, myTrackingConfidence As TrackingConfidence)
02    If myTrackingConfidence <> TrackingConfidence.High Then
03        Return
04    End If
05    If state = HandState.Open Then   (1)
06        Index = 1
07    ElseIf state = HandState.Closed Then   (2)
08        Index = 2
09    Else    (3)
10        Index = 3
11    End If
12End Sub
  1. 手がパーの状態なら、Indexの値を1で初期化します。
  2. 手がグーの状態の場合は、メンバー変数Indexを2で初期化します。
  3. それ以外は「3」で初期化します。

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

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

01Private Sub DrawEllipse(myJoint As Joint, R As Integer, myBrush As Brush)
02    Dim myEllipse = New Ellipse
03    With myEllipse
04        .Width = R
05        .Height = R
06        .Fill = myBrush
07    End With
08 
09    point = myKinect.CoordinateMapper.MapCameraPointToDepthSpace(myJoint.Position) (1)
10    If point.X < 0 OrElse point.Y < 0 Then
11        Return
12    End If
13    Canvas.SetLeft(myEllipse, point.X - (R / 2))   (2)
14    Canvas.SetTop(myEllipse, point.Y - (R / 2))
15    If myJoint.JointType = JointType.HandRight Then
16        Select Case Index   (3)
17            Case 1
18                myMap.ZoomLevel += 0.1
19            Case 2
20                myMap.ZoomLevel -= 0.1
21            Case 3
22                Index = 0
23                Exit Sub
24        End Select
25    End If
26    CanvasBody.Children.Add(myEllipse)
27End Sub

透明な直径10ピクセルの円を作成します。直径はDrawEllipseを呼ぶ際に指定しています(リスト4)。

  1. CoordinateMapper.MapCameraPointToDepthSpaceメソッドで、関節の位置を、カメラ空間から距離空間へのポイントにマップし、メンバー変数pointで参照します。
  2. SetLeftとSetTopメソッドで透明な円を、指定したXとY軸に描きます。
  3. メンバー変数Indexの値で条件分岐を行います。Indexの値が1、つまり手の状態がパーなら地図を0.1ずつズームインし、Indexの値が2、つまり手の状態がグーなら地図を0.1ずつズームアウトします。

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

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

1Private Sub MainWindow_Closing(sender As Object, e As CancelEventArgs) Handles Me.Closing
2    If myKinect Is Nothing = False Then
3        myKinect.Close()
4        myKinect = Nothing
5    End If
6End Sub
7End Class

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

実際に動作させてみた際の画面は、動画1のようになります。

  • Kinect v2でBing Mapsを操作するプログラム

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

薬師寺国安事務所代表。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メルマガ会員のサービス内容を見る

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