在kinect类和opentk onrenderframe类之间共享值

时间:2013-01-17 23:53:51

标签: c# kinect opentk

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

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

所以基本上我需要将kinectControl中SensorSkeletonFrameReady的坐标发送到主窗口类中的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

1 个答案:

答案 0 :(得分: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线程中唯一发生的事情是处理函数内部或它调用的内容。