|
@@ -0,0 +1,205 @@
|
|
|
+namespace KinectCar
|
|
|
+{
|
|
|
+ using System;
|
|
|
+ using System.Collections.Generic;
|
|
|
+ using System.ComponentModel;
|
|
|
+ using System.Windows;
|
|
|
+ using System.Windows.Media;
|
|
|
+ using Microsoft.Kinect;
|
|
|
+
|
|
|
+ /// <summary>
|
|
|
+ /// MainWindow.xaml 的交互逻辑
|
|
|
+ /// </summary>
|
|
|
+ public partial class MainWindow : Window, INotifyPropertyChanged
|
|
|
+ {
|
|
|
+ // 活动的 Kinect 传感器
|
|
|
+ private KinectSensor kinectSensor = null;
|
|
|
+ // 坐标映射器将一种类型的点映射到另一种
|
|
|
+ private CoordinateMapper coordinateMapper = null;
|
|
|
+ // 身体框架渲染器
|
|
|
+ private BodyFrameReader bodyFrameReader = null;
|
|
|
+ // 身体的数组
|
|
|
+ private Body[] bodies = null;
|
|
|
+ // 骨骼的定义
|
|
|
+ private List<Tuple<JointType, JointType>> bones;
|
|
|
+ // 显示宽度,高度(深度空间)
|
|
|
+ private int displayWidth, displayHeight;
|
|
|
+ // 要显示的当前状态文本
|
|
|
+ private string statusText = null;
|
|
|
+
|
|
|
+ // INotifyPropertyChangedPropertyChanged 事件允许窗口控件绑定到可更改的数据
|
|
|
+ public event PropertyChangedEventHandler PropertyChanged;
|
|
|
+
|
|
|
+ public string StatusText
|
|
|
+ {
|
|
|
+ get
|
|
|
+ {
|
|
|
+ return this.statusText;
|
|
|
+ }
|
|
|
+
|
|
|
+ set
|
|
|
+ {
|
|
|
+ if (this.statusText != value)
|
|
|
+ {
|
|
|
+ this.statusText = value;
|
|
|
+
|
|
|
+ // 通知任何绑定元素文本已更改
|
|
|
+ if (this.PropertyChanged != null)
|
|
|
+ {
|
|
|
+ this.PropertyChanged(this, new PropertyChangedEventArgs("StatusText"));
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ public MainWindow()
|
|
|
+ {
|
|
|
+ // 目前支持一个传感器
|
|
|
+ this.kinectSensor = KinectSensor.GetDefault();
|
|
|
+
|
|
|
+ // 获取坐标映射器
|
|
|
+ this.coordinateMapper = this.kinectSensor.CoordinateMapper;
|
|
|
+
|
|
|
+ // 获取深度(显示)范围
|
|
|
+ FrameDescription frameDescription = this.kinectSensor.DepthFrameSource.FrameDescription;
|
|
|
+
|
|
|
+ // 得到关节空间的大小
|
|
|
+ this.displayWidth = frameDescription.Width;
|
|
|
+ this.displayHeight = frameDescription.Height;
|
|
|
+
|
|
|
+ // 打开渲染器的身体框架
|
|
|
+ this.bodyFrameReader = this.kinectSensor.BodyFrameSource.OpenReader();
|
|
|
+
|
|
|
+ // 骨骼定义为两个关节之间的线
|
|
|
+ this.bones = new List<Tuple<JointType, JointType>>();
|
|
|
+
|
|
|
+ // 躯干
|
|
|
+ this.bones.Add(new Tuple<JointType, JointType>(JointType.Head, JointType.Neck));
|
|
|
+ this.bones.Add(new Tuple<JointType, JointType>(JointType.Neck, JointType.SpineShoulder));
|
|
|
+ this.bones.Add(new Tuple<JointType, JointType>(JointType.SpineShoulder, JointType.SpineMid));
|
|
|
+ this.bones.Add(new Tuple<JointType, JointType>(JointType.SpineMid, JointType.SpineBase));
|
|
|
+ this.bones.Add(new Tuple<JointType, JointType>(JointType.SpineShoulder, JointType.ShoulderRight));
|
|
|
+ this.bones.Add(new Tuple<JointType, JointType>(JointType.SpineShoulder, JointType.ShoulderLeft));
|
|
|
+ this.bones.Add(new Tuple<JointType, JointType>(JointType.SpineBase, JointType.HipRight));
|
|
|
+ this.bones.Add(new Tuple<JointType, JointType>(JointType.SpineBase, JointType.HipLeft));
|
|
|
+
|
|
|
+ // 右臂
|
|
|
+ this.bones.Add(new Tuple<JointType, JointType>(JointType.ShoulderRight, JointType.ElbowRight));
|
|
|
+ this.bones.Add(new Tuple<JointType, JointType>(JointType.ElbowRight, JointType.WristRight));
|
|
|
+ this.bones.Add(new Tuple<JointType, JointType>(JointType.WristRight, JointType.HandRight));
|
|
|
+ this.bones.Add(new Tuple<JointType, JointType>(JointType.HandRight, JointType.HandTipRight));
|
|
|
+ this.bones.Add(new Tuple<JointType, JointType>(JointType.WristRight, JointType.ThumbRight));
|
|
|
+
|
|
|
+ // 左臂
|
|
|
+ this.bones.Add(new Tuple<JointType, JointType>(JointType.ShoulderLeft, JointType.ElbowLeft));
|
|
|
+ this.bones.Add(new Tuple<JointType, JointType>(JointType.ElbowLeft, JointType.WristLeft));
|
|
|
+ this.bones.Add(new Tuple<JointType, JointType>(JointType.WristLeft, JointType.HandLeft));
|
|
|
+ this.bones.Add(new Tuple<JointType, JointType>(JointType.HandLeft, JointType.HandTipLeft));
|
|
|
+ this.bones.Add(new Tuple<JointType, JointType>(JointType.WristLeft, JointType.ThumbLeft));
|
|
|
+
|
|
|
+ // 右腿
|
|
|
+ this.bones.Add(new Tuple<JointType, JointType>(JointType.HipRight, JointType.KneeRight));
|
|
|
+ this.bones.Add(new Tuple<JointType, JointType>(JointType.KneeRight, JointType.AnkleRight));
|
|
|
+ this.bones.Add(new Tuple<JointType, JointType>(JointType.AnkleRight, JointType.FootRight));
|
|
|
+
|
|
|
+ // 左腿
|
|
|
+ this.bones.Add(new Tuple<JointType, JointType>(JointType.HipLeft, JointType.KneeLeft));
|
|
|
+ this.bones.Add(new Tuple<JointType, JointType>(JointType.KneeLeft, JointType.AnkleLeft));
|
|
|
+ this.bones.Add(new Tuple<JointType, JointType>(JointType.AnkleLeft, JointType.FootLeft));
|
|
|
+
|
|
|
+ // 设置 IsAvailableChanged 事件通知程序
|
|
|
+ this.kinectSensor.IsAvailableChanged += this.Sensor_IsAvailableChanged;
|
|
|
+
|
|
|
+ // 打开传感器
|
|
|
+ this.kinectSensor.Open();
|
|
|
+
|
|
|
+ // 设置状态文本
|
|
|
+ this.StatusText = this.kinectSensor.IsAvailable ? Properties.Resources.RunningStatusText : Properties.Resources.NoSensorStatusText;
|
|
|
+
|
|
|
+ // 在这个简单的例子中使用window对象作为视图模型
|
|
|
+ this.DataContext = this;
|
|
|
+
|
|
|
+ // 初始化窗口的组件(控件)
|
|
|
+ this.InitializeComponent();
|
|
|
+ }
|
|
|
+
|
|
|
+ private void Window_Loaded(object sender, RoutedEventArgs e)
|
|
|
+ {
|
|
|
+ if (this.bodyFrameReader != null)
|
|
|
+ {
|
|
|
+ this.bodyFrameReader.FrameArrived += this.Reader_FrameArrived;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ private void Window_Closing(object sender, CancelEventArgs e)
|
|
|
+ {
|
|
|
+ if (this.bodyFrameReader != null)
|
|
|
+ {
|
|
|
+ this.bodyFrameReader.Dispose();
|
|
|
+ this.bodyFrameReader = null;
|
|
|
+ }
|
|
|
+
|
|
|
+ if (this.kinectSensor != null)
|
|
|
+ {
|
|
|
+ this.kinectSensor.Close();
|
|
|
+ this.kinectSensor = null;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ private void Reader_FrameArrived(object sender, BodyFrameArrivedEventArgs e)
|
|
|
+ {
|
|
|
+ bool dataReceived = false;
|
|
|
+ using (BodyFrame bodyFrame = e.FrameReference.AcquireFrame())
|
|
|
+ {
|
|
|
+ if (bodyFrame != null)
|
|
|
+ {
|
|
|
+ if (this.bodies == null)
|
|
|
+ {
|
|
|
+ this.bodies = new Body[bodyFrame.BodyCount];
|
|
|
+ }
|
|
|
+ // 第一次调用GetAndRefreshBodyData时,Kinect将在数组中分配每个Body。只要这些主体对象没有被释放并且在数组中没有设置为null,那么这些主体对象将被重用。
|
|
|
+ bodyFrame.GetAndRefreshBodyData(this.bodies);
|
|
|
+ dataReceived = true;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ if (dataReceived)
|
|
|
+ {
|
|
|
+ foreach (Body body in bodies)
|
|
|
+ {
|
|
|
+ if (body.IsTracked)
|
|
|
+ {
|
|
|
+ status.Content = "追踪到Body.";
|
|
|
+ IReadOnlyDictionary<JointType, Joint> joints = body.Joints;
|
|
|
+
|
|
|
+ Joint jointHead = joints[JointType.Head], jointHandRight = joints[JointType.HandRight];
|
|
|
+ CameraSpacePoint positionHead = jointHead.Position, positionHandRight = jointHandRight.Position;
|
|
|
+ if (jointHead.TrackingState == TrackingState.Tracked && jointHandRight.TrackingState == TrackingState.Tracked)
|
|
|
+ {
|
|
|
+ Console.WriteLine("X = " + positionHead.X + ", Y = " + positionHead.Y + ", Z = " + positionHead.Z);
|
|
|
+ Console.WriteLine("X = " + positionHandRight.X + ", Y = " + positionHandRight.Y + ", Z = " + positionHandRight.Z);
|
|
|
+ }
|
|
|
+
|
|
|
+ // 将关节点转换为深度(显示)空间
|
|
|
+ //Dictionary<JointType, Point> jointPoints = new Dictionary<JointType, Point>();
|
|
|
+ //foreach (JointType jointType in joints.Keys)
|
|
|
+ //{
|
|
|
+ // DepthSpacePoint depthSpacePoint = this.coordinateMapper.MapCameraPointToDepthSpace(positionHead);
|
|
|
+ // jointPoints[jointType] = new Point(depthSpacePoint.X, depthSpacePoint.Y);
|
|
|
+ //}
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+ status.Content = "无";
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ private void Sensor_IsAvailableChanged(object sender, IsAvailableChangedEventArgs e)
|
|
|
+ {
|
|
|
+ // 如果失败,设置状态文本
|
|
|
+ this.StatusText = this.kinectSensor.IsAvailable ? Properties.Resources.RunningStatusText : Properties.Resources.SensorNotAvailableStatusText;
|
|
|
+ }
|
|
|
+ }
|
|
|
+}
|