1

残念ながら、私はまだ新しい Kinect SDK 1.7 に少し苦労しています。この問題は、実際には「リフレクション c# を介したイベントの検索」: Click イベントと同じコンテキストにあります(ただし、この問題を理解するために必要ではありません)。

私の問題は単純です。右手でカーソル (「新しい」Kinect HandPointer) を制御していて、それが画面の左上隅にある場合、座標 (0,0) を返す必要があります。カーソルが右下隅にある場合、座標はそれぞれ現在の画面解像度 (1920,1080) になります。

新しい SDK には、HandPointer と一緒に移動し、(左上の場合) 0.0 から (右下の場合) 1.0 までの値を持つ各 HandPointer (最大 4) のいわゆる PhysicalInteractionZones (PIZ) があります。つまり、Kinect の前でのユーザーの動きに応じて動的に変化するため、画面へのマッピングには使用できません。少なくとも、それを機能させる方法を見つけることができませんでした。

次に、SkeletonStream を介して試してみました。右手の座標が追跡され、クリック ジェスチャが登録されるとすぐに、この特定のポイントで Click-Event がトリガーされます。次のコードで試しました。

private void ksensor_SkeletonFrameReady(object sender, SkeletonFrameReadyEventArgs e)
    {
        using (SkeletonFrame frame = e.OpenSkeletonFrame())
        {
            if (frame != null)
            {
                frame.CopySkeletonDataTo(this._FrameSkeletons);
                var accelerometerReading = 
                    Settings.Instance.ksensor.AccelerometerGetCurrentReading();
                ProcessFrame(frame);
                _InteractionStream.ProcessSkeleton(_FrameSkeletons,
                    accelerometerReading, frame.Timestamp);
            }
        }
    }

private void ProcessFrame(ReplaySkeletonFrame frame)
    {
        foreach (var skeleton in frame.Skeletons)
        {
            if (skeleton.TrackingState != SkeletonTrackingState.Tracked)
                continue;
            foreach (Joint joint in skeleton.Joints)
            {
                if (joint.TrackingState != JointTrackingState.Tracked)
                    continue;
                if (joint.JointType == JointType.HandRight)
                {
                    _SwipeGestureDetectorRight.Add(joint.Position,
                        Settings.Instance.ksensor);
                    _RightHand = GetPosition(joint);
                    myTextBox.Text = _RightHand.ToString();
                }
                if (joint.JointType == JointType.HandLeft)
                {
                    _SwipeGestureDetectorLeft.Add(joint.Position, 
                        Settings.Instance.ksensor);
                    _LeftHand = GetPosition(joint);
                }
            }
        }
    }

補助GetPositionメソッドは次のように定義されます。

private Point GetPosition(Joint joint)
    {
        DepthImagePoint point = 
            Settings.Instance.ksensor.CoordinateMapper.MapSkeletonPointToDepthPoint(joint.Position, Settings.Instance.ksensor.DepthStream.Format);
        point.X *= 
            (int)Settings.Instance.mainWindow.ActualWidth / Settings.Instance.ksensor.DepthStream.FrameWidth;
        point.Y *= 
            (int)Settings.Instance.mainWindow.ActualHeight / Settings.Instance.ksensor.DepthStream.FrameHeight;

        return new Point(point.X, point.Y);
    }

クリック ジェスチャが検出されるとすぐに、simpleinvokeClick(_RightHand)が呼び出されてクリックが実行されます。クリック自体は完全に正常に機能しています (その問題について回答してくれた人々に感謝します)。これまでのところ機能していないのは、座標のみを取得するため、座標のマッピングです

x 軸: 900 ~ 1500 (左から右) y 軸: 300 ~ 740 (上から下)

また、これらの座標は、画面上の特定のポイントに 100 または 200 ピクセルずつ到達しようとするたびに変化します。たとえば、画面の左側は最初は 900 ですが、手を Kinect の範囲外に移動すると、 (背中の後ろまたはテーブルの下)そして左側に向かって動きを繰り返すと、突然700かそのあたりの座標が得られます。(それぞれ) のScaleToメソッドも試してみましたが、x:300000、y:-100000、または 240000 のクレイジーな座標が得られました...アイデアが不足しているので、誰かが私のために持っていることを願っています。これに対する解決策でさえあります。Coding4Fun.Kinect.WpfScaleTo(1920,1080)ScaleTo(SystemParameters.PrimaryScreenWidth,SystemParameters.PrimaryScreenHight)

長文で申し訳ありませんが、できるだけ具体的に書いてみました。助けてくれてありがとう!

4

3 に答える 3

2

InteractionHandPointer クラスには、手の画面座標が含まれています。このコードは SDK デモから変更しました。ジャンプするための多くのフープがあります!:

this.sensor.DepthFrameReady += this.Sensor_DepthFrameReady;
this.interaction = new InteractionStream(sensor, new InteractionClient());
this.interaction.InteractionFrameReady += interaction_InteractionFrameReady;

...

private void Sensor_DepthFrameReady(object sender, DepthImageFrameReadyEventArgs e)
{
    using (var frame = e.OpenDepthImageFrame())
    {
        if (frame != null)
        {
            try
            {
                interaction.ProcessDepth(frame.GetRawPixelData(), frame.Timestamp);
            }
            catch (InvalidOperationException) { }
        }
    }
}

private void interaction_InteractionFrameReady(object sender, InteractionFrameReadyEventArgs e)
{
    using (var frame = e.OpenInteractionFrame())
    {
        if (frame != null)
        {
            if ((interactionData == null) || 
                (interactionData.Length !== InteractionStream.FrameUserInfoArrayLength))
            {
                interactionData = new UserInfo[InteractionStream.FrameUserInfoArrayLength];
            }
            frame.CopyInteractionDataTo(interactionData);

            foreach (var ui in interactionData)
            {
                foreach (var hp in ui.HandPointers)
                {
                    // Get screen coordinates
                    var screenX = hp.X * DisplayWidth;
                    var screenY = hp.Y * DisplayHeight;

                    // You can also access IsGripped, IsPressed etc.
                }
            }
        }
    }
}

public class InteractionClient: IInteractionClient
{
    public InteractionInfo GetInteractionInfoAtLocation(
        int skeletonTrackingId,
        InteractionHandType handType,
        double x, double y)
    {
        return new InteractionInfo();
    }
}
于 2013-06-20T14:05:32.580 に答える
1

この問題を解決する別の方法は、「スケルトンの基本 - WPF」という名前の kinect sdk ツールキット v1.8 の例で提供されているコードを使用することです。その場合、スケルトン ポイントを受け取り、次のようにポイントを返すように関数が既に設定されています。

    private Point SkeletonPointToScreen(SkeletonPoint skelpoint)
    {
        // Convert point to depth space.  
        // We are not using depth directly, but we do want the points in our 640x480 output resolution.
        DepthImagePoint depthPoint = this.sensor.CoordinateMapper.MapSkeletonPointToDepthPoint(skelpoint, DepthImageFormat.Resolution640x480Fps30);
        return new Point(depthPoint.X, depthPoint.Y);

    }
于 2013-12-02T16:10:43.077 に答える