Kinect v2のジェスチャーでBing Mapsを未来的に直感操作する
2015年1月14日(水)

新しいボディフレームの準備ができているときに発生するイベント処理
リスト4:MainWindow.xaml.vbの一部 (リスト3の続き)
Private Sub myBodyFrameReader_FrameArrived(sender As Object, e As BodyFrameArrivedEventArgs) 'CanvasBody.Children.Clear() 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) 'CInt((body.Joints(JointType.ThumbRight).Position.X)) (7) myHandPositionY = CInt(myColorSpacePoint.Y * 0.5) 'CInt((body.Joints(JointType.ThumbRight).Position.Y)) DrawHandState(body.Joints(JointType.HandRight), body.HandRightState, body.HandRightConfidence) End If End If End If Next Next End Sub
- e.FrameReference.AcquireFrameメソッドで、ボディフレームを取得し、myBodyFrameで参照します。myBodyFrameに何もなかった場合は、何も行いません。
- GetAndRefreshBodyDataメソッドで、更新されたボディデータを取得します。
- CanvasBody内を一度クリアしておきます。
- ボディデータの中を、反復処理を行いながら、繰り返し変数jointで関節の位置を反復処理しながら、位置を取得していきます。
- 関節が追跡されている場合は、関節の位置と、関節の位置を描く円の大きさと描く色(透明)を指定して、DrawEllipseを実行します。
- 右手が追跡されている場合は、CoordinateMapper.MapCameraPointToColorSpaceメソッドで、関節の位置をカメラ空間から距離空間へのポイントにマップし、変数myColorSpacePointで参照します。
- 手のXとY軸の位置を取得して、メンバー変数、myHandPositionXとmyHandPositionYに格納します。右手の位置と、右手の状態と、右手を追跡している精度を引数にして、DrawHandStateを実行します。
プレイヤーの手の形によって条件分岐を行う処理
リスト5:MainWindow.xaml.vbの一部(リスト4の続き)
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 (1) Index = 1 ElseIf state = HandState.Closed Then (2) Index = 2 Else (3) Index = 3 End If End Sub
- 手がパーの状態なら、Indexの値を1で初期化します。
- 手がグーの状態の場合は、メンバー変数Indexを2で初期化します。
- それ以外は「3」で初期化します。
関節の位置に透明の円を表示する処理
リスト6:MainWindow.xaml.vbの一部(リスト5の続き)
Private Sub DrawEllipse(myJoint As Joint, R As Integer, myBrush As Brush) Dim myEllipse = New Ellipse With myEllipse .Width = R .Height = R .Fill = myBrush End With point = myKinect.CoordinateMapper.MapCameraPointToDepthSpace(myJoint.Position) (1) If point.X < 0 OrElse point.Y < 0 Then Return End If Canvas.SetLeft(myEllipse, point.X - (R / 2)) (2) Canvas.SetTop(myEllipse, point.Y - (R / 2)) If myJoint.JointType = JointType.HandRight Then Select Case Index (3) Case 1 myMap.ZoomLevel += 0.1 Case 2 myMap.ZoomLevel -= 0.1 Case 3 Index = 0 Exit Sub End Select End If CanvasBody.Children.Add(myEllipse) End Sub
透明な直径10ピクセルの円を作成します。直径はDrawEllipseを呼ぶ際に指定しています(リスト4)。
- CoordinateMapper.MapCameraPointToDepthSpaceメソッドで、関節の位置を、カメラ空間から距離空間へのポイントにマップし、メンバー変数pointで参照します。
- SetLeftとSetTopメソッドで透明な円を、指定したXとY軸に描きます。
- メンバー変数Indexの値で条件分岐を行います。Indexの値が1、つまり手の状態がパーなら地図を0.1ずつズームインし、Indexの値が2、つまり手の状態がグーなら地図を0.1ずつズームアウトします。
ウインドウが閉じられる場合の処理
リスト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 End Class
Kinectが動作している場合は、Kinectを閉じ、全ての関連付けから解放します。
実際に動作させてみた際の画面は、動画1のようになります。
連載バックナンバー
Think ITメルマガ会員登録受付中
Think ITでは、技術情報が詰まったメールマガジン「Think IT Weekly」の配信サービスを提供しています。メルマガ会員登録を済ませれば、メルマガだけでなく、さまざまな限定特典を入手できるようになります。