|
@@ -6,10 +6,12 @@
|
|
|
using System.Windows;
|
|
|
using System.Windows.Media;
|
|
|
using Microsoft.Kinect;
|
|
|
-
|
|
|
- /// <summary>
|
|
|
- /// MainWindow.xaml 的交互逻辑
|
|
|
- /// </summary>
|
|
|
+ using uPLibrary.Networking.M2Mqtt;
|
|
|
+ using System.Net;
|
|
|
+ using uPLibrary.Networking.M2Mqtt.Messages;
|
|
|
+ using System.Text;/// <summary>
|
|
|
+ /// MainWindow.xaml 的交互逻辑
|
|
|
+ /// </summary>
|
|
|
public partial class MainWindow : Window, INotifyPropertyChanged
|
|
|
{
|
|
|
// 活动的 Kinect 传感器
|
|
@@ -26,6 +28,14 @@
|
|
|
private int displayWidth, displayHeight;
|
|
|
// 要显示的当前状态文本
|
|
|
private string statusText = null;
|
|
|
+ // 阈值(1/2框)(单位:米)
|
|
|
+ private float THRESHOLD = 0.15f;
|
|
|
+ // 当前状态
|
|
|
+ private int gesture = -1;
|
|
|
+
|
|
|
+ private static string MQTT_BROKER_ADDRESS = "123.207.151.92";
|
|
|
+ //创建客户端实例
|
|
|
+ MqttClient client = new MqttClient(IPAddress.Parse(MQTT_BROKER_ADDRESS), 1600, false, null, null, MqttSslProtocols.None); //主机为IP时
|
|
|
|
|
|
// INotifyPropertyChangedPropertyChanged 事件允许窗口控件绑定到可更改的数据
|
|
|
public event PropertyChangedEventHandler PropertyChanged;
|
|
@@ -34,19 +44,19 @@
|
|
|
{
|
|
|
get
|
|
|
{
|
|
|
- return this.statusText;
|
|
|
+ return statusText;
|
|
|
}
|
|
|
|
|
|
set
|
|
|
{
|
|
|
- if (this.statusText != value)
|
|
|
+ if (statusText != value)
|
|
|
{
|
|
|
- this.statusText = value;
|
|
|
+ statusText = value;
|
|
|
|
|
|
// 通知任何绑定元素文本已更改
|
|
|
- if (this.PropertyChanged != null)
|
|
|
+ if (PropertyChanged != null)
|
|
|
{
|
|
|
- this.PropertyChanged(this, new PropertyChangedEventArgs("StatusText"));
|
|
|
+ PropertyChanged(this, new PropertyChangedEventArgs("StatusText"));
|
|
|
}
|
|
|
}
|
|
|
}
|
|
@@ -55,95 +65,100 @@
|
|
|
public MainWindow()
|
|
|
{
|
|
|
// 目前支持一个传感器
|
|
|
- this.kinectSensor = KinectSensor.GetDefault();
|
|
|
-
|
|
|
+ kinectSensor = KinectSensor.GetDefault();
|
|
|
// 获取坐标映射器
|
|
|
- this.coordinateMapper = this.kinectSensor.CoordinateMapper;
|
|
|
-
|
|
|
+ coordinateMapper = kinectSensor.CoordinateMapper;
|
|
|
// 获取深度(显示)范围
|
|
|
- FrameDescription frameDescription = this.kinectSensor.DepthFrameSource.FrameDescription;
|
|
|
-
|
|
|
+ FrameDescription frameDescription = kinectSensor.DepthFrameSource.FrameDescription;
|
|
|
// 得到关节空间的大小
|
|
|
- this.displayWidth = frameDescription.Width;
|
|
|
- this.displayHeight = frameDescription.Height;
|
|
|
-
|
|
|
+ displayWidth = frameDescription.Width;
|
|
|
+ displayHeight = frameDescription.Height;
|
|
|
// 打开渲染器的身体框架
|
|
|
- this.bodyFrameReader = this.kinectSensor.BodyFrameSource.OpenReader();
|
|
|
-
|
|
|
+ bodyFrameReader = kinectSensor.BodyFrameSource.OpenReader();
|
|
|
// 骨骼定义为两个关节之间的线
|
|
|
- this.bones = new List<Tuple<JointType, JointType>>();
|
|
|
-
|
|
|
+ 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));
|
|
|
-
|
|
|
+ bones.Add(new Tuple<JointType, JointType>(JointType.Head, JointType.Neck));
|
|
|
+ bones.Add(new Tuple<JointType, JointType>(JointType.Neck, JointType.SpineShoulder));
|
|
|
+ bones.Add(new Tuple<JointType, JointType>(JointType.SpineShoulder, JointType.SpineMid));
|
|
|
+ bones.Add(new Tuple<JointType, JointType>(JointType.SpineMid, JointType.SpineBase));
|
|
|
+ bones.Add(new Tuple<JointType, JointType>(JointType.SpineShoulder, JointType.ShoulderRight));
|
|
|
+ bones.Add(new Tuple<JointType, JointType>(JointType.SpineShoulder, JointType.ShoulderLeft));
|
|
|
+ bones.Add(new Tuple<JointType, JointType>(JointType.SpineBase, JointType.HipRight));
|
|
|
+ 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));
|
|
|
-
|
|
|
+ bones.Add(new Tuple<JointType, JointType>(JointType.ShoulderRight, JointType.ElbowRight));
|
|
|
+ bones.Add(new Tuple<JointType, JointType>(JointType.ElbowRight, JointType.WristRight));
|
|
|
+ bones.Add(new Tuple<JointType, JointType>(JointType.WristRight, JointType.HandRight));
|
|
|
+ bones.Add(new Tuple<JointType, JointType>(JointType.HandRight, JointType.HandTipRight));
|
|
|
+ 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));
|
|
|
-
|
|
|
+ bones.Add(new Tuple<JointType, JointType>(JointType.ShoulderLeft, JointType.ElbowLeft));
|
|
|
+ bones.Add(new Tuple<JointType, JointType>(JointType.ElbowLeft, JointType.WristLeft));
|
|
|
+ bones.Add(new Tuple<JointType, JointType>(JointType.WristLeft, JointType.HandLeft));
|
|
|
+ bones.Add(new Tuple<JointType, JointType>(JointType.HandLeft, JointType.HandTipLeft));
|
|
|
+ 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));
|
|
|
-
|
|
|
+ bones.Add(new Tuple<JointType, JointType>(JointType.HipRight, JointType.KneeRight));
|
|
|
+ bones.Add(new Tuple<JointType, JointType>(JointType.KneeRight, JointType.AnkleRight));
|
|
|
+ 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));
|
|
|
-
|
|
|
+ bones.Add(new Tuple<JointType, JointType>(JointType.HipLeft, JointType.KneeLeft));
|
|
|
+ bones.Add(new Tuple<JointType, JointType>(JointType.KneeLeft, JointType.AnkleLeft));
|
|
|
+ bones.Add(new Tuple<JointType, JointType>(JointType.AnkleLeft, JointType.FootLeft));
|
|
|
// 设置 IsAvailableChanged 事件通知程序
|
|
|
- this.kinectSensor.IsAvailableChanged += this.Sensor_IsAvailableChanged;
|
|
|
-
|
|
|
+ kinectSensor.IsAvailableChanged += Sensor_IsAvailableChanged;
|
|
|
// 打开传感器
|
|
|
- this.kinectSensor.Open();
|
|
|
-
|
|
|
+ kinectSensor.Open();
|
|
|
// 设置状态文本
|
|
|
- this.StatusText = this.kinectSensor.IsAvailable ? Properties.Resources.RunningStatusText : Properties.Resources.NoSensorStatusText;
|
|
|
-
|
|
|
+ StatusText = kinectSensor.IsAvailable ? Properties.Resources.RunningStatusText : Properties.Resources.NoSensorStatusText;
|
|
|
// 在这个简单的例子中使用window对象作为视图模型
|
|
|
- this.DataContext = this;
|
|
|
-
|
|
|
+ DataContext = this;
|
|
|
// 初始化窗口的组件(控件)
|
|
|
- this.InitializeComponent();
|
|
|
+ InitializeComponent();
|
|
|
}
|
|
|
|
|
|
private void Window_Loaded(object sender, RoutedEventArgs e)
|
|
|
{
|
|
|
- if (this.bodyFrameReader != null)
|
|
|
+ if (bodyFrameReader != null)
|
|
|
{
|
|
|
- this.bodyFrameReader.FrameArrived += this.Reader_FrameArrived;
|
|
|
+ bodyFrameReader.FrameArrived += Reader_FrameArrived;
|
|
|
}
|
|
|
+ // 注册消息接收处理事件,还可以注册消息订阅成功、取消订阅成功、与服务器断开等事件处理函数
|
|
|
+ client.MqttMsgPublishReceived += client_MqttMsgPublishReceived;
|
|
|
+ //生成客户端 ID 并连接服务器
|
|
|
+ string clientId = Guid.NewGuid().ToString();
|
|
|
+ client.Connect(clientId, "yumin", "minbb.cn");
|
|
|
+ // 订阅主题"wifi/car" 消息质量为 2
|
|
|
+ client.Subscribe(new string[] { "wifi/car" }, new byte[] { MqttMsgBase.QOS_LEVEL_EXACTLY_ONCE });
|
|
|
+ // 发布消息到主题 "wifi/car" 消息质量为 2,不保留
|
|
|
+ client.Publish("wifi/car", Encoding.UTF8.GetBytes("I'm C#"), MqttMsgBase.QOS_LEVEL_EXACTLY_ONCE, false);
|
|
|
}
|
|
|
|
|
|
private void Window_Closing(object sender, CancelEventArgs e)
|
|
|
{
|
|
|
- if (this.bodyFrameReader != null)
|
|
|
+ if (bodyFrameReader != null)
|
|
|
{
|
|
|
- this.bodyFrameReader.Dispose();
|
|
|
- this.bodyFrameReader = null;
|
|
|
+ bodyFrameReader.Dispose();
|
|
|
+ bodyFrameReader = null;
|
|
|
}
|
|
|
|
|
|
- if (this.kinectSensor != null)
|
|
|
+ if (kinectSensor != null)
|
|
|
{
|
|
|
- this.kinectSensor.Close();
|
|
|
- this.kinectSensor = null;
|
|
|
+ kinectSensor.Close();
|
|
|
+ kinectSensor = null;
|
|
|
}
|
|
|
+ if (client != null)
|
|
|
+ {
|
|
|
+ client.Disconnect();
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ void client_MqttMsgPublishReceived(object sender, MqttMsgPublishEventArgs e)
|
|
|
+ {
|
|
|
+ //处理接收到的消息
|
|
|
+ string msg = System.Text.Encoding.Default.GetString(e.Message);
|
|
|
+ Console.WriteLine("收到消息 = " + msg + "\r\n");
|
|
|
}
|
|
|
|
|
|
private void Reader_FrameArrived(object sender, BodyFrameArrivedEventArgs e)
|
|
@@ -153,12 +168,12 @@
|
|
|
{
|
|
|
if (bodyFrame != null)
|
|
|
{
|
|
|
- if (this.bodies == null)
|
|
|
+ if (bodies == null)
|
|
|
{
|
|
|
- this.bodies = new Body[bodyFrame.BodyCount];
|
|
|
+ bodies = new Body[bodyFrame.BodyCount];
|
|
|
}
|
|
|
// 第一次调用GetAndRefreshBodyData时,Kinect将在数组中分配每个Body。只要这些主体对象没有被释放并且在数组中没有设置为null,那么这些主体对象将被重用。
|
|
|
- bodyFrame.GetAndRefreshBodyData(this.bodies);
|
|
|
+ bodyFrame.GetAndRefreshBodyData(bodies);
|
|
|
dataReceived = true;
|
|
|
}
|
|
|
}
|
|
@@ -172,19 +187,105 @@
|
|
|
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)
|
|
|
+ Joint jointHandRight = joints[JointType.HandRight], jointShoulderRight = joints[JointType.ShoulderRight];
|
|
|
+ CameraSpacePoint positionHandRight = jointHandRight.Position, positionShoulderRight = jointShoulderRight.Position;
|
|
|
+ if (jointHandRight.TrackingState == TrackingState.Tracked &&
|
|
|
+ jointShoulderRight.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);
|
|
|
+ float xHandRight = positionHandRight.X, yHandRight = positionHandRight.Y;
|
|
|
+ float xShoulderRight = positionShoulderRight.X, yShoulderRight = positionShoulderRight.Y;
|
|
|
+ // 右手位置判定(基于右肩为原点且无深度检测)
|
|
|
+ if (xHandRight >= 2 * xShoulderRight - THRESHOLD && xHandRight <= 2 * xShoulderRight + THRESHOLD &&
|
|
|
+ yHandRight >= 2 * yShoulderRight - THRESHOLD && yHandRight <= 2 * yShoulderRight + THRESHOLD)
|
|
|
+ {
|
|
|
+ // 中 - 5
|
|
|
+ if(gesture != 5)
|
|
|
+ {
|
|
|
+ gesture = 5;
|
|
|
+ Console.WriteLine("中");
|
|
|
+ }
|
|
|
+ }
|
|
|
+ else if(xHandRight > 2 * xShoulderRight - THRESHOLD && xHandRight < 2 * xShoulderRight + THRESHOLD && yHandRight > 2 * yShoulderRight + THRESHOLD)
|
|
|
+ {
|
|
|
+ // 上 - 2
|
|
|
+ if (gesture != 2)
|
|
|
+ {
|
|
|
+ gesture = 2;
|
|
|
+ Console.WriteLine("上");
|
|
|
+ }
|
|
|
+ }
|
|
|
+ else if (xHandRight > 2 * xShoulderRight - THRESHOLD && xHandRight < 2 * xShoulderRight + THRESHOLD && yHandRight < 2 * yShoulderRight + THRESHOLD)
|
|
|
+ {
|
|
|
+ // 下 - 8
|
|
|
+ if (gesture != 8)
|
|
|
+ {
|
|
|
+ gesture = 8;
|
|
|
+ Console.WriteLine("下");
|
|
|
+ }
|
|
|
+ }
|
|
|
+ else if (xHandRight < 2 * xShoulderRight - THRESHOLD && yHandRight > 2 * yShoulderRight - THRESHOLD && yHandRight < 2 * yShoulderRight + THRESHOLD)
|
|
|
+ {
|
|
|
+ // 左 - 4
|
|
|
+ if (gesture != 4)
|
|
|
+ {
|
|
|
+ gesture = 4;
|
|
|
+ Console.WriteLine("左");
|
|
|
+ }
|
|
|
+ }
|
|
|
+ else if (xHandRight > 2 * xShoulderRight + THRESHOLD && yHandRight > 2 * yShoulderRight - THRESHOLD && yHandRight < 2 * yShoulderRight + THRESHOLD)
|
|
|
+ {
|
|
|
+ // 右 - 6
|
|
|
+ if (gesture != 6)
|
|
|
+ {
|
|
|
+ gesture = 6;
|
|
|
+ Console.WriteLine("右");
|
|
|
+ }
|
|
|
+ }
|
|
|
+ else if (xHandRight > 2 * xShoulderRight + THRESHOLD && yHandRight > 2 * yShoulderRight + THRESHOLD)
|
|
|
+ {
|
|
|
+ // 右上 - 3
|
|
|
+ if (gesture != 3)
|
|
|
+ {
|
|
|
+ gesture = 3;
|
|
|
+ Console.WriteLine("右上");
|
|
|
+ }
|
|
|
+ }
|
|
|
+ else if (xHandRight > 2 * xShoulderRight + THRESHOLD && yHandRight < 2 * yShoulderRight - THRESHOLD)
|
|
|
+ {
|
|
|
+ // 右下 - 9
|
|
|
+ if (gesture != 9)
|
|
|
+ {
|
|
|
+ gesture = 9;
|
|
|
+ Console.WriteLine("右下");
|
|
|
+ }
|
|
|
+ }
|
|
|
+ else if (xHandRight < 2 * xShoulderRight - THRESHOLD && yHandRight > 2 * yShoulderRight + THRESHOLD)
|
|
|
+ {
|
|
|
+ // 左上 - 1
|
|
|
+ if (gesture != 1)
|
|
|
+ {
|
|
|
+ gesture = 1;
|
|
|
+ Console.WriteLine("左上");
|
|
|
+ }
|
|
|
+ }
|
|
|
+ else if (xHandRight < 2 * xShoulderRight - THRESHOLD && yHandRight < 2 * yShoulderRight - THRESHOLD)
|
|
|
+ {
|
|
|
+ // 左下 - 7
|
|
|
+ if (gesture != 7)
|
|
|
+ {
|
|
|
+ gesture = 7;
|
|
|
+ Console.WriteLine("左下");
|
|
|
+ }
|
|
|
+ }
|
|
|
+ //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);
|
|
|
+ // DepthSpacePoint depthSpacePoint = coordinateMapper.MapCameraPointToDepthSpace(positionHead);
|
|
|
// jointPoints[jointType] = new Point(depthSpacePoint.X, depthSpacePoint.Y);
|
|
|
//}
|
|
|
}
|
|
@@ -199,7 +300,7 @@
|
|
|
private void Sensor_IsAvailableChanged(object sender, IsAvailableChangedEventArgs e)
|
|
|
{
|
|
|
// 如果失败,设置状态文本
|
|
|
- this.StatusText = this.kinectSensor.IsAvailable ? Properties.Resources.RunningStatusText : Properties.Resources.SensorNotAvailableStatusText;
|
|
|
+ StatusText = kinectSensor.IsAvailable ? Properties.Resources.RunningStatusText : Properties.Resources.SensorNotAvailableStatusText;
|
|
|
}
|
|
|
}
|
|
|
}
|