15
15
using Windows . UI . Xaml . Navigation ;
16
16
using WindowsPreview . Kinect ;
17
17
using System . ComponentModel ;
18
+ using Windows . Storage . Streams ;
19
+ using System . Runtime . InteropServices ;
20
+ using System . Diagnostics ;
18
21
19
22
namespace Kinect2Sample
20
23
{
21
24
public enum DisplayFrameType
22
25
{
23
26
Infrared ,
24
27
Color ,
25
- Depth
28
+ Depth ,
29
+ BodyMask
26
30
}
27
31
28
32
public sealed partial class MainPage : Page , INotifyPropertyChanged
@@ -76,6 +80,7 @@ public sealed partial class MainPage : Page, INotifyPropertyChanged
76
80
private FrameDescription currentFrameDescription ;
77
81
private DisplayFrameType currentDisplayFrameType ;
78
82
private MultiSourceFrameReader multiSourceFrameReader = null ;
83
+ private CoordinateMapper coordinateMapper = null ;
79
84
80
85
//Infrared Frame
81
86
private ushort [ ] infraredFrameData = null ;
@@ -85,6 +90,9 @@ public sealed partial class MainPage : Page, INotifyPropertyChanged
85
90
private ushort [ ] depthFrameData = null ;
86
91
private byte [ ] depthPixels = null ;
87
92
93
+ //BodyMask Frames
94
+ private DepthSpacePoint [ ] colorMappedToDepthPoints = null ;
95
+
88
96
public event PropertyChangedEventHandler PropertyChanged ;
89
97
public string StatusText
90
98
{
@@ -125,7 +133,9 @@ public MainPage()
125
133
126
134
SetupCurrentDisplay ( DEFAULT_DISPLAYFRAMETYPE ) ;
127
135
128
- this . multiSourceFrameReader = this . kinectSensor . OpenMultiSourceFrameReader ( FrameSourceTypes . Infrared | FrameSourceTypes . Color | FrameSourceTypes . Depth ) ;
136
+ this . coordinateMapper = this . kinectSensor . CoordinateMapper ;
137
+
138
+ this . multiSourceFrameReader = this . kinectSensor . OpenMultiSourceFrameReader ( FrameSourceTypes . Infrared | FrameSourceTypes . Color | FrameSourceTypes . Depth | FrameSourceTypes . BodyIndex ) ;
129
139
130
140
this . multiSourceFrameReader . MultiSourceFrameArrived += this . Reader_MultiSourceFrameArrived ;
131
141
@@ -144,6 +154,8 @@ public MainPage()
144
154
private void SetupCurrentDisplay ( DisplayFrameType newDisplayFrameType )
145
155
{
146
156
currentDisplayFrameType = newDisplayFrameType ;
157
+ // Frames used by more than one type are declared outside the switch
158
+ FrameDescription colorFrameDescription = null ;
147
159
switch ( currentDisplayFrameType )
148
160
{
149
161
case DisplayFrameType . Infrared :
@@ -156,7 +168,7 @@ private void SetupCurrentDisplay(DisplayFrameType newDisplayFrameType)
156
168
break ;
157
169
158
170
case DisplayFrameType . Color :
159
- FrameDescription colorFrameDescription = this . kinectSensor . ColorFrameSource . FrameDescription ;
171
+ colorFrameDescription = this . kinectSensor . ColorFrameSource . FrameDescription ;
160
172
this . CurrentFrameDescription = colorFrameDescription ;
161
173
// create the bitmap to display
162
174
this . bitmap = new WriteableBitmap ( colorFrameDescription . Width , colorFrameDescription . Height ) ;
@@ -171,6 +183,13 @@ private void SetupCurrentDisplay(DisplayFrameType newDisplayFrameType)
171
183
this . bitmap = new WriteableBitmap ( depthFrameDescription . Width , depthFrameDescription . Height ) ;
172
184
break ;
173
185
186
+ case DisplayFrameType . BodyMask :
187
+ colorFrameDescription = this . kinectSensor . ColorFrameSource . FrameDescription ;
188
+ this . CurrentFrameDescription = colorFrameDescription ;
189
+ // allocate space to put the pixels being received and converted
190
+ this . colorMappedToDepthPoints = new DepthSpacePoint [ colorFrameDescription . Width * colorFrameDescription . Height ] ;
191
+ this . bitmap = new WriteableBitmap ( colorFrameDescription . Width , colorFrameDescription . Height ) ;
192
+ break ;
174
193
default :
175
194
break ;
176
195
}
@@ -183,40 +202,158 @@ private void Sensor_IsAvailableChanged(KinectSensor sender, IsAvailableChangedEv
183
202
184
203
private void Reader_MultiSourceFrameArrived ( MultiSourceFrameReader sender , MultiSourceFrameArrivedEventArgs e )
185
204
{
205
+
186
206
MultiSourceFrame multiSourceFrame = e . FrameReference . AcquireFrame ( ) ;
187
207
188
208
// If the Frame has expired by the time we process this event, return.
189
209
if ( multiSourceFrame == null )
190
210
{
191
211
return ;
192
212
}
213
+ DepthFrame depthFrame = null ;
214
+ ColorFrame colorFrame = null ;
215
+ InfraredFrame infraredFrame = null ;
216
+ BodyIndexFrame bodyIndexFrame = null ;
217
+ //windows.storage.streams
218
+ IBuffer depthFrameData = null ;
219
+ IBuffer bodyIndexFrameData = null ;
220
+ // Com interface for unsafe byte manipulation
221
+ IBufferByteAccess bodyIndexByteAccess = null ;
193
222
194
223
switch ( currentDisplayFrameType )
195
224
{
196
225
case DisplayFrameType . Infrared :
197
- using ( InfraredFrame infraredFrame = multiSourceFrame . InfraredFrameReference . AcquireFrame ( ) )
226
+ using ( infraredFrame = multiSourceFrame . InfraredFrameReference . AcquireFrame ( ) )
198
227
{
199
228
ShowInfraredFrame ( infraredFrame ) ;
200
229
}
201
230
break ;
202
231
case DisplayFrameType . Color :
203
- using ( ColorFrame colorFrame = multiSourceFrame . ColorFrameReference . AcquireFrame ( ) )
232
+ using ( colorFrame = multiSourceFrame . ColorFrameReference . AcquireFrame ( ) )
204
233
{
205
234
ShowColorFrame ( colorFrame ) ;
206
235
}
207
236
break ;
208
237
case DisplayFrameType . Depth :
209
- using ( DepthFrame depthFrame =
210
- multiSourceFrame . DepthFrameReference . AcquireFrame ( ) )
238
+ using ( depthFrame = multiSourceFrame . DepthFrameReference . AcquireFrame ( ) )
211
239
{
212
240
ShowDepthFrame ( depthFrame ) ;
213
241
}
214
242
break ;
243
+ case DisplayFrameType . BodyMask :
244
+ // Put in a try catch to utilise finally() and clean up frames
245
+ try
246
+ {
247
+ depthFrame = multiSourceFrame . DepthFrameReference . AcquireFrame ( ) ;
248
+ bodyIndexFrame = multiSourceFrame . BodyIndexFrameReference . AcquireFrame ( ) ;
249
+ colorFrame = multiSourceFrame . ColorFrameReference . AcquireFrame ( ) ;
250
+ if ( ( depthFrame == null ) || ( colorFrame == null ) || ( bodyIndexFrame == null ) )
251
+ {
252
+ return ;
253
+ }
254
+
255
+ // Access the depth frame data directly via LockImageBuffer to avoid making a copy
256
+ depthFrameData = depthFrame . LockImageBuffer ( ) ;
257
+ this . coordinateMapper . MapColorFrameToDepthSpaceUsingIBuffer ( depthFrameData , this . colorMappedToDepthPoints ) ;
258
+ // Process Color
259
+ colorFrame . CopyConvertedFrameDataToBuffer ( this . bitmap . PixelBuffer , ColorImageFormat . Bgra ) ;
260
+ // Access the body index frame data directly via LockImageBuffer to avoid making a copy
261
+ bodyIndexFrameData = bodyIndexFrame . LockImageBuffer ( ) ;
262
+ ShowMappedBodyFrame ( depthFrame . FrameDescription . Width , depthFrame . FrameDescription . Height , bodyIndexFrameData , bodyIndexByteAccess ) ;
263
+
264
+ }
265
+ finally
266
+ {
267
+ // ... disposing of depth, color and bodyIndex frames
268
+ if ( depthFrame != null )
269
+ {
270
+ depthFrame . Dispose ( ) ;
271
+ }
272
+ if ( colorFrame != null )
273
+ {
274
+ colorFrame . Dispose ( ) ;
275
+ }
276
+ if ( bodyIndexFrame != null )
277
+ {
278
+ bodyIndexFrame . Dispose ( ) ;
279
+ }
280
+
281
+ if ( depthFrameData != null )
282
+ {
283
+ // We must force a release of the IBuffer in order to ensure that we have dropped all references to it.
284
+ System . Runtime . InteropServices . Marshal . ReleaseComObject ( depthFrameData ) ;
285
+ }
286
+ if ( bodyIndexFrameData != null )
287
+ {
288
+ System . Runtime . InteropServices . Marshal . ReleaseComObject ( bodyIndexFrameData ) ;
289
+ }
290
+ if ( bodyIndexByteAccess != null )
291
+ {
292
+ System . Runtime . InteropServices . Marshal . ReleaseComObject ( bodyIndexByteAccess ) ;
293
+ }
294
+
295
+ }
296
+ break ;
297
+
215
298
default :
216
299
break ;
217
300
}
218
301
}
219
302
303
+ unsafe private void ShowMappedBodyFrame ( int depthWidth , int depthHeight , IBuffer bodyIndexFrameData , IBufferByteAccess bodyIndexByteAccess )
304
+ {
305
+ bodyIndexByteAccess = ( IBufferByteAccess ) bodyIndexFrameData ;
306
+ byte * bodyIndexBytes = null ;
307
+ bodyIndexByteAccess . Buffer ( out bodyIndexBytes ) ;
308
+
309
+ fixed ( DepthSpacePoint * colorMappedToDepthPointsPointer = this . colorMappedToDepthPoints )
310
+ {
311
+ IBufferByteAccess bitmapBackBufferByteAccess = ( IBufferByteAccess ) this . bitmap . PixelBuffer ;
312
+
313
+ byte * bitmapBackBufferBytes = null ;
314
+ bitmapBackBufferByteAccess . Buffer ( out bitmapBackBufferBytes ) ;
315
+
316
+ // Treat the color data as 4-byte pixels
317
+ uint * bitmapPixelsPointer = ( uint * ) bitmapBackBufferBytes ;
318
+
319
+ // Loop over each row and column of the color image
320
+ // Zero out any pixels that don't correspond to a body index
321
+ int colorMappedLength = this . colorMappedToDepthPoints . Length ;
322
+ for ( int colorIndex = 0 ; colorIndex < colorMappedLength ; ++ colorIndex )
323
+ {
324
+ float colorMappedToDepthX = colorMappedToDepthPointsPointer [ colorIndex ] . X ;
325
+ float colorMappedToDepthY = colorMappedToDepthPointsPointer [ colorIndex ] . Y ;
326
+
327
+ // The sentinel value is -inf, -inf, meaning that no depth pixel corresponds to this color pixel.
328
+ if ( ! float . IsNegativeInfinity ( colorMappedToDepthX ) &&
329
+ ! float . IsNegativeInfinity ( colorMappedToDepthY ) )
330
+ {
331
+ // Make sure the depth pixel maps to a valid point in color space
332
+ int depthX = ( int ) ( colorMappedToDepthX + 0.5f ) ;
333
+ int depthY = ( int ) ( colorMappedToDepthY + 0.5f ) ;
334
+
335
+ // If the point is not valid, there is no body index there.
336
+ if ( ( depthX >= 0 ) && ( depthX < depthWidth ) && ( depthY >= 0 ) && ( depthY < depthHeight ) )
337
+ {
338
+ int depthIndex = ( depthY * depthWidth ) + depthX ;
339
+
340
+ // If we are tracking a body for the current pixel, do not zero out the pixel
341
+ if ( bodyIndexBytes [ depthIndex ] != 0xff )
342
+ {
343
+ // this bodyIndexByte is good and is a body, loop again.
344
+ continue ;
345
+ }
346
+ }
347
+ }
348
+ // this pixel does not correspond to a body so make it black and transparent
349
+ bitmapPixelsPointer [ colorIndex ] = 0 ;
350
+ }
351
+ }
352
+
353
+ this . bitmap . Invalidate ( ) ;
354
+ FrameDisplayImage . Source = this . bitmap ;
355
+ }
356
+
220
357
private void ShowDepthFrame ( DepthFrame depthFrame )
221
358
{
222
359
bool depthFrameProcessed = false ;
@@ -387,5 +524,17 @@ private void DepthButton_Click(object sender, RoutedEventArgs e)
387
524
SetupCurrentDisplay ( DisplayFrameType . Depth ) ;
388
525
}
389
526
527
+ private void BodyMaskButton_Click ( object sender , RoutedEventArgs e )
528
+ {
529
+ SetupCurrentDisplay ( DisplayFrameType . BodyMask ) ;
530
+ }
531
+
532
+ [ Guid ( "905a0fef-bc53-11df-8c49-001e4fc686da" ) , InterfaceType ( ComInterfaceType . InterfaceIsIUnknown ) ]
533
+ interface IBufferByteAccess
534
+ {
535
+ unsafe void Buffer ( out byte * pByte ) ;
536
+ }
537
+
538
+
390
539
}
391
540
}
0 commit comments