forked from MaximilianLackaw/KinectBand
-
Notifications
You must be signed in to change notification settings - Fork 0
/
MainWindow.xaml.cs
251 lines (214 loc) · 10.4 KB
/
MainWindow.xaml.cs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
//---------------------------------------------------------------------------------------------------
// <copyright file="MainWindow.xaml.cs" company="Microsoft">
// Copyright (c) Microsoft Corporation. All rights reserved.
// </copyright>
//
// <Description>
// This program tracks up to 6 people simultaneously.
// If a person is tracked, the associated gesture detector will determine if that person is seated or not.
// If any of the 6 positions are not in use, the corresponding gesture detector(s) will be paused
// and the 'Not Tracked' image will be displayed in the UI.
// </Description>
//----------------------------------------------------------------------------------------------------
namespace Microsoft.Samples.Kinect.DiscreteGestureBasics
{
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Windows;
using System.Windows.Controls;
using Microsoft.Kinect;
using Microsoft.Kinect.VisualGestureBuilder;
/// <summary>
/// Interaction logic for the MainWindow
/// </summary>
public partial class MainWindow : Window, INotifyPropertyChanged
{
/// <summary> Active Kinect sensor </summary>
private KinectSensor kinectSensor = null;
/// <summary> Array for the bodies (Kinect will track up to 6 people simultaneously) </summary>
private Body[] bodies = null;
/// <summary> Reader for body frames </summary>
private BodyFrameReader bodyFrameReader = null;
/// <summary> Current status text to display </summary>
private string statusText = null;
/// <summary> KinectBodyView object which handles drawing the Kinect bodies to a View box in the UI </summary>
private KinectBodyView kinectBodyView = null;
/// <summary> List of gesture detectors, there will be one detector created for each potential body (max of 6) </summary>
private List<GestureDetector> gestureDetectorList = null;
/// <summary>
/// Initializes a new instance of the MainWindow class
/// </summary>
public MainWindow()
{
// only one sensor is currently supported
this.kinectSensor = KinectSensor.GetDefault();
// set IsAvailableChanged event notifier
this.kinectSensor.IsAvailableChanged += this.Sensor_IsAvailableChanged;
// open the sensor
this.kinectSensor.Open();
// set the status text
this.StatusText = this.kinectSensor.IsAvailable ? Properties.Resources.RunningStatusText
: Properties.Resources.NoSensorStatusText;
// open the reader for the body frames
this.bodyFrameReader = this.kinectSensor.BodyFrameSource.OpenReader();
// set the BodyFramedArrived event notifier
this.bodyFrameReader.FrameArrived += this.Reader_BodyFrameArrived;
// initialize the BodyViewer object for displaying tracked bodies in the UI
this.kinectBodyView = new KinectBodyView(this.kinectSensor);
// initialize the gesture detection objects for our gestures
this.gestureDetectorList = new List<GestureDetector>();
// initialize the MainWindow
this.InitializeComponent();
// set our data context objects for display in UI
this.DataContext = this;
this.kinectBodyViewbox.DataContext = this.kinectBodyView;
// create a gesture detector for each body (6 bodies => 6 detectors) and create content controls to display results in the UI
int col0Row = 0;
int col1Row = 0;
int maxBodies = this.kinectSensor.BodyFrameSource.BodyCount;
for (int i = 0; i < maxBodies; ++i)
{
GestureResultView result = new GestureResultView(i, false, false, 0.0f);
GestureDetector detector = new GestureDetector(this.kinectSensor, result);
this.gestureDetectorList.Add(detector);
// split gesture results across the first two columns of the content grid
ContentControl contentControl = new ContentControl();
contentControl.Content = this.gestureDetectorList[i].GestureResultView;
if (i % 2 == 0)
{
// Gesture results for bodies: 0, 2, 4
Grid.SetColumn(contentControl, 0);
Grid.SetRow(contentControl, col0Row);
++col0Row;
}
else
{
// Gesture results for bodies: 1, 3, 5
Grid.SetColumn(contentControl, 1);
Grid.SetRow(contentControl, col1Row);
++col1Row;
}
this.contentGrid.Children.Add(contentControl);
}
}
/// <summary>
/// INotifyPropertyChangedPropertyChanged event to allow window controls to bind to changeable data
/// </summary>
public event PropertyChangedEventHandler PropertyChanged;
/// <summary>
/// Gets or sets the current status text to display
/// </summary>
public string StatusText
{
get
{
return this.statusText;
}
set
{
if (this.statusText != value)
{
this.statusText = value;
// notify any bound elements that the text has changed
if (this.PropertyChanged != null)
{
this.PropertyChanged(this, new PropertyChangedEventArgs("StatusText"));
}
}
}
}
/// <summary>
/// Execute shutdown tasks
/// </summary>
/// <param name="sender">object sending the event</param>
/// <param name="e">event arguments</param>
private void MainWindow_Closing(object sender, CancelEventArgs e)
{
if (this.bodyFrameReader != null)
{
// BodyFrameReader is IDisposable
this.bodyFrameReader.FrameArrived -= this.Reader_BodyFrameArrived;
this.bodyFrameReader.Dispose();
this.bodyFrameReader = null;
}
if (this.gestureDetectorList != null)
{
// The GestureDetector contains disposable members (VisualGestureBuilderFrameSource and VisualGestureBuilderFrameReader)
foreach (GestureDetector detector in this.gestureDetectorList)
{
detector.Dispose();
}
this.gestureDetectorList.Clear();
this.gestureDetectorList = null;
}
if (this.kinectSensor != null)
{
this.kinectSensor.IsAvailableChanged -= this.Sensor_IsAvailableChanged;
this.kinectSensor.Close();
this.kinectSensor = null;
}
}
/// <summary>
/// Handles the event when the sensor becomes unavailable (e.g. paused, closed, unplugged).
/// </summary>
/// <param name="sender">object sending the event</param>
/// <param name="e">event arguments</param>
private void Sensor_IsAvailableChanged(object sender, IsAvailableChangedEventArgs e)
{
// on failure, set the status text
this.StatusText = this.kinectSensor.IsAvailable ? Properties.Resources.RunningStatusText
: Properties.Resources.SensorNotAvailableStatusText;
}
/// <summary>
/// Handles the body frame data arriving from the sensor and updates the associated gesture detector object for each body
/// </summary>
/// <param name="sender">object sending the event</param>
/// <param name="e">event arguments</param>
private void Reader_BodyFrameArrived(object sender, BodyFrameArrivedEventArgs e)
{
bool dataReceived = false;
using (BodyFrame bodyFrame = e.FrameReference.AcquireFrame())
{
if (bodyFrame != null)
{
if (this.bodies == null)
{
// creates an array of 6 bodies, which is the max number of bodies that Kinect can track simultaneously
this.bodies = new Body[bodyFrame.BodyCount];
}
// The first time GetAndRefreshBodyData is called, Kinect will allocate each Body in the array.
// As long as those body objects are not disposed and not set to null in the array,
// those body objects will be re-used.
bodyFrame.GetAndRefreshBodyData(this.bodies);
dataReceived = true;
}
}
if (dataReceived)
{
// visualize the new body data
this.kinectBodyView.UpdateBodyFrame(this.bodies);
// we may have lost/acquired bodies, so update the corresponding gesture detectors
if (this.bodies != null)
{
// loop through all bodies to see if any of the gesture detectors need to be updated
int maxBodies = this.kinectSensor.BodyFrameSource.BodyCount;
for (int i = 0; i < maxBodies; ++i)
{
Body body = this.bodies[i];
ulong trackingId = body.TrackingId;
// if the current body TrackingId changed, update the corresponding gesture detector with the new value
if (trackingId != this.gestureDetectorList[i].TrackingId)
{
this.gestureDetectorList[i].TrackingId = trackingId;
// if the current body is tracked, unpause its detector to get VisualGestureBuilderFrameArrived events
// if the current body is not tracked, pause its detector so we don't waste resources trying to get invalid gesture results
this.gestureDetectorList[i].IsPaused = trackingId == 0;
}
}
}
}
}
}
}