Buenas,
después de los primeros 2 posts
- [#KINECT] HowTo: Utilizar Face Recognition con #KinectSdk (I)
http://elbruno.com/2012/07/31/kinect-howto-utilizar-face-recognition-con-kinectsdk-i/ - [#KINECT] HowTo: Utilizar Face Recognition con #KinectSdk (II)
http://elbruno.com/2012/08/07/kinect-howto-utilizar-face-recognition-con-kinectsdk-ii/
hoy veremos como modificar la “red” que se dibuja en nuestro rostro utilizando el ejemplo del post anterior. Repasando un poco cómo está montado el mismo, vemos que el UserControl [FaceTracking.xaml] es el que muestra la red con la cara sobre una imagen en la que se muestra el output de la cámara del sensor Kinect.
Para pintar la red, la clase [SkeletonFaceTracker.cs] utiliza la rutina DrawFaceModel() que crea una colección de triángulos y luego pinta los mismos.
1: public void DrawFaceModel(DrawingContext drawingContext)
2: {
3: if (!LastFaceTrackSucceeded || _skeletonTrackingState != SkeletonTrackingState.Tracked)
4: {
5: _startFaceRecognition = DateTime.MinValue;
6: return;
7: }
8:
9: var faceModelPts = _facePoints.Select(t => new Point(t.X + 0.5f, t.Y + 0.5f)).ToList();
10:
11: var faceModel = _faceTriangles.Select(t => new FaceModelTriangle
12: {
13: P1 = faceModelPts[t.First],
14: P2 = faceModelPts[t.Second],
15: P3 = faceModelPts[t.Third]
16: }).ToList();
17:
18: var faceModelGroup = new GeometryGroup();
19: for (var i = 0; i < faceModel.Count; i++)
20: {
21: var faceTriangle = new GeometryGroup();
22: faceTriangle.Children.Add(new LineGeometry(faceModel[i].P1, faceModel[i].P2));
23: faceTriangle.Children.Add(new LineGeometry(faceModel[i].P2, faceModel[i].P3));
24: faceTriangle.Children.Add(new LineGeometry(faceModel[i].P3, faceModel[i].P1));
25: faceModelGroup.Children.Add(faceTriangle);
26: }
27:
28: drawingContext.DrawGeometry(Brushes.BlueViolet, new Pen(Brushes.Red, 1.0), faceModelGroup);
29: if (_startFaceRecognition == DateTime.MinValue)
30: {
31: _startFaceRecognition = DateTime.Now;
32: }
33: else
34: {
35: if (DateTime.Now.Subtract(_startFaceRecognition).TotalSeconds > 5)
36: {
37: Application.Current.Dispatcher.BeginInvoke(new Action(() =>
38: {
39: System.Threading.Thread.Sleep(300);
40: _startFaceRecognition = DateTime.MinValue;
41: }));
42: }
43: }
44: }
Para la mejorar un poco este ejemplo, en lugar de pintar la red sobre la cara, lo que haremos es pintar los puntos y además en cada punto poner el número del mismo. Lo que hacemos es crear una nueva función llamada () con el siguiente código.
1: public void DrawFaceFlat(DrawingContext drawingContext)
2: {
3: if (!LastFaceTrackSucceeded || _skeletonTrackingState != SkeletonTrackingState.Tracked)
4: {
5: _startFaceRecognition = DateTime.MinValue;
6: return;
7: }
8:
9: var faceModelPts = _facePoints.Select(t => new Point(t.X + 0.5f, t.Y + 0.5f)).ToList();
10:
11: var faceModelGroup = new GeometryGroup();
12: for (var i = 0; i < faceModelPts.Count; i++)
13: {
14: var geometryGroup = new GeometryGroup();
15: var ellipseGeometry = new EllipseGeometry(faceModelPts[i], 1, 1);
16:
17: var formattedText = new FormattedText(i.ToString(), CultureInfo.InvariantCulture, FlowDirection.LeftToRight,
18: new Typeface("Verdana"), 12, Brushes.White);
19: geometryGroup.Children.Add(ellipseGeometry);
20: faceModelGroup.Children.Add(geometryGroup);
21: }
22:
23: drawingContext.DrawGeometry(Brushes.Yellow, new Pen(Brushes.Yellow, 1.0), faceModelGroup);
24:
25: for (var i = 0; i < faceModelPts.Count; i++)
26: {
27: var formattedText = new FormattedText(i.ToString(), CultureInfo.InvariantCulture, FlowDirection.LeftToRight, new Typeface("Verdana"), 8, Brushes.White);
28: drawingContext.DrawText(formattedText, faceModelPts[i]);
29: }
30:
31: if (_startFaceRecognition == DateTime.MinValue)
32: {
33: _startFaceRecognition = DateTime.Now;
34: }
35: else
36: {
37: if (DateTime.Now.Subtract(_startFaceRecognition).TotalSeconds > 5)
38: {
39: Application.Current.Dispatcher.BeginInvoke(new Action(() =>
40: {
41: System.Threading.Thread.Sleep(300);
42: _startFaceRecognition = DateTime.MinValue;
43: }));
44: }
45: }
46: }
Luego cambiamos la ínvocación en [FaceTracking.xaml] para que utilice esta rutina y el resultado es el siguiente.
Ahora bien, como hay demasiados puntos para mostrar en un espacio tan pequeño, aplicaremos un filtro para solo motrar los puntos
var pointFilter = new List<int> {4, 8 , 39, 41, 42, 48, 54, 68, 86, 74, 80, 57, 51};
el resultado es un poco más simpático …![]()
Saludos @ La Finca
El Bruno
Saludos desde Ecuador!
Excelente proyecto!!, soy novato en el uso del C# y quiero hacer un proyecto con KINECT FaceTracking.
Quiero encender una luz al momento que el usuario gire la cabeza al lado izquierdo, para eso creo que necesito el vector que tiene los puntos 3D, el mismo que posee los numeros de cada punto, para poder manejarme con ellos.
Por favor dame alguna sugerencia para lograrlo.
Muchas gracias!!
Alejandro, pues lo que comentas no es complicado de hacer. Con el Kinect SDK lo podrás hacer fácilmente. Cuando lo temines me avisas así lo vemos
Saludos
Buenas Bruno,
Como puedo hacer que una vez reconocida la cara me dibuje otro tipo de mascara? una mascara estática 3D? que tipo de formato debe de tener?
Me gustaría comenzar pudiendo añadir simples objetos 3d a la cara de los usuarios como gorros, bigotes y pelucas. Crees que esto es posible?
Muchas gracias por tu ayuda.
Buenas,
La misma respuesta que en el post anterior.
Buenas comodin
pues la verdad que no sabría decirte como poner una máscara estática 3D en una app WPF. No soy un experto en WPF y mucho menos en modelados 3D.
El Toolkit tiene varios ejemplos y uno de ellos agrega una proyección de la cara de la persona, lo puedes ver en http://kinectforwindowsorg, dentro de las descargas del Toolkit. El ejemplo es FaceTracking 3D-WPF (http://msdn.microsoft.com/en-us/library/jj131043) y tal vez pueda servirte como punto de partida.
Saludos
/Bruno