Pruebas Unitarias – Parte 1

Hola, sean bienvenidos a una nueva sección, donde vamos a explicar un poco todo lo relacionado con este tema muy interesante de unit testing, a continuación en la primera entrega de videos de programación y buenas practicas.

Espero les sea de provecho y utilidad, esperen la segunda parte que ya esta en el horno, salu2…

Demo Kinect Comandos por voz en ESPAÑOL

En este post explicare sobre el uso de el arreglo de microfonos del Kinect con un ejemplo donde a travez de las librerias Microsoft Speech SDK y el SDK de KINECT podremos a travez de comandos de voz dar alguna instruccion al computador para mostrar algo en una aplicacion C# natural en WPF…

Se me ocurrio un ejemplo similar al que nos trae la SDK Toolkit de Kinect donde al hablar se muestra el espectro de voz de la persona que habla, pero en este caso, utilizare para explicarles sencillamente como ejemplo una aplicacion que al decir un color de los que muestre en la aplicacion esta sea capaz de identificarlo y de pintarlo en la aplicación, dando un rango de exito o de fracaso…

Pensaran que es algo complejo de analizar y de sintetizar la voz y esas cosas pero realmente no nos complicaremos la vida y por suerte ya existen herramientas a la mano para hacer estas cosas como

Bien para esto es necesario previamente tener el Microsoft Speech SDK en este caso la version mas actual que es la 11.0 que la podemos descargar en el siguiente enlace: Microsoft Speech SDK v11.0

Tambien necesitaremos de una libreria de idioma en nuestro caso Español que debemos de desacargar de la pagina Oficial de Kinect en nuestro caso ES-mx (Español-Mexico) o ES-es (Español-España): Kinect for Windows Language Packs v11.0

Una vez instalado estas, procedemos ahora a crear un nuevo proyecto WPF en C# en Visual Studio 2012 o 2010 como lo vayan preferiendo.

blogaudiokinet1

Una vez creada la solucion del proyecto nos vamos al archivo MainWindow.xaml donde escribiremos el siguiente codigo..


<Window x:Class="WpfAudioKinectPruebaHablar.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        
        Title="Kinect Audio Demo" Height="364" Width="680">
    <Grid Background="white">
        <TextBlock Text="KINECT Demo Audio Prueba" FontSize="36" HorizontalAlignment="Left" VerticalAlignment="Top" Margin="10,5,0,0" FontWeight="Light" />
        <StackPanel HorizontalAlignment="Center" VerticalAlignment="Bottom" >
            <TextBlock x:Name="tbColor" Height="100" Width="500"/>            
            <TextBlock x:Name="tbInfo" Text="" Foreground="Black" Height="50" FontSize="20" TextAlignment="Center" Padding="0,10,0,0"/>
            <TextBlock x:Name="tbSpeech" Text="" Foreground="Black" Height="60" FontSize="16" TextAlignment="Left" Padding="0,10,0,10"/>
        </StackPanel>
        <TextBlock FontSize="16" HorizontalAlignment="Left" Margin="80,93,0,0" Text="diga algo para activar el reconocimiento" VerticalAlignment="Top" Width="379" FontWeight="Light" />
        
    </Grid>
</Window>

En el codigo aparecen tres TextBlock de nombre tbColor, tbInfo, tbSpeech estos son para mostrar una breve leyenda, el color procesado y el indice de acierto…

Antes de iniciar el codigo y la logica de la aplicacion debemos de agregar las referencias o DLLs que ya habiamos mencionado que son la Microsoft.Speech y Microsoft.Kinect

addreference

ahora bien, vamos con la parte mas interesante que es la de trabajar con las librerias de Microsoft Speech y por supuesto la libreria de KINECT sdk, procedemos a abrir el code-behind de MainWindow.xaml que es MainWindow.cs; donde ya abierto, agregamos la libreria Microsoft.Kinect, las siguientes Microsoft.Speech.AudioFormat y Microsoft.Speech.Recognition


using Microsoft.Kinect;

using Microsoft.Speech.AudioFormat;
using Microsoft.Speech.Recognition;

siguiendo con el codigo creamos 5 variables de tipo SolidColorBrush y le di a cada una un color y creamos la variable kinect de tipo KinectSensor, un DispatcherTimer que le llame readyTimer y dos variables muy interesantes que vienen de la libreria Speech que son EnergyCalculatingPassThroughStream que es la variable que contendra el espectro de la energia y la forma de la voz sintetizada para a travez de la segunda variable que es la que crea una especie de gramatica dependiendo de la cultura y el enfasis de la voz la como se muestra en el siguiente codigo.


 private readonly SolidColorBrush redBrush = new SolidColorBrush(Colors.Red);
 private readonly SolidColorBrush greenBrush = new SolidColorBrush(Colors.Green);
 private readonly SolidColorBrush yellowBrush = new SolidColorBrush(Colors.Yellow);
 private readonly SolidColorBrush blueBrush = new SolidColorBrush(Colors.Blue);
 private readonly SolidColorBrush WhiteBrush = new SolidColorBrush(Colors.White);

 KinectSensor kinect;

 private DispatcherTimer readyTimer;
 private EnergyCalculatingPassThroughStream stream;
 private SpeechRecognitionEngine speechRecognizer;

«Suena dificil y complejo pero son solo sencillas primitivas para trabajar el reconocimiento de voz en nuestras aplicaciones».. aca les dejo unas rutinas establecidas para el control de la voz, sintetizarla y despues tomarla en la variable para asi ahora poder trabajar con ella a travez del Kinect, por ahora solo les dejo el siguiente codigo:

 private class EnergyCalculatingPassThroughStream : Stream
 {
   private const int SamplesPerPixel = 10;

   private readonly double[] energy = new double[500];
   private readonly object syncRoot = new object();
   private readonly Stream baseStream;

   private int index;
   private int sampleCount;
   private double avgSample;

 public EnergyCalculatingPassThroughStream(Stream stream)
 {
   this.baseStream = stream;
 }

 public override long Length
 {
   get { return this.baseStream.Length; }
 }

 public override long Position
 {
   get { return this.baseStream.Position; }
   set { this.baseStream.Position = value; }
 }

 public override bool CanRead
 {
   get { return this.baseStream.CanRead; }
 }

 public override bool CanSeek
 {
   get { return this.baseStream.CanSeek; }
 }

 public override bool CanWrite
 {
   get { return this.baseStream.CanWrite; }
 }

 public override void Flush()
 {
   this.baseStream.Flush();
 }

 public void GetEnergy(double[] energyBuffer)
 {
   lock (this.syncRoot)
   {
     int energyIndex = this.index;
     for (int i = 0; i < this.energy.Length; i++)       {       energyBuffer[i] = this.energy[energyIndex];       energyIndex++;       if (energyIndex >= this.energy.Length)
     {
       energyIndex = 0;
     }
   }
  }
 }

  public override int Read(byte[] buffer, int offset, int count)
  {
    int retVal = this.baseStream.Read(buffer, offset, count);
    const double A = 0.3;
    lock (this.syncRoot)
    {
    for (int i = 0; i < retVal; i += 2)      {        short sample = BitConverter.ToInt16(buffer, i + offset);        this.avgSample += sample * sample;        this.sampleCount++;        if (this.sampleCount == SamplesPerPixel)        {          this.avgSample /= SamplesPerPixel;          this.energy[this.index] = .2 + ((this.avgSample * 11) / (int.MaxValue / 2));          this.energy[this.index] = this.energy[this.index] > 10 ? 10 : this.energy[this.index];

        if (this.index > 0)
        {
          this.energy[this.index] = (this.energy[this.index] * A) + ((1 - A) * this.energy[this.index - 1]);
        }

     this.index++;

     if (this.index >= this.energy.Length)
     {
       this.index = 0;
     }

       this.avgSample = 0;
       this.sampleCount = 0;
    }
   }
  }

  return retVal;
 }

  public override long Seek(long offset, SeekOrigin origin)
  {
    return this.baseStream.Seek(offset, origin);
  }

  public override void SetLength(long value)
  {
    this.baseStream.SetLength(value);
  }

  public override void Write(byte[] buffer, int offset, int count)
  {
    this.baseStream.Write(buffer, offset, count);
  }
 }

Y aca les dejo todo codigo fuente para poner a andar nuestro Kinect por voz y en español!…. despues les seguire mostrando detalladamente cada una de las funcionalidades de este demo para que lo apliquen a un sin fin de cosas.

using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Threading;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Threading;

using Microsoft.Kinect;

using Microsoft.Speech.AudioFormat;
using Microsoft.Speech.Recognition;
namespace WpfAudioKinectPruebaHablar
{
 ///
 /// Interaction logic for MainWindow.xaml
 ///
 public partial class MainWindow : Window
 {
 private readonly SolidColorBrush redBrush = new SolidColorBrush(Colors.Red);
 private readonly SolidColorBrush greenBrush = new SolidColorBrush(Colors.Green);
 private readonly SolidColorBrush yellowBrush = new SolidColorBrush(Colors.Yellow);
 private readonly SolidColorBrush blueBrush = new SolidColorBrush(Colors.Blue);
 private readonly SolidColorBrush WhiteBrush = new SolidColorBrush(Colors.White);

 KinectSensor kinect;

 private DispatcherTimer readyTimer;
 private EnergyCalculatingPassThroughStream stream;
 private SpeechRecognitionEngine speechRecognizer;

 #region class EnergyCalculatingPassThroughStream

 private class EnergyCalculatingPassThroughStream : Stream
 {
 private const int SamplesPerPixel = 10;

 private readonly double[] energy = new double[500];
 private readonly object syncRoot = new object();
 private readonly Stream baseStream;

 private int index;
 private int sampleCount;
 private double avgSample;

 public EnergyCalculatingPassThroughStream(Stream stream)
 {
 this.baseStream = stream;
 }

 public override long Length
 {
 get { return this.baseStream.Length; }
 }

 public override long Position
 {
 get { return this.baseStream.Position; }
 set { this.baseStream.Position = value; }
 }

 public override bool CanRead
 {
 get { return this.baseStream.CanRead; }
 }

 public override bool CanSeek
 {
 get { return this.baseStream.CanSeek; }
 }

 public override bool CanWrite
 {
 get { return this.baseStream.CanWrite; }
 }

 public override void Flush()
 {
 this.baseStream.Flush();
 }

 public void GetEnergy(double[] energyBuffer)
 {
 lock (this.syncRoot)
 {
 int energyIndex = this.index;
 for (int i = 0; i < this.energy.Length; i++) { energyBuffer[i] = this.energy[energyIndex]; energyIndex++; if (energyIndex >= this.energy.Length)
 {
 energyIndex = 0;
 }
 }
 }
 }

 public override int Read(byte[] buffer, int offset, int count)
 {
 int retVal = this.baseStream.Read(buffer, offset, count);
 const double A = 0.3;
 lock (this.syncRoot)
 {
 for (int i = 0; i < retVal; i += 2) { short sample = BitConverter.ToInt16(buffer, i + offset); this.avgSample += sample * sample; this.sampleCount++; if (this.sampleCount == SamplesPerPixel) { this.avgSample /= SamplesPerPixel; this.energy[this.index] = .2 + ((this.avgSample * 11) / (int.MaxValue / 2)); this.energy[this.index] = this.energy[this.index] > 10 ? 10 : this.energy[this.index];

 if (this.index > 0)
 {
 this.energy[this.index] = (this.energy[this.index] * A) + ((1 - A) * this.energy[this.index - 1]);
 }

 this.index++;

 if (this.index >= this.energy.Length)
 {
 this.index = 0;
 }

 this.avgSample = 0;
 this.sampleCount = 0;
 }
 }
 }

 return retVal;
 }

 public override long Seek(long offset, SeekOrigin origin)
 {
 return this.baseStream.Seek(offset, origin);
 }

 public override void SetLength(long value)
 {
 this.baseStream.SetLength(value);
 }

 public override void Write(byte[] buffer, int offset, int count)
 {
 this.baseStream.Write(buffer, offset, count);
 }
 }
 #endregion

public MainWindow()
{
 InitializeComponent();

 kinect = KinectSensor.KinectSensors[0];

 if (this.kinect != null)
 {
 this.InitializeKinect();
 }
}

 private void Start()
 {
 var audioSource = this.kinect.AudioSource;
 audioSource.BeamAngleMode = BeamAngleMode.Adaptive;

 audioSource.EchoCancellationMode = EchoCancellationMode.CancellationAndSuppression;
 var kinectStream = audioSource.Start();

 this.stream = new EnergyCalculatingPassThroughStream(kinectStream);
 this.speechRecognizer.SetInputToAudioStream(this.stream, new SpeechAudioFormatInfo
 (EncodingFormat.Pcm, 16000, 16, 1, 32000, 2, null));
 this.speechRecognizer.RecognizeAsync(RecognizeMode.Multiple);
 }

 private static RecognizerInfo GetKinectRecognizer()
 {
 Func<RecognizerInfo, bool> matchingFunc = r =>
 {
 string value;
 r.AdditionalInfo.TryGetValue("Kinect", out value);
 return "True".Equals(value, StringComparison.InvariantCultureIgnoreCase) &&
 "es-ES".Equals(r.Culture.Name,StringComparison.InvariantCultureIgnoreCase);
 };
 return SpeechRecognitionEngine.InstalledRecognizers().Where(matchingFunc).FirstOrDefault();
 }

 private SpeechRecognitionEngine CreateSpeechRecognizer()
 {
 RecognizerInfo ri = GetKinectRecognizer();
 if (ri == null)
 {
 MessageBox.Show(@"Hay un problema al inicializar el dispositivo de reconocimiento de voz.
 asegurese de tener Microsoft Speech SDK instalado y configurado.",
 "Falla al cargar Speech SDK", MessageBoxButton.OK, MessageBoxImage.Error);

 this.Close();
 return null;
 }

 SpeechRecognitionEngine sre;
 try
 {
 sre = new SpeechRecognitionEngine(ri.Id);
 }
 catch
 {
 MessageBox.Show(@"Hay un problema al inicializar el dispositivo de reconocimiento de voz.
 asegurese de tener Microsoft Speech SDK instalado y configurado.", "Falla al cargar Speech SDK",
 MessageBoxButton.OK, MessageBoxImage.Error);
 this.Close();
 return null;
 }

 var colors = new Choices();
 colors.Add("rojo");
 colors.Add("verde");
 colors.Add("azul");
 colors.Add("amarillo");

 var gb = new GrammarBuilder { Culture = ri.Culture };
 gb.Append(colors);

 // Create the actual Grammar instance, and then load it into the speech recognizer.
 var g = new Grammar(gb);

 sre.LoadGrammar(g);
 sre.SpeechRecognized += this.SreSpeechRecognized;
 sre.SpeechHypothesized += this.SreSpeechHypothesized;
 sre.SpeechRecognitionRejected += this.SreSpeechRecognitionRejected;

 return sre;
 }

 private void RejectSpeech(RecognitionResult result)
 {
 string status = "Rechazado: " + (result == null ? string.Empty : result.Text + " " + result.Confidence);
 this.ReportSpeechStatus(status);

 Dispatcher.BeginInvoke(new Action(() => { tbColor.Background = WhiteBrush; }), DispatcherPriority.Normal);
 }

 private void SreSpeechRecognitionRejected(object sender, SpeechRecognitionRejectedEventArgs e)
 {
 this.RejectSpeech(e.Result);
 }

 private void SreSpeechHypothesized(object sender, SpeechHypothesizedEventArgs e)
 {
 this.ReportSpeechStatus("Hipotetico: " + e.Result.Text + " " + e.Result.Confidence);
 }

 private void SreSpeechRecognized(object sender, SpeechRecognizedEventArgs e)
 {
 SolidColorBrush brush;

 if (e.Result.Confidence < 0.7) { this.RejectSpeech(e.Result); return; } switch (e.Result.Text.ToUpperInvariant()) { case "ROJO": brush = this.redBrush; break; case "VERDE": brush = this.greenBrush; break; case "AZUL": brush = this.blueBrush; break; case "AMARILLO": brush = this.yellowBrush; break; default: brush = this.WhiteBrush; break; } string status = "Reconocido: " + e.Result.Text + " " + e.Result.Confidence; this.ReportSpeechStatus(status); Dispatcher.BeginInvoke(new Action(() => { tbColor.Background = brush; }), DispatcherPriority.Normal);
 }

 private void ReportSpeechStatus(string status)
 {
 Dispatcher.BeginInvoke(new Action(() => { tbSpeech.Text = status; }), DispatcherPriority.Normal);
 }

 private void UpdateInstructionsText(string instructions)
 {
 Dispatcher.BeginInvoke(new Action(() => { tbInfo.Text = instructions; }), DispatcherPriority.Normal);
 }

 private void MainWindowClosing(object sender, System.ComponentModel.CancelEventArgs e)
 {
 this.UninitializeKinect();
 }

 private void ReadyTimerTick(object sender, EventArgs e)
 {
 this.Start();
 this.ReportSpeechStatus("Listo para reconocer voz!");
 this.UpdateInstructionsText("Diga: 'rojo', 'verde', 'amarillo' o 'azul'");
 this.readyTimer.Stop();
 this.readyTimer = null;
 }

 private void InitializeKinect()
 {
 var sensor = this.kinect;
 this.speechRecognizer = this.CreateSpeechRecognizer();
 try
 {
 sensor.Start();
 }
 catch (Exception)
 {

 }

 if (this.speechRecognizer != null && sensor != null)
 {
 // NOTE: Need to wait 4 seconds for device to be ready to stream audio right after initialization
 this.readyTimer = new DispatcherTimer();
 this.readyTimer.Tick += this.ReadyTimerTick;
 this.readyTimer.Interval = new TimeSpan(0, 0, 4);
 this.readyTimer.Start();

 this.ReportSpeechStatus("Inicializando el dispositivo de audio Kinect...");
 this.UpdateInstructionsText(string.Empty);

 this.Closing += this.MainWindowClosing;
 }
 }

 private void UninitializeKinect()
 {
 var sensor = this.kinect;

 if (this.speechRecognizer != null && sensor != null)
 {
 sensor.AudioSource.Stop();
 sensor.Stop();
 this.speechRecognizer.RecognizeAsyncCancel();
 this.speechRecognizer.RecognizeAsyncStop();
 }

 if (this.readyTimer != null)
 {
 this.readyTimer.Stop();
 this.readyTimer = null;
 }
 }

 }
}

nota: esta entrada esta sujeta a cambios por la actualizacion de la libreria KINECT, luego les seguire comentando acerca de esto, por ahora solo les adelanto este post!…

UPDATE «Novedades liberadas desde Octubre 2012 SDK»

Entre las nuevas cosas que nos viene ahora en esta actualizacion mencionare las mas destacadas y muy utiles para nosotros los desarrolladores.

1) El stream de infrarrojos está ahora expuesto en el API

El sensor Kinect está ahora expuesto como un formato de color de la imagen nueva. Usted puede utilizar el flujo de infrarrojos en muchos escenarios, tales como:

  •      Calibración de otras cámaras de color para el sensor de profundidad de Kinect
  •      La captura de imágenes en escala de grises en situaciones de poca luz
  •      Dos muestras de infrarrojos se han añadido a la caja de herramientas, y también se puede probar de infrarrojos en KinectExplorer. Esto proporciona a los desarrolladores un amplio espectro de escenarios de pruebas.
  •      Tenga en cuenta que el sensor no es capaz de capturar flujos de infrarrojos y corrientes de color al mismo tiempo. Puede, sin embargo, capturar flujos de infrarrojos y la profundidad simultáneamente.

2) Datos profundidad ampliados 

  • CopyDepthImagePixelData() ahora proporciona detalles más allá de 4 metros, por favor, tenga en cuenta que la calidad de los datos se degrada con la distancia. Además de los datos de profundidad extendidos, facilidad de uso de la profundidad del API de datos ha sido mejorada (enmascaramiento de bits ya no se requiere).
  • Esto significa que las aplicaciones serán capaces de leer los datos más allá de 4 metros cuando sea necesario.
3) Configuracion de color en la APIs de la Cámara

  • Los ajustes de color de la cámara ahora puede ser optimizado para su entorno.
  •      Ahora se puede ajustar el balance de blancos, contraste, tono, saturación y otros parámetros, dando una mejor imagen de color para cada usuario individual.
  •      Para ver la lista completa de los ajustes que se pueden optimizar, inicie el Explorador de Kinect desde el navegador Developer Toolkit y revisar la exposición y controles de color.

4) API de datos Acelerómetro

  • Los datos de los acelerómetros del sensor se expone ahora en la API. Esto permite la detección de la orientación del sensor.

5) Nueva API de conversión de coordenadas espacio

  • Existen varias APIs nuevo para convertir datos entre espacios de coordenadas: el color, la profundidad y el esqueleto.
  • Hay dos conjuntos de API: uno para la conversión de los píxeles individuales y la otra para la conversión de un cuadro de imagen completa.
  • Más allá de mejorar la facilidad de uso, este soporta la funcionalidad adicional mapeo de coordenadas previamente no disponibles para los desarrolladores.

6) Kinect Studio 1.6.0

  • Kinect Studio ha sido actualizado para soportar los rayos infrarrojos, raw bayer, datos extendidos de profundidad, y cuenta con acelerómetro.

7) Raw Bayer

  • El nuevo formato de color de imagen raw Bayer que permite hacer tu propia Bayer RGB conversiones de unidades de procesamiento central (CPU) o unidades de procesamiento gráfico (GPU). Esto permite a los desarrolladores elegir una calidad de conversión superior a RGB de Bayer que nuestro SDK proporciona de forma predeterminada.

Si no tienes la minima idea de que es un Bayer, para los que saben de fotografia tambien pueden refrescar su memoria con estos breves conceptos http://es.wikipedia.org/wiki/Mosaico_de_Bayer

Ademas de las amplias funciones destacadas en la nueva actualizacion tambien estan incluidos nuevos soportes de herramientas y compatibilidad en el sistema operativo Windows 8

Soporte para máquinas virtuales
El sensor Kinect para Windows ahora funciona en Windows que se ejecutan en una máquina virtual (VM) y ha sido probado con los siguientes entornos de VM:

  •      Microsoft HyperV
  •      VMWare
  •      paralelas

Esto amplía enormemente la utilidad de la Kinect para Windows SDK, ya que ahora se puede utilizar en cualquier máquina cuyo sistema operativo nativo admite que ejecuta Windows en uno de los paquetes VM mencionadas anteriormente. Además, esto permite varios escenarios de desarrollo, tales como ciertos enfoques de prueba automatizados.

Actualización Kinect Studio
La actualización simplifica la depuracion y comprobación de las aplicaciones mediante el uso de Kinect Studio para grabar, reproducir y depurar los datos de Kinect. Esta versión se ha actualizado para admitir los nuevos infrarrojo, crudo Bayer, datos extendidos de profundidad, y cuenta con acelerómetro.

Soporte para Windows 8
Al utilizar el Kinect para Windows SDK, puede desarrollar una aplicación Kinect para Windows para una aplicación de escritorio en Windows 8.

Soporte para Visual Studio 2012
El SDK es compatible el desarrollo con Visual Studio 2012, además con el soporte de Visual Studio 2010, y el nuevo Microsoft. NET Framework 4.5, además de los ya soportados. NET Framework 4.0. y el ya mencionado soporte para Windows 8

Skeletons?… el desarrollo de una interfaz verdaderamente natural..

Hola una vez mas estoy aca para explicarles a fondo sobre las funciones y nociones basicas para poder desarrollar aplicaciones con este gran dispositivo de interfaz natural de usuario NUI KINECT.

Esta vez hablaremos acerca de Skeletons de una manera teorica, luego posteare un Tutorial basico de trabajo con estas funciones para reconocimiento de personas en una aplicacion…

Entonces veamos un poco que es Skeletons?… Son funciones que nos definen un patron de la anatomia del cuerpo humano reconocido a travez del KINECT para ser colocado dentro las aplicaciones a traves de la libreria de datos dinamica MICROSOFT.KINECT en su version 1.5 al ser esta la mas ultima liberada por Microsoft.Bien para una gran resumen veamos el siguiente grafico..

Joints: de forma mas española es la definicion de coyunturas o extremidades que son partes del cuerpo humano que unen sus extremidades, es esto la base de nuestra definicion de Skeletons en la SDK de KINECT, en la grafica se muestran cada una de sus Joints

Entonces bien esta nueva SDK nos ofrece 2 nuevas funciones añadidas tales como:
Modo de seguimiento del esqueleto en forma sentada
Proporciona la capacidad de rastrear el cuerpo de los usuarios superior (10 Joints), y dan a la parte inferior del cuerpo si no son visibles o relevantes para la aplicación. Además, permite la identificación de usuario cuando se sienta en un objeto de silla, sillón o de otro inanimado.
Mejorar el seguimiento del esqueleto
En el rango cercano, los usuarios que están sentados o de pie, se puede seguir dentro de 40 cm (16 pulgadas) del sensor. Además, el motor de seguimiento del esqueleto es ahora más rápido, hacer un mejor uso de la CPU y la ampliación de los recursos informáticos. Además, la información que acaba de agregar la orientación conjunta de los esqueletos es ideal para escenarios de animación Avatar y la detección sencilla postura.

En el siguiente post empezaremos desde cero con una aplicacion Skeletons para KINECT de una forma bien explicada y portable que podras usar en todas tus nuevas aplicaciones..

Salu2

Tutorial KINECT Hello World en la PC

Hola, en este artículo vamos a explicar y a demostrar conceptos básicos acerca del dispositivo de interfaz natural de usuario o NUI (Natural User Interface) , Microsoft KINECT y explicar brevemente como conectar, inicializar y mostrar las diferentes cámaras y funciones de reconocimiento de gestos a través de este dispositivo con el SDK oficial liberado hace ya unos meses por Microsoft.
Como la mayoría sabemos KINECT es un dispositivo que fue creado por Microsoft en un principio para el entretenimiento a través de la consola XBOX 360, pero este a su vez ha sido un tema a fondo para el uso en diversos aspectos como la investigación académica, la ciencia, para fines empresariales, para nuevas tendencias, etc…
Dejando a un lado la diversión y colocando temas muy serios en cuanto a revolucionar nuestro estilo de vida de cómo interactuar con los sistemas bajo un esquema donde la persona es el ratón o el teclado…
Pero bien basta de charlar y vamos al código, a lo que en verdad quiero demostrarles.
Primero debemos de tener a la mano todo para comenzar:
Hardware:
  • Sensor Microsoft KINECT.
  • Cable conversor de puerto KINECT a USB. (este cable esta incluido cuando compras el KINECT aparte, para la versión que viene con el Xbox 360 no viene con esta extensión, pero se puede conseguir fácilmente en una tienda Microsoft Store o en tiendas electrónicas, Amazon, etc.)
  • PC con 2.66 GHZ de procesador o mucho más rápido con 2Gb de memoria RAM si tienes más, excelente.
  • Microsoft Windows 7 en sus diferentes versiones compatible con tarjetas gráficas con Direct X 9.0c
Software:
Teniendo estos requisitos básicos procedemos primero con la instalación del Microsoft KINECT SDK tal y como se muestra en la siguiente imagen.

 
Ahora bien iniciamos Visual Studio 2010 y creamos un nuevo proyecto de aplicación Windows WPF, yo lo llame HelloWorldKinect, pueden colocarle el nombre que deseen.
Una vez creado el proyecto en el diseñador nos situamos en el codigo XAML y colocamos dos controles de tipo imagen, para este ejemplo solo coloque uno grande que abarque toda la ventana de nombre depthImagenpara la camara de profundidad  y uno pequeño en la parte superior derecha que me mostrara el contenido de la camara de video de nombre videoImage tal como se muestra en la figura.
 En la pestaña de Explorador de Soluciones, hacemos clic derecho en la carpeta References y le damos a la opción Add References y agregamos la referencia Microsoft.Research.Kinect tal como se muestra en las imágenes. Esta parte es importante ya que sin las referencias no podemos iniciar los controles para poder trabajar con nuestro dispositivo KINECT.
 
Si estas en el diseñador solo debes de presionar F7 y estarás en el Code Behind del formulario, nos situamos en la parte superior del código ahora bien debemos de hacer la referencia en el código colocando la siguiente línea tal y como se muestra en la imagen.

 
Debemos de crear una variable de tipo Runtime (esta variable es en si el dispositivo como tal para poder manejar sus diferentes streamsy funciones que nos ofrece la SDK de KINECT) tal y como muestra la imagen.
 
Luego de esto debemos de crear dos eventos ruteados, uno de nombre Loaded y otro Unloaded (esto es porque estos métodos deben de asegurarnos tanto el cargar todo en memoria como el otro para cerrar el dispositivo).
 Así como también debemos de crear dos eventos ruteados para crear y abrir las cámaras del dispositivo como se muestra en la imagen.
Bien ahora en el evento Loaded debemos de inicializar el dispositivo y posteriormente se deben de crear dos rutinas para abrir el dispositivo para poder mostrar los streams de profundidad y el otro de RGB, dándole como variables el tipo de stream, la resolución y el tipo de imagen del stream.
En el evento Unloaded con solo colocar la siguiente rutina este se encargara de cerrar el dispositivo una vez terminada la aplicación.

Como último código propuesto vamos a los dos métodos VideoFrameReadyy DepthFrameReady  crearemos una variable de tipo PlanarImage asignándole lo que nos trae el resultado del evento que siempre está en ejecución mostrando la imagen y después una variable de tipo BitmapSource en la que crearemos a partir del stream correspondiente, pasándole como parámetros, el ancho, el alto, los DPIde cada imagen (por defecto son 96), el formato de sus pixeles en lo que la diferencia de que una es RGB o BGR32 para el video y para profundidad daré una paleta de colores gris de 16 bits o Gray16correspondiente en cada método, luego los bits en memoria a partir de la variable image y por ultimo asignamos todo al control de tipo imagen que habíamos preparado y definido en el diseño de la interfaz.  

Bien nuestro código está listo, ahora solo corremos la aplicación F5 y como buena recompensa nuestro Hello World en KINECT.

Es de resaltar que estos códigos prácticamente son preestablecidos y son primordiales para iniciar el dispositivo y trabajar en conjunto con él para cualquier fin, ya vendrá de parte de Microsoft el ofrecer otras alternativas o mediante otras versiones nuevas de esta SDKmuchas más opciones para programar y trabajar con este dispositivo, es de constar también que esta SDK es de solo desarrollo e investigación ya que no está no fue liberada bajo un perfil comercial o para un fin de lucro, ya veremos en las siguientes versiones.

En mi siguiente entrega les explicare mediante una aplicación definiendo a fondo el uso de las funciones Skeletons a través de sus Joints(coyunturas), y el uso de patrones para reconocer gestos, estos son en sí combinados con profundidad para el diseño de aplicaciones bien interesantes para el uso común, diversión, investigación y afines.
Aca les dejo un enlace para descargar el codigo fuente y el proyecto como tal
http://www.megaupload.com/?d=6QX8U3Y8

Enjoy… Salu2… 😀

El Futuro de Silverlight – Silvelight5

Como bien saben, Silverlight es la plataforma estratégica de Microsoft para desarrollar aplicaciones interactivas a través del escritorio (desktop), el teléfono y el browser. Es por lo anterior, que este producto es de suma importancia para la comunidad de desarrolladores, entusiastas y estudiantes del mundo tecnológico ya que en su siguiente versión incluirá aspectos realmente importantes.

En esta ocasión, se detallaron grandes temas en el ambito del desarrollo en Silverlight y el gran anuncio de Silverlight 5 con su primera version beta que sera liberada para la primavera y la version oficial para Octubre del proximo año,

Llamado Silverlight Firestarter! que tuvo lugar en la ciudad de Redmond Washington pero que se transmitio en vivo para todo el mundo con 3:30 horas de diferencia aca en Venezuela y para el mundo respectivamente. En esta ocasión la conferencia magistral o mundialmente conocido como Key Note, fue impartido por Scott Guthrie quien hablo del futuro de esta importante plataforma y la forma en que le permite a los desarrolladores integrar las diversas pantallas por la que las personas pasan horas conectados a la tecnología, de forma eficiente, dinámica y con una grandiosa experiencia de usuario.

El evento incluyo entrenamientos y laboratorios a través de videos, así como un panel de preguntas y respuestas que se enviaron y fueron contestadas por el equipo de producto de Silverlight en el evento.

¡Un evento para todos!

No importa que no sepas qué es Silverlight, ya que esta es una gran oportunidad de aprender, a través de las sesión general y los laboratorios de entrenamiento que serán impartidos a diversos niveles.

Si ya construyes aplicaciones en Silverlight y conoces de esta gran tecnología, aprenderás lo más nuevo y vanguardista del producto así como el futuro de esta plataforma para comenzar a crear aplicaciones tanto de consumo como de negocio que vayan apagadas a lo más actualizado y funcional para brindar una experiencia de usuario inigualable.

Compartire con ustedes lo que fue la agenda del evento. Una gran oportunidad de aprovechar la tecnología, maximizar los recursos desde el hogar o la oficina y aprender de lo último en tecnología de desarrollo

Todavia puedes ver algunos webcast y videos del evento: http://www.silverlight.net/news/events/firestarter/

Agenda Firestarter Live

Hora Ponente Detalles de la sessión
8:00 am Desayuno
9:00 am Scott Guthrie Scott Guthrie El futuro de Silverlight
10:45 am Jesse Liberty Jesse Liberty Estrategias de Data Binding con Silverlight y WP7
11:30 am Yavor Georgiev Yavor Georgiev Construcción de aplicaciones utilizando REST con WCF y LINQ
12:15 pm Almuerzo
1:00 pm Dan Wahlin Dan Wahlin Construccion de aplicaciones de negocios ricas en caracteristicas de hoy con RIA Services
1:45 pm John Papa John Papa MVVM: Porque y Como? Tips and Patrones usando MVVM y Patrones de servicio con Silverlight WP7
2:45 pm Tim Heuer Tim Heuer Tips and Trucos para una Grandiosa Experiencia de Instalacion
3:30 pm Scott Guthrie Mike Cook &
Jossef Goldberg
Optimización de sus Aplicaciones: Perfiles y Tips de Rendimiento
4:30 pm Jaime Rodriguez Jaime Rodriguez Tips de rendimiento para Silverlight en Windows Phone 7
5:15 pm Fiesta despues del evento!