1
|
using UnityEngine;
|
2
|
using System;
|
3
|
using System.Collections;
|
4
|
using System.Collections.Generic;
|
5
|
using System.IO;
|
6
|
|
7
|
|
8
|
/// <summary>
|
9
|
/// Background removal manager is the component that manages Kinect background removal, i.e. cutting out user body silhouettes.
|
10
|
/// </summary>
|
11
|
public class BackgroundRemovalManager : MonoBehaviour
|
12
|
{
|
13
|
[Tooltip("Index of the player, tracked by this component. -1 means all players, 0 - the 1st player only, 1 - the 2nd player only, etc.")]
|
14
|
public int playerIndex = -1;
|
15
|
|
16
|
[Tooltip("Camera that may be used to display the foreground texture as GUI texture on the screen.")]
|
17
|
public Camera foregroundCamera;
|
18
|
|
19
|
[Tooltip("Whether the hi-res (color camera resolution) is preferred for the foreground image. Otherwise the depth camera resolution will be used.")]
|
20
|
public bool colorCameraResolution = true;
|
21
|
|
22
|
[Tooltip("Whether only the body alpha texture is needed.")]
|
23
|
public bool computeBodyTexOnly = false;
|
24
|
|
25
|
[Tooltip("Whether the color texture will be inverted or not. Leave disabled for silhouettes, enable for background.")]
|
26
|
public bool invertAlphaColorMask = false;
|
27
|
|
28
|
[Tooltip("Color used to paint pixels, where the foreground color data is not available.")]
|
29
|
private Color32 defaultColor = new Color32(64, 64, 64, 255);
|
30
|
|
31
|
[Tooltip("(Advanced) Number of erode iterations used by the erode/dilate filter.")]
|
32
|
[Range(0, 9)]
|
33
|
public int erodeIterations = 0; // 3;
|
34
|
|
35
|
[Tooltip("(Advanced) Number of dilate iterations used by the erode/dilate filter.")]
|
36
|
[Range(0, 9)]
|
37
|
public int dilateIterations = 0; // 3;
|
38
|
|
39
|
[Tooltip("GUI-Text to display the BR-Manager debug messages.")]
|
40
|
public GUIText debugText;
|
41
|
|
42
|
// buffer for the raw foreground image
|
43
|
private byte[] foregroundImage;
|
44
|
|
45
|
// the foreground texture
|
46
|
private Texture2D foregroundTex;
|
47
|
|
48
|
// rectangle taken by the foreground texture (in pixels)
|
49
|
private Rect foregroundRect;
|
50
|
|
51
|
// primary sensor data structure
|
52
|
private KinectInterop.SensorData sensorData = null;
|
53
|
|
54
|
// Bool to keep track whether Kinect and BR library have been initialized
|
55
|
private bool isBrInited = false;
|
56
|
|
57
|
// The single instance of BackgroundRemovalManager
|
58
|
private static BackgroundRemovalManager instance;
|
59
|
|
60
|
|
61
|
/// <summary>
|
62
|
/// Gets the single BackgroundRemovalManager instance.
|
63
|
/// </summary>
|
64
|
/// <value>The BackgroundRemovalManager instance.</value>
|
65
|
public static BackgroundRemovalManager Instance
|
66
|
{
|
67
|
get
|
68
|
{
|
69
|
return instance;
|
70
|
}
|
71
|
}
|
72
|
|
73
|
/// <summary>
|
74
|
/// Determines whether the BackgroundRemovalManager was successfully initialized.
|
75
|
/// </summary>
|
76
|
/// <returns><c>true</c> if the BackgroundRemovalManager was successfully initialized; otherwise, <c>false</c>.</returns>
|
77
|
public bool IsBackgroundRemovalInitialized()
|
78
|
{
|
79
|
return isBrInited;
|
80
|
}
|
81
|
|
82
|
// // returns the raw foreground image
|
83
|
// public byte[] GetForegroundImage()
|
84
|
// {
|
85
|
// return foregroundImage;
|
86
|
// }
|
87
|
|
88
|
/// <summary>
|
89
|
/// Gets the foreground image texture.
|
90
|
/// </summary>
|
91
|
/// <returns>The foreground image texture.</returns>
|
92
|
public Texture GetForegroundTex()
|
93
|
{
|
94
|
bool bHiResSupported = sensorData != null && sensorData.sensorInterface != null ?
|
95
|
sensorData.sensorInterface.IsBRHiResSupported() : false;
|
96
|
bool bKinect1Int = sensorData != null && sensorData.sensorInterface != null ?
|
97
|
(sensorData.sensorInterface.GetSensorPlatform() == KinectInterop.DepthSensorPlatform.KinectSDKv1) : false;
|
98
|
|
99
|
if(computeBodyTexOnly && sensorData != null && sensorData.alphaBodyTexture)
|
100
|
{
|
101
|
return sensorData.alphaBodyTexture;
|
102
|
}
|
103
|
else if(sensorData != null && bHiResSupported && !bKinect1Int && sensorData.color2DepthTexture)
|
104
|
{
|
105
|
return sensorData.color2DepthTexture;
|
106
|
}
|
107
|
else if(sensorData != null && !bKinect1Int && sensorData.depth2ColorTexture)
|
108
|
{
|
109
|
return sensorData.depth2ColorTexture;
|
110
|
}
|
111
|
|
112
|
return foregroundTex;
|
113
|
}
|
114
|
|
115
|
/// <summary>
|
116
|
/// Gets the alpha body texture.
|
117
|
/// </summary>
|
118
|
/// <returns>The alpha body texture.</returns>
|
119
|
public Texture GetAlphaBodyTex()
|
120
|
{
|
121
|
if(sensorData != null)
|
122
|
{
|
123
|
if(sensorData.alphaBodyTexture != null)
|
124
|
return sensorData.alphaBodyTexture;
|
125
|
else if(foregroundTex != null)
|
126
|
return foregroundTex; // fallback for k1
|
127
|
else
|
128
|
return sensorData.bodyIndexTexture; // general fallback (may have different dimensions)
|
129
|
}
|
130
|
|
131
|
return null;
|
132
|
}
|
133
|
|
134
|
//----------------------------------- end of public functions --------------------------------------//
|
135
|
|
136
|
void Awake()
|
137
|
{
|
138
|
instance = this;
|
139
|
}
|
140
|
|
141
|
void Start()
|
142
|
{
|
143
|
try
|
144
|
{
|
145
|
// get sensor data
|
146
|
KinectManager kinectManager = KinectManager.Instance;
|
147
|
if(kinectManager && kinectManager.IsInitialized())
|
148
|
{
|
149
|
sensorData = kinectManager.GetSensorData();
|
150
|
}
|
151
|
|
152
|
if(sensorData == null || sensorData.sensorInterface == null)
|
153
|
{
|
154
|
throw new Exception("Background removal cannot be started, because KinectManager is missing or not initialized.");
|
155
|
}
|
156
|
|
157
|
// ensure the needed dlls are in place and speech recognition is available for this interface
|
158
|
bool bNeedRestart = false;
|
159
|
bool bSuccess = sensorData.sensorInterface.IsBackgroundRemovalAvailable(ref bNeedRestart);
|
160
|
|
161
|
if(bSuccess)
|
162
|
{
|
163
|
if(bNeedRestart)
|
164
|
{
|
165
|
KinectInterop.RestartLevel(gameObject, "BR");
|
166
|
return;
|
167
|
}
|
168
|
}
|
169
|
else
|
170
|
{
|
171
|
string sInterfaceName = sensorData.sensorInterface.GetType().Name;
|
172
|
throw new Exception(sInterfaceName + ": Background removal is not supported!");
|
173
|
}
|
174
|
|
175
|
// inverted alpha-body mask to color texture
|
176
|
sensorData.invertAlphaColorMask = invertAlphaColorMask;
|
177
|
|
178
|
if(invertAlphaColorMask &&
|
179
|
(sensorData.sensorInterface.GetSensorPlatform() == KinectInterop.DepthSensorPlatform.KinectSDKv1))
|
180
|
{
|
181
|
// enable the foreground blender if found
|
182
|
ForegroundBlender foreBlender = ForegroundBlender.Instance;
|
183
|
|
184
|
if(foreBlender)
|
185
|
{
|
186
|
foreBlender.enabled = true;
|
187
|
|
188
|
// disable the foreground camera, too
|
189
|
foregroundCamera = null;
|
190
|
}
|
191
|
}
|
192
|
|
193
|
// Initialize the background removal
|
194
|
bSuccess = sensorData.sensorInterface.InitBackgroundRemoval(sensorData, colorCameraResolution);
|
195
|
|
196
|
if (!bSuccess)
|
197
|
{
|
198
|
throw new Exception("Background removal could not be initialized.");
|
199
|
}
|
200
|
|
201
|
// create the foreground image and alpha-image
|
202
|
int imageLength = sensorData.sensorInterface.GetForegroundFrameLength(sensorData, colorCameraResolution);
|
203
|
foregroundImage = new byte[imageLength];
|
204
|
|
205
|
// get the needed rectangle
|
206
|
Rect neededFgRect = sensorData.sensorInterface.GetForegroundFrameRect(sensorData, colorCameraResolution);
|
207
|
|
208
|
// create the foreground texture
|
209
|
foregroundTex = new Texture2D((int)neededFgRect.width, (int)neededFgRect.height, TextureFormat.RGBA32, false);
|
210
|
|
211
|
// calculate the foreground rectangle
|
212
|
if(foregroundCamera != null)
|
213
|
{
|
214
|
Rect cameraRect = foregroundCamera.pixelRect;
|
215
|
float rectHeight = cameraRect.height;
|
216
|
float rectWidth = cameraRect.width;
|
217
|
|
218
|
if(rectWidth > rectHeight)
|
219
|
rectWidth = Mathf.Round(rectHeight * neededFgRect.width / neededFgRect.height);
|
220
|
else
|
221
|
rectHeight = Mathf.Round(rectWidth * neededFgRect.height / neededFgRect.width);
|
222
|
|
223
|
foregroundRect = new Rect((cameraRect.width - rectWidth) / 2, cameraRect.height - (cameraRect.height - rectHeight) / 2, rectWidth, -rectHeight);
|
224
|
}
|
225
|
|
226
|
isBrInited = true;
|
227
|
|
228
|
//DontDestroyOnLoad(gameObject);
|
229
|
}
|
230
|
catch(DllNotFoundException ex)
|
231
|
{
|
232
|
Debug.LogError(ex.ToString());
|
233
|
if(debugText != null)
|
234
|
debugText.text = "Please check the Kinect and BR-Library installations.";
|
235
|
}
|
236
|
catch (Exception ex)
|
237
|
{
|
238
|
Debug.LogError(ex.ToString());
|
239
|
if(debugText != null)
|
240
|
debugText.text = ex.Message;
|
241
|
}
|
242
|
}
|
243
|
|
244
|
void OnDestroy()
|
245
|
{
|
246
|
if(isBrInited && sensorData != null && sensorData.sensorInterface != null)
|
247
|
{
|
248
|
// finish background removal
|
249
|
sensorData.sensorInterface.FinishBackgroundRemoval(sensorData);
|
250
|
}
|
251
|
|
252
|
isBrInited = false;
|
253
|
instance = null;
|
254
|
}
|
255
|
|
256
|
void Update ()
|
257
|
{
|
258
|
if(isBrInited)
|
259
|
{
|
260
|
// select one player or all players
|
261
|
if(playerIndex != -1)
|
262
|
{
|
263
|
KinectManager kinectManager = KinectManager.Instance;
|
264
|
long userID = 0;
|
265
|
|
266
|
if(kinectManager && kinectManager.IsInitialized())
|
267
|
{
|
268
|
userID = kinectManager.GetUserIdByIndex(playerIndex);
|
269
|
|
270
|
if(userID != 0)
|
271
|
{
|
272
|
sensorData.selectedBodyIndex = (byte)kinectManager.GetBodyIndexByUserId(userID);
|
273
|
}
|
274
|
}
|
275
|
|
276
|
if(userID == 0)
|
277
|
{
|
278
|
// don't display anything - set fictive index
|
279
|
sensorData.selectedBodyIndex = 222;
|
280
|
}
|
281
|
}
|
282
|
else
|
283
|
{
|
284
|
// show all players
|
285
|
sensorData.selectedBodyIndex = 255;
|
286
|
}
|
287
|
|
288
|
// erode & dilate iterations
|
289
|
sensorData.erodeIterations = erodeIterations;
|
290
|
sensorData.dilateIterations = dilateIterations;
|
291
|
|
292
|
// update the background removal
|
293
|
bool bSuccess = sensorData.sensorInterface.UpdateBackgroundRemoval(sensorData, colorCameraResolution, defaultColor, computeBodyTexOnly);
|
294
|
|
295
|
if(bSuccess)
|
296
|
{
|
297
|
KinectManager kinectManager = KinectManager.Instance;
|
298
|
if(kinectManager && kinectManager.IsInitialized())
|
299
|
{
|
300
|
bool bLimitedUsers = kinectManager.IsTrackedUsersLimited();
|
301
|
List<int> alTrackedIndexes = kinectManager.GetTrackedBodyIndices();
|
302
|
bSuccess = sensorData.sensorInterface.PollForegroundFrame(sensorData, colorCameraResolution, defaultColor, bLimitedUsers, alTrackedIndexes, ref foregroundImage);
|
303
|
|
304
|
if(bSuccess)
|
305
|
{
|
306
|
foregroundTex.LoadRawTextureData(foregroundImage);
|
307
|
foregroundTex.Apply();
|
308
|
}
|
309
|
}
|
310
|
}
|
311
|
}
|
312
|
}
|
313
|
|
314
|
void OnGUI()
|
315
|
{
|
316
|
if(isBrInited && foregroundCamera)
|
317
|
{
|
318
|
// get the foreground rectangle (use the portrait background, if available)
|
319
|
PortraitBackground portraitBack = PortraitBackground.Instance;
|
320
|
if(portraitBack && portraitBack.enabled)
|
321
|
{
|
322
|
foregroundRect = portraitBack.GetBackgroundRect();
|
323
|
|
324
|
foregroundRect.y += foregroundRect.height; // invert y
|
325
|
foregroundRect.height = -foregroundRect.height;
|
326
|
}
|
327
|
|
328
|
// update the foreground texture
|
329
|
bool bHiResSupported = sensorData != null && sensorData.sensorInterface != null ?
|
330
|
sensorData.sensorInterface.IsBRHiResSupported() : false;
|
331
|
bool bKinect1Int = sensorData != null && sensorData.sensorInterface != null ?
|
332
|
(sensorData.sensorInterface.GetSensorPlatform() == KinectInterop.DepthSensorPlatform.KinectSDKv1) : false;
|
333
|
|
334
|
if(computeBodyTexOnly && sensorData != null && sensorData.alphaBodyTexture)
|
335
|
{
|
336
|
GUI.DrawTexture(foregroundRect, sensorData.alphaBodyTexture);
|
337
|
}
|
338
|
else if(sensorData != null && bHiResSupported && !bKinect1Int && sensorData.color2DepthTexture)
|
339
|
{
|
340
|
//GUI.DrawTexture(foregroundRect, sensorData.alphaBodyTexture);
|
341
|
GUI.DrawTexture(foregroundRect, sensorData.color2DepthTexture);
|
342
|
}
|
343
|
else if(sensorData != null && !bKinect1Int && sensorData.depth2ColorTexture)
|
344
|
{
|
345
|
//GUI.DrawTexture(foregroundRect, sensorData.alphaBodyTexture);
|
346
|
GUI.DrawTexture(foregroundRect, sensorData.depth2ColorTexture);
|
347
|
}
|
348
|
else if(foregroundTex)
|
349
|
{
|
350
|
//GUI.DrawTexture(foregroundRect, sensorData.alphaBodyTexture);
|
351
|
GUI.DrawTexture(foregroundRect, foregroundTex);
|
352
|
}
|
353
|
}
|
354
|
}
|
355
|
|
356
|
|
357
|
}
|