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のサンプルプログラム