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

本文关键字:之间 共享 onrenderframe kinect 类和 opentk | 更新日期: 2023-09-27 17:53:58

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

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

所以基本上我需要将坐标从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

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

轮询是一种选择,但我仍然不清楚是否有必要将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工具包的一部分。使用上面的方法,我的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线程上唯一发生的事情是你的handler函数内部发生的事情,或者它调用的东西。