我在我的应用程序中使用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
答案 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);
}
KinectSensorManager
是KinectWpfViewers
示例项目中的辅助函数; 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线程中唯一发生的事情是处理函数内部或它调用的内容。