0

Kinect をOpenTKアプリケーションで使用しています。あるクラスではWindowLoaded、メソッドを使用します。このメソッドは、ループ呼び出しSensorSkeletonFrameReadyで、計算された右手の座標をコンソールに書き込みます。

メイン ウィンドウ クラスで を呼び出しますOnRenderFrame。これは、ループで立方体をビューポートに描画します。

したがって、基本的にSensorSkeletonFrameReadyは kinectControl からOnRenderFrameメイン ウィンドウ クラスに座標を送信する必要があります。

スレッドでこれを達成しようとしましたが、値を送信する方法がわかりません。

編集:

これはメインウィンドウ クラスです。

                ...
                public class MainWindow : GameWindow
                {
                ...
                /*Kinect thread start*/
                        kinectControl kinectObject = new kinectControl();
                        Thread oThread = new Thread(new ThreadStart(kinectObject.WindowLoaded));
                        oThread.Start();
                        ...
protected override void OnRenderFrame(FrameEventArgs e)
        {
        ...
        //Here I need get coordinates from kinectControl

                        DrawCube();
                        ...

そして、これは kinectControl クラスです:

    ...
    private void SensorSkeletonFrameReady(object sender, SkeletonFrameReadyEventArgs e)
    {
    ...
            foreach (Skeleton skeleton in skeletons)
            {
                Joint rightHand = skeleton.Joints[JointType.HandRight];
                Joint leftHand = skeleton.Joints[JointType.HandLeft];
                Joint head = skeleton.Joints[JointType.Head];

                double leftY = leftHand.Position.Y;
                double headY = head.Position.Y;




                // get the individual points of the right hand
                double rightX = rightHand.Position.X;
                double rightY = rightHand.Position.Y;
                double rightZ = rightHand.Position.Z;

                //here I need send this coordinates to mainwindow class

...

Edit2: 解決策を見つけました。イベントを登録する代わりに、OnRenderFrame メソッドの OpenNextFrame メソッドでポーリングを使用します。

public void findSkeleton()//random name of function
        {
            Skeleton[] skeletons = new Skeleton[0];

            SkeletonFrame skeletonFrame = this.sensor.SkeletonStream.OpenNextFrame(0);

                if (skeletonFrame != null)
                {
                    skeletons = new Skeleton[skeletonFrame.SkeletonArrayLength];
                    skeletonFrame.CopySkeletonDataTo(skeletons);
                }
...//rest is the same as in SensorSkeletonFrameReady event
4

1 に答える 1

0

ポーリングはオプションですが、Kinect コードを別のスレッドに配置する必要があるかどうかはまだわかりません。Kinect によって行われるすべてのポーリングと処理は、UI スレッドから既に行われていFrameReadyます。UI スレッドをミックスに持ち込むのは、イベントの 1 つをキャプチャするときだけです。そのイベントをキャプチャするときは、通常、とにかく UI で何かをしたいと考えています。

個人的には、次のコア構造を使用して

private readonly KinectSensorChooser _sensorChooser = new KinectSensorChooser();

public MainViewModel()
{
    KinectSensorManager = new KinectSensorManager();
    KinectSensorManager.KinectSensorChanged += OnKinectSensorChanged;

    _sensorChooser.Start();

    if (_sensorChooser.Kinect == null)
    {
        MessageBox.Show("Unable to detect an available Kinect Sensor");
        Application.Current.Shutdown();
    }

    // Bind the KinectSensor from the sensorChooser to the KinectSensor on the KinectSensorManager
    var kinectSensorBinding = new Binding("Kinect") { Source = _sensorChooser };
    BindingOperations.SetBinding(this.KinectSensorManager, KinectSensorManager.KinectSensorProperty, kinectSensorBinding);
}

これは、サンプル プロジェクトKinectSensorManagerにあるヘルパー関数です。KinectWpfViewersKinect for Windows Toolkit の一部です。上記を使用して、Kinect は次のように初期化されます。

#region Kinect Discovery & Setup

private void OnKinectSensorChanged(object sender, KinectSensorManagerEventArgs<KinectSensor> args)
{
    if (null != args.OldValue)
        UninitializeKinectServices(args.OldValue);

    if (null != args.NewValue)
        InitializeKinectServices(KinectSensorManager, args.NewValue);
}

/// <summary>
/// Initialize Kinect based services.
/// </summary>
/// <param name="kinectSensorManager"></param>
/// <param name="sensor"></param>
private void InitializeKinectServices(KinectSensorManager kinectSensorManager, KinectSensor sensor)
{
    // configure the color stream
    kinectSensorManager.ColorFormat = ColorImageFormat.RgbResolution640x480Fps30;
    kinectSensorManager.ColorStreamEnabled = true;

    // configure the depth stream
    kinectSensorManager.DepthStreamEnabled = true;

    kinectSensorManager.TransformSmoothParameters =
        new TransformSmoothParameters
        {
            // as the smoothing value is increased responsiveness to the raw data
            // decreases; therefore, increased smoothing leads to increased latency.
            Smoothing = 0.5f,
            // higher value corrects toward the raw data more quickly,
            // a lower value corrects more slowly and appears smoother.
            Correction = 0.5f,
            // number of frames to predict into the future.
            Prediction = 0.5f,
            // determines how aggressively to remove jitter from the raw data.
            JitterRadius = 0.05f,
            // maximum radius (in meters) that filtered positions can deviate from raw data.
            MaxDeviationRadius = 0.04f
        };

    // configure the skeleton stream
    sensor.SkeletonFrameReady += OnSkeletonFrameReady;
    kinectSensorManager.SkeletonStreamEnabled = true;

    // initialize the gesture recognizer
    _gestureController = new GestureController();
    _gestureController.GestureRecognized += OnGestureRecognized;

    kinectSensorManager.KinectSensorEnabled = true;

    if (!kinectSensorManager.KinectSensorAppConflict)
    {
        // more initialization
    }
}

/// <summary>
/// Uninitialize all Kinect services that were initialized in InitializeKinectServices.
/// </summary>
/// <param name="sensor"></param>
private void UninitializeKinectServices(KinectSensor sensor)
{
    // unregister services
}

ここのコード例では、SkeletonFrameReadyイベントが定義されています。これは、他のFrameReadyイベントでも同じです。適切なハンドラーを設定してデータを取得し、必要な処理を実行できます。これで、OpenTK 参照があるメイン クラスにいます。

UI スレッドで発生するのは、ハンドラー関数の内部にあるもの、またはそれが呼び出すものだけです。

于 2013-01-18T20:37:24.230 に答える