Kinectで手の動きに合わせてモニタ上の画像を動かすサンプル

前ページからの続きです。
スケルトンの位置を取得する処理
Kinectセンサーの距離カメラから、距離カメラのフレームデータを表すDepthImageFrameクラス型のdepth変数を宣言し、OpenDepthImageFrameメソッドで、距離カメラのフレームデータを取得します。
距離データのピクセル座標、および距離、プレイヤーIDを表す、DepthImagePoint構造体のleftDepthPoint変数を宣言し、MapFromSkeletonPointメソッドで、スケルトンの座標を、距離カメラの座標に変換します。この場合、左手の位置を距離カメラの座標に変換します。同じく右手の位置も距離カメラの座標に変換します。MapFromSkeletonPointメソッドの書式は下記の通りです。
DepthImageFrame. MapFromSkeletonPoint(変換するスケルトン座標)
次に、RGBデータのピクセル座標を表す、ColorImagePoint構造体の変数leftColorPointを宣言し、MapToColorImagePointメソッドで、距離カメラの座標をRGBカメラの座標に変換します。書式は下記の通りです。
DepthFrameImage.MapToColorImagePoint(距離カメラのX座標,距離カメラのY座標,RGBカメラのフォーマット)
この場合、左手の距離カメラのX座標と、Y座標をRGBフォーマット(解像度が640×480、フレーム レートは 毎秒30フレーム)に変換しています。同様に右手に対しても同じ処理を行います。
距離カメラのデータをRGBカメラ(実写)のデータにマップします。
RGBカメラの座標に変換された、左手のデータと右手のデータを引数に、画像が回転するScaleプロシージャを実行します。
Image1とRGBカメラの座標に変換された、左手、右手のデータを引数に、手の動きに合わせて画像の位置が変化するCameraPositionプロシージャを実行します。
左手のY座標が、右手のY座標より15㎝以上大きく、または、右手のY座標の位置が、左手のY座標より15㎝以上大きい場合は、画像を回転するImageRotateプロシージャを実行します。右手と左手、または右手と左手が、上下に15㎝以上離れて重なった場合に画像が回転します。
左手が上の場合はmyFlagはTrue、右手が上の場合はmyFlagはFalseとします。この値で右回転か左回転かを決めています。
Private Sub GetCameraPoint(ByVal first As Skeleton, ByVal e As AllFramesReadyEventArgs)
Try
Using depth As DepthImageFrame = e.OpenDepthImageFrame()
Dim leftDepthPoint As DepthImagePoint = depth.MapFromSkeletonPoint(first.Joints(JointType.HandLeft).Position)
Dim rightDepthPoint As DepthImagePoint = depth.MapFromSkeletonPoint(first.Joints(JointType.HandRight).Position)
Dim leftColorPoint As ColorImagePoint = depth.MapToColorImagePoint(leftDepthPoint.X, leftDepthPoint.Y, ColorImageFormat.RgbResolution640x480Fps30)
'right hand
Dim rightColorPoint As ColorImagePoint = depth.MapToColorImagePoint(rightDepthPoint.X, rightDepthPoint.Y, ColorImageFormat.RgbResolution640x480Fps30)
Scale(leftColorPoint, rightColorPoint)
CameraPosition(Image1, leftColorPoint)
CameraPosition(Image1, rightColorPoint)
If leftColorPoint.Y > rightColorPoint.Y + 150 OrElse rightColorPoint.Y > leftColorPoint.Y + 150 Then
If leftColorPoint.Y > rightColorPoint.Y + 150 Then myFlag = True
If rightColorPoint.Y > leftColorPoint.Y + 150 Then myFlag = False
ImageRotate()
End If
End Using
Catch
Exit Sub
End Try
End Sub
画像が拡大縮小する処理
myScaleという名前を持つ、ScaleTransformのScaleX(x軸のスケールファクターを設定)とScaleY(y軸のスケールファクターを設定)に、RGBのピクセル座標に変換された左手のX座標の位置から、右手のX座標の位置を差し引いた値に0.01を乗算して指定します。0.01を乗算しないと巨大な画像が表示されますので、必ず0.01乗算する必要があります。
Private Sub Scale(lcolorPoint As ColorImagePoint, rcolorPoint As ColorImagePoint)
myScale.ScaleX = (lcolorPoint.X - rcolorPoint.X) * 0.01
myScale.ScaleY = (lcolorPoint.X - rcolorPoint.X) * 0.01
myRotate.Angle = 180
End Sub
画像が回転する処理
myFlagがTrueなら右回転、Falseなら左回転になります。メンバ変数noの値を10ずつ増減させて、Angleの値に指定して回転させます。10度ずつ回転します。画像の中心を軸に回転するよう
myRotate.CenterX = Image1.Width / 2
myRotate.CenterY = Image1.Height / 2
と指定しておきます。
Private Sub ImageRotate()
If no >= 360 Then no = 0
myRotate.Angle = no
myScale.ScaleX = 1.5
myScale.ScaleY = 1.5
myRotate.CenterX = Image1.Width / 2
myRotate.CenterY = Image1.Height / 2
If myFlag = True Then
no = no + 10
Else
no = no - 10
End If
End Sub
画像が、右手、左手の動きに反応する処理
Coding4Fun Kinect ToolkitのScaleToメソッドで、指定した幅と高さにJointオブジェクトの位置をスケーリングします。書式は下記です。1920×1080は筆者のPCの解像度です。
Joint.ScaleTo(width As Integer, height As Integer)
Canvas.SetLeftとSetTopプロパティの書式は下記です。
Canvas.SetLeft(プロパティ値の書き込み対象の要素,指定した要素のCanvas.Left属性を設定)
Canvas.SetTop(プロパティ値の書き込み対象の要素,指定した要素のCanvas.Top属性を設定)
Private Sub ScalePosition(ByVal element As FrameworkElement, ByVal joint As Joint)
Dim scaledJoint As Joint = joint.ScaleTo(1920, 1080)
Canvas.SetLeft(element, scaledJoint.Position.X)
Canvas.SetTop(element, scaledJoint.Position.Y)
End Sub
手の動きに合わせて画像の位置が変化する処理
Canvas.SetLeftとSetTopプロパティの書式は下記です。
Canvas.SetLeft(プロパティ値の書き込み対象の要素,指定した要素のCanvas.Left属性を設定)
Canvas.SetTop(プロパティ値の書き込み対象の要素,指定した要素のCanvas.Top属性を設定)
Private Sub CameraPosition(ByVal element As FrameworkElement, ByVal point As ColorImagePoint)
Canvas.SetLeft(element, point.X - (CLng(element.Width) / 2))
Canvas.SetTop(element, point.Y - CLng(element.Height) / 2)
End Sub
円が手の動きに合わせて動く処理
Private Sub SetEllipsePosition(myEllipse As Ellipse, myJoint As Joint)
Canvas.SetLeft(myEllipse, (320 * myJoint.Position.X) + 320)
Canvas.SetTop(myEllipse, (240 * -myJoint.Position.Y) + 240)
End Sub
Kinect センサーを停止する処理
Kinectセンサーが動作している場合は、動作を停止してリソースを解放します。
Private Sub StopKinect(ByVal sensor As KinectSensor)
If sensor Is Nothing = False Then
If sensor.IsRunning = True Then
sensor.Stop()
sensor.Dispose()
End If
End If
End Sub
ウィンドウが閉じられる時に発生するイベント
Kinect センサーを停止するStopKinectプロシージャを、動作しているKinect センサーを引数にして実行します。
Private Sub MainWindow_Closing(sender As Object, e As System.ComponentModel.CancelEventArgs) Handles Me.Closing
StopKinect(newSensor)
End Sub
End Class
今回のサンプルは以上で終了です。
連載バックナンバー
Think ITメルマガ会員登録受付中
全文検索エンジンによるおすすめ記事
- Kinectで人体を認識して棒人間を動かすサンプル
- Kinectを使って、自分の手のひらに小さな分身を出現させてみる
- Kinectで手の動きに合わせて波紋を発生させるサンプル
- 声で選んだアイテムをプレイヤーの身体に装着・連動させるKinectサンプル
- Kinectで手の動きとカーソルを連動して操作するサンプル
- プレイヤーの身体パーツを判別するKinectサンプル
- Kinectを使って、顔の動きを認識して画面に表示する
- Kinectで得た人体情報を転送して、Windows Phoneの画面上に関節の位置を表示してみる
- Kinectを使ったバーチャル試着室で着せ替えシミュレーション
- 人体の連続した動作を音声でキャプチャするKinectのサンプルプログラム


