| using System;␊ |
| using System.Windows;␊ |
| using System.Windows.Controls;␊ |
| using System.Windows.Media;␊ |
| using System.Windows.Media.Imaging;␊ |
| using System.Windows.Shapes;␊ |
| using Microsoft.Kinect;␊ |
| using System.Linq;␊ |
| ␊ |
| namespace kinectTest␊ |
| {␊ |
| public partial class MainWindow : Window␊ |
| {␊ |
| //Instantiate the Kinect runtime. Required to initialize the device.␊ |
| //IMPORTANT NOTE: You can pass the device ID here, in case more than one Kinect device is connected.␊ |
| KinectSensor sensor = KinectSensor.KinectSensors[0];␊ |
| byte[] pixelData;␊ |
| Skeleton[] skeletons;␊ |
| ␊ |
| public MainWindow()␊ |
| {␊ |
| InitializeComponent();␊ |
| ␊ |
| //Runtime initialization is handled when the window is opened. When the window␊ |
| //is closed, the runtime MUST be unitialized.␊ |
| this.Loaded += new RoutedEventHandler(MainWindow_Loaded);␊ |
| this.Unloaded += new RoutedEventHandler(MainWindow_Unloaded);␊ |
| ␊ |
| sensor.ColorStream.Enable();␊ |
| sensor.SkeletonStream.Enable();␊ |
| }␊ |
| ␊ |
| void runtime_SkeletonFrameReady(object sender, SkeletonFrameReadyEventArgs e)␊ |
| {␊ |
| bool receivedData = false;␊ |
| ␊ |
| using (SkeletonFrame SFrame = e.OpenSkeletonFrame())␊ |
| {␊ |
| if (SFrame == null)␊ |
| {␊ |
| // The image processing took too long. More than 2 frames behind.␊ |
| }␊ |
| else␊ |
| {␊ |
| skeletons = new Skeleton[SFrame.SkeletonArrayLength];␊ |
| SFrame.CopySkeletonDataTo(skeletons);␊ |
| receivedData = true;␊ |
| }␊ |
| }␊ |
| ␊ |
| if (receivedData)␊ |
| {␊ |
| ␊ |
| Skeleton currentSkeleton = (from s in skeletons␊ |
| where s.TrackingState == SkeletonTrackingState.Tracked␊ |
| select s).FirstOrDefault();␊ |
| ␊ |
| if (currentSkeleton != null)␊ |
| {␊ |
| SetEllipsePosition(head, currentSkeleton.Joints[JointType.Head]);␊ |
| SetEllipsePosition(leftHand, currentSkeleton.Joints[JointType.HandLeft]);␊ |
| SetEllipsePosition(rightHand, currentSkeleton.Joints[JointType.HandRight]);␊ |
| }␊ |
| }␊ |
| }␊ |
| ␊ |
| public void ClampPositionToCircle(SkeletonPoint center, float radius, ref SkeletonPoint position)␊ |
| {␊ |
| // Calculate the offset vector from the center of the circle to our position␊ |
| SkeletonPoint offset = new SkeletonPoint();␊ |
| offset.X = position.X - center.X;␊ |
| offset.Y = position.Y - center.Y;␊ |
| offset.Z = position.Z;␊ |
| // Calculate the linear distance of this offset vector␊ |
| double distance = Math.Abs(Math.Sqrt((offset.X * offset.X) + (offset.Y * offset.Y)));␊ |
| if (radius < distance)␊ |
| {␊ |
| // If the distance is more than our radius we need to clamp␊ |
| // Calculate the direction to our position␊ |
| SkeletonPoint direction = new SkeletonPoint();␊ |
| direction.X = (float)(offset.X / distance);␊ |
| direction.Y = (float)(offset.Y / distance);␊ |
| direction.Z = offset.Z;␊ |
| //Vector2 direction = offset / distance;␊ |
| // Calculate our new position using the direction to our old position and our radius␊ |
| position.X += center.X * radius;␊ |
| position.Y += center.Y * radius;␊ |
| ␊ |
| //position = center + direction * radius;␊ |
| }␊ |
| }␊ |
| ␊ |
| ␊ |
| //This method is used to position the ellipses on the canvas␊ |
| //according to correct movements of the tracked joints.␊ |
| ␊ |
| //IMPORTANT NOTE: Code for vector scaling was imported from the Coding4Fun Kinect Toolkit␊ |
| //available here: http://c4fkinect.codeplex.com/␊ |
| //I only used this part to avoid adding an extra reference.␊ |
| private void SetEllipsePosition(Ellipse ellipse, Joint joint)␊ |
| {␊ |
| Microsoft.Kinect.SkeletonPoint vector = new Microsoft.Kinect.SkeletonPoint();␊ |
| vector.X = ScaleVector(640, joint.Position.X);␊ |
| vector.Y = ScaleVector(480, -joint.Position.Y);␊ |
| vector.Z = joint.Position.Z;␊ |
| ␊ |
| Joint updatedJoint = new Joint();␊ |
| updatedJoint = joint;␊ |
| updatedJoint.TrackingState = JointTrackingState.Tracked;␊ |
| updatedJoint.Position = vector;␊ |
| ␊ |
| SkeletonPoint center = new SkeletonPoint();␊ |
| center.X = 0;␊ |
| center.Y = 0;␊ |
| SkeletonPoint pos = updatedJoint.Position;␊ |
| ClampPositionToCircle(center, 10.0f, ref pos);␊ |
| updatedJoint.Position = pos;␊ |
| Canvas.SetLeft(ellipse, updatedJoint.Position.X);␊ |
| Canvas.SetTop(ellipse, updatedJoint.Position.Y);␊ |
| }␊ |
| ␊ |
| ␊ |
| private float ScaleVector(int length, float position)␊ |
| {␊ |
| float value = (((((float)length) / 1f) / 2f) * position) + (length / 2);␊ |
| if (value > length)␊ |
| {␊ |
| return (float)length;␊ |
| }␊ |
| if (value < 0f)␊ |
| {␊ |
| return 0f;␊ |
| }␊ |
| return value;␊ |
| }␊ |
| ␊ |
| void MainWindow_Unloaded(object sender, RoutedEventArgs e)␊ |
| {␊ |
| sensor.Stop();␊ |
| }␊ |
| ␊ |
| void MainWindow_Loaded(object sender, RoutedEventArgs e)␊ |
| {␊ |
| sensor.SkeletonFrameReady += runtime_SkeletonFrameReady;␊ |
| sensor.ColorFrameReady += runtime_VideoFrameReady;␊ |
| sensor.Start();␊ |
| }␊ |
| ␊ |
| void runtime_VideoFrameReady(object sender, ColorImageFrameReadyEventArgs e)␊ |
| {␊ |
| bool receivedData = false;␊ |
| ␊ |
| using (ColorImageFrame CFrame = e.OpenColorImageFrame())␊ |
| {␊ |
| if (CFrame == null)␊ |
| {␊ |
| // The image processing took too long. More than 2 frames behind.␊ |
| }␊ |
| else␊ |
| {␊ |
| pixelData = new byte[CFrame.PixelDataLength];␊ |
| CFrame.CopyPixelDataTo(pixelData);␊ |
| receivedData = true;␊ |
| }␊ |
| }␊ |
| ␊ |
| if (receivedData)␊ |
| {␊ |
| BitmapSource source = BitmapSource.Create(640, 480, 96, 96,␊ |
| PixelFormats.Bgr32, null, pixelData, 640 * 4);␊ |
| ␊ |
| videoImage.Source = source;␊ |
| }␊ |
| }␊ |
| }␊ |
| }␊ |