프로젝트

일반

사용자정보

통계
| 개정판:

t1 / TFDContents / Assets / KinectScripts / BackgroundRemovalManager.cs @ 3

이력 | 보기 | 이력해설 | 다운로드 (11 KB)

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
}