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

C# 在kinect类和opentk onrenderframe类之间共享值,c#,kinect,opentk,C#,Kinect,Opentk,我在应用程序中使用Kinect和OpenTK。在一个类中,我使用WindowLoaded方法,该方法在循环中调用SensorSkeletonFrameReady并将右手的计算坐标写入控制台 在主窗口类中,我调用OnRenderFrame,它在循环中将立方体绘制到视口 所以基本上我需要将坐标从kinectControl中的SensorSkeletonFrameReady发送到主窗口类中的OnRenderFrame 我试着用线程来实现这一点,但我不知道如何发送值 编辑: 这是主窗口类:

我在应用程序中使用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

轮询是一种选择,但我仍然不清楚是否有必要将Kinect代码放在单独的线程中。Kinect完成的所有轮询和处理都已在UI线程之外完成,只有在捕获一个
FrameReady
事件时,才会将UI线程带入混合。在捕获该事件时,您通常希望对UI做些什么

就我个人而言,我使用follow核心结构

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
是在
KinectWpfViewers
示例项目中找到的辅助功能;Kinect for Windows工具包的一部分。使用上述方法,然后使用以下内容初始化my 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
}
#区域Kinect发现和设置
KinectSensorChanged上的私有无效(对象发送方,KinectSensorManagerEventArgs args)
{
if(null!=args.OldValue)
取消初始化KinectServices(args.OldValue);
if(null!=args.NewValue)
初始化KinectServices(KinectSensorManager,args.NewValue);
}
/// 
///初始化基于Kinect的服务。
/// 
/// 
/// 
private void InitializeKinectServices(Kinect传感器管理器Kinect传感器管理器,Kinect传感器)
{
//配置颜色流
kinectSensorManager.ColorFormat=ColorImageFormat.RgbResolution640x480Fps30;
kinectSensorManager.ColorStreamEnabled=true;
//配置深度流
kinectSensorManager.DepthStreamEnabled=true;
kinectSensorManager.TransformSmoothParameters=
新参数
{
//随着平滑值的增加,对原始数据的响应性增强
//减少;因此,增加平滑会导致延迟增加。
平滑度=0.5f,
//值越高,对原始数据的校正速度越快,
//值越小,校正速度越慢,看起来越平滑。
修正值=0.5f,
//要预测未来的帧数。
预测值=0.5f,
//确定从原始数据中删除抖动的力度。
吉特拉迪乌斯=0.05f,
//过滤位置可能偏离原始数据的最大半径(米)。
最大偏差半径=0.04f
};
//配置骨架流
sensor.SkeletonFrameReady+=OnSkeletonFrameReady;
kinectSensorManager.SkeletonStreamEnabled=true;
//初始化手势识别器
_gestureController=新的gestureController();
_gestureController.GestureReceignized+=OnGestureReceignized;
kinectSensorManager.KinectSensorEnabled=true;
如果(!kinectSensorManager.KinectSensorAppConflict)
{
//更多初始化
}
}
/// 
///取消初始化在InitializeKinect services中初始化的所有Kinect服务。
/// 
/// 
private void取消初始化Kinect服务(Kinect传感器)
{
//注销服务
}
在这里的示例代码中,我定义了一个
SkeletonFrameReady
事件。这对于任何其他
FrameReady
事件都是相同的。您可以设置适当的处理程序来获取数据,然后对其执行所需的操作。现在,您进入了OpenTK引用所在的主类


UI线程上发生的唯一事情是处理程序函数中的内容,或者它调用的内容。

您能在这里发布您正在讨论的适用代码吗?在循环中使用
SensorSkeletonFrameReady
没有意义——这是一个事件。您可以在与您的
OnRenderFrame
相同的类中跟踪
SensorSkeletonFrameReady
事件。有一些代码来查看您的逻辑将有助于理解您的最终目标。是的,您是对的,这是事件而不是循环,我错了。我的简短回答是,Kinect处理不需要在自己的线程中。看看Kinect for Windows工具包中的所有示例——没有一个使用线程,因为所有处理都已在UI线程之外完成;这些事件允许您捕获信息并在UI线程上进行处理。我很快会得到一个更详细的答案。