0

我在我的应用程序中使用 Kinect OpenTK。在一个类中,我使用WindowLoaded方法,该方法在循环中调用SensorSkeletonFrameReady并写入控制台计算的右手坐标。

在我调用的主窗口类OnRenderFrame中,它在循环中将立方体绘制到视口。

所以基本上我需要将坐标从SensorSkeletonFrameReadykinectControl 发送到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 线程带入混合中。捕获该事件时,您通常希望对 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);
}

KinectSensorManagerKinectWpfViewers示例项目中的一个辅助函数;Kinect 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 回答