Buenas,
esta es la 2da parte del post donde muestro como utilizar a la cámara de Kinect como una pantalla verde para plantar la imagen de nuestro cuerpo … pues donde queramos.
En el post anterior quedaba una parte importante de analizar que era el proceso de cada frame del skeleton, cámara y sensor de profundidad.
1: void SensorAllFramesReady(object sender, AllFramesReadyEventArgs e)
2: {
3: if (_sensor == null) return;
4: var hasDepth = false;
5: var hasColor = false;
6: hasDepth = GetDepthFrame(e);
7: hasColor = GetColorFrame(e);
8: ProcessDepthFrame(hasDepth);
9: ProcessColorFrame(hasColor);
10: }
Como veremos en el siguiente código, las funciones GetDepthFrame y GetColorFrame validan que poseamos información correcta de la cámara y del sensor de profundidad, antes de dar como válido el proceso.
A continuación la función ProcessDepthFrame se encarga de realizar un mapeo de los puntos del array de la cámara y del array del sensor de profundidad que nos da como resultado un array donde en cada punto sabemos, la información de la cámara, la distancia de la misma al sensor, si está relacionada con un player y además podremos relacionarla también con un joint del skeleton.
Con toda esta información, en la 2da función ProcessColorFrame ya podremos pintar sobre el mapa de bits de la imagen de fondo, solo el cuerpo de cada player y dejar los otros bits en modo transparente.
1: private void ProcessColorFrame(bool hasColor)
2: {
3: if (!hasColor) return;
4: // Write the pixel data into our bitmap
5: _colorBitmap.WritePixels(new Int32Rect(0, 0, _colorBitmap.PixelWidth, _colorBitmap.PixelHeight), _colorPixels,
6: _colorBitmap.PixelWidth*sizeof (int), 0);
7:
8: if (_playerOpacityMaskImage == null)
9: {
10: _playerOpacityMaskImage = new WriteableBitmap(_depthWidth, _depthHeight, 96, 96, PixelFormats.Bgra32, null);
11: imgMask.OpacityMask = new ImageBrush
12: {
13: ImageSource = _playerOpacityMaskImage
14: };
15: }
16:
17: _playerOpacityMaskImage.WritePixels(new Int32Rect(0, 0, _depthWidth, _depthHeight), _greenScreenPixelData,
18: _depthWidth*((_playerOpacityMaskImage.Format.BitsPerPixel + 7)/8), 0);
19: }
20:
21: private void ProcessDepthFrame(bool hasDepth)
22: {
23: if (hasDepth)
24: {
25: _sensor.MapDepthFrameToColorFrame(DepthImageFormat.Resolution320x240Fps30, _depthPixels,
26: ColorImageFormat.RgbResolution640x480Fps30, _colorCoordinates);
27:
28: Array.Clear(_greenScreenPixelData, 0, _greenScreenPixelData.Length);
29:
30: for (var y = 0; y < _depthHeight; ++y)
31: {
32: for (var x = 0; x < _depthWidth; ++x)
33: {
34: var depthIndex = x + (y*_depthWidth);
35: var depthPixel = _depthPixels[depthIndex];
36: var player = depthPixel & DepthImageFrame.PlayerIndexBitmask;
37: if (player <= 0) continue;
38:
39: var colorImagePoint = _colorCoordinates[depthIndex];
40: var colorInDepthX = colorImagePoint.X/_colorToDepthDivisor;
41: var colorInDepthY = colorImagePoint.Y/_colorToDepthDivisor;
42: if (colorInDepthX <= 0 || colorInDepthX >= _depthWidth || colorInDepthY < 0 ||
43: colorInDepthY >= _depthHeight) continue;
44: var greenScreenIndex = colorInDepthX + (colorInDepthY*_depthWidth);
45: _greenScreenPixelData[greenScreenIndex] = OpaquePixelValue;
46: _greenScreenPixelData[greenScreenIndex - 1] = OpaquePixelValue;
47: }
48: }
49: }
50: }
51:
52: private bool GetColorFrame(AllFramesReadyEventArgs e)
53: {
54: bool hasColor;
55: using (var colorFrame = e.OpenColorImageFrame())
56: {
57: if (colorFrame != null)
58: {
59: colorFrame.CopyPixelDataTo(_colorPixels);
60: hasColor = true;
61: }
62: }
63: return hasColor;
64: }
65:
66: private bool GetDepthFrame(AllFramesReadyEventArgs e)
67: {
68: bool hasDepth;
69: using (var depthFrame = e.OpenDepthImageFrame())
70: {
71: if (depthFrame != null)
72: {
73: depthFrame.CopyPixelDataTo(_depthPixels);
74: hasDepth = true;
75: }
76: }
77: return hasDepth;
78: }
Ahora si que lo han simplificado ![]()
Saludos @ Home
El Bruno
Leave a comment