martes, 10 de abril de 2012

SDK Kinect for Dummies-1

Todos conocemos Kinect, unos lo habréis probado en casa de algún amigo, otros solo lo habéis visto en la tele. Sea como sea Kinect nos puede servir como herramienta de desarrollo y de investigación o simplemente como entretenimiento. Al poco de aparecer Kinect hubo un SDK no oficial para poder emplear Kinect en nuestros PCs. Pasado un tiempo Microsoft lanzó el SDK de Kinect para Windows. Pero en los detalles de hardware o como ha ido evolucionando Kinect no es en lo que me fijaré en el blog. Intentaré orientarme más a la programación.



Ahora viene mi opinión. Pues bien me he puesto con el SDK de Kinect y me gusta. He estado haciendo cosillas con el reconocimiento de voz aunque de momento no tengo material para subir ninguna entrada. Por otra parte como primer paso con el SDK de Kinect veremos como pintar lo que muestra la cámara. Es decir, tan solo la cámara sin Skeleton ni nada por el estilo. 

Necesitamos:
- Visual Studio: versión Express o si somos estudiantes desde www.dreamspark.com
- Sensor Kinect.

Una vez tenemos todo podemos comenzar a familiarizarnos con el SDK de Kinect. Abrimos Visual Studio y creamos un nuevo proyecto: 'WPF application'. Le damos un nombre a nuestro proyecto, en mi caso lo he llamado ejemploKinect.



Una vez agregado el proyecto debemos agregar la referencia de Kinect a nuestro proyecto. Vamos al Solution Explorer y en nuestro proyecto en 'Reference' hacemos clic derecho y seleccionamos 'Add Reference..' y en la pestaña de .NET buscamos la referencia Microsoft.Kinect.



Una vez agregada la referencia debemos ir al "MainWindow.xaml" y agregar un control del tipo imagen. Le cambiaremos el nombre al que queramos y modificaremos su ancho y su alto. Debido a que la imagen de Kinect va a 640x480 recomiendo poner 480 de alto y 640 de ancho. Debido a que no me funciona correctamente el script para subir código mostraré una imagen.









A continuación vamos al .cs asociado a MainWindow. Esto es "MainWindow.xaml.cs". El código esta comentado por tanto no será necesario explicaciones extra. Tan solo apuntar que se debe añadir "using Microsoft.Kinect;"

 
/// 
    /// Interaction logic for MainWindow.xaml
    /// 
    public partial class MainWindow : Window
    {
        KinectSensor miKinect;
        public MainWindow()
        {
            InitializeComponent();
            // Agregamos el evento de carga de la ventana
            Loaded += MainWindowLoaded;
        }

        void MainWindowLoaded(object sender, RoutedEventArgs e)
        {
            // Comprobamos que tenemos un sensor conectado
            if (KinectSensor.KinectSensors.Count > 0)
            {
                //Evento ejecutado al cerrar
                Closing += MainClosing;
                // Escogemos el primer sensor kinect que tengamos conectado. Puede haber más de un kinect conectado
                miKinect = KinectSensor.KinectSensors[0];
                // Habilitamos la cámara elegiendo el formato de imagen.
                miKinect.ColorStream.Enable(ColorImageFormat.RgbResolution640x480Fps30);
                // Arrancamos Kinect.
                miKinect.Start();
                // Nos suscribimos al método
                miKinect.AllFramesReady += KinectAllFramesReady;
            }

        }

        /// 
        /// Obtenemos los frames y los pintamos en la imagen.
        /// 
        /// 
        /// 

        void KinectAllFramesReady(object sender, AllFramesReadyEventArgs e)
        {
            //Obtenemos el frame de imagen de la camara
            using (var colorFrame = e.OpenColorImageFrame())
            {
                // Si este es null no continuamos
                if (colorFrame == null) return;
                // Creamos un array de bytes del tamaño de los pixel del frame.
                byte[] pixels = new byte[colorFrame.PixelDataLength];
                //Copiamos los pixel del frame a nuestro array de bytes.
                colorFrame.CopyPixelDataTo(pixels);
                // Colocamos los pixel del frame en la imagen del xml
                int stride = colorFrame.Width * 4;
                imageKinect.Source = BitmapSource.Create(colorFrame.Width, colorFrame.Height, 96, 96, PixelFormats.Bgr32, null, pixels, stride);
                //imageKinect es el objeto imagen colocado en el xaml
            }
        }

        void MainClosing(object sender, EventArgs e)
        {
            // Al cerrar paramos Kinect
            if (miKinect != null)
            {
                miKinect.Stop();
            }
        }
    }


Y ahora veamos como queda:



Las imágenes se ven como un espejo debido a que Kinect esta preparado para que nosotros nos veamos en él.

Intentaré subir el proyecto proximamente.

7 comentarios:

  1. Gracvias amigo, esto me interesa y es bueno que hayas puesto un ejemplo como este de claro

    ResponderEliminar
  2. muy buen aporte yo tambien acabo de iniciarme a la programacion de mismo

    ResponderEliminar
  3. Muy interesante, un buen inicio para comenzar a programar en Kinect.. gracias por el tuto :)

    ResponderEliminar
  4. namespace WpfApplication1
    {
    ///
    /// Lógica de interacción para MainWindow.xaml
    ///
    public partial class MainWindow : Window
    {
    Microsoft.Kinect. KinectSensor miKinect;
    public MainWindow()
    {
    InitializeComponent();
    // Agregamos el evento de carga de la ventana
    Loaded += MainWindowLoaded;
    }

    void MainWindowLoaded(object sender, RoutedEventArgs e)
    {
    // Comprobamos que tenemos un sensor conectado
    if (Microsoft.Kinect.KinectSensor.KinectSensors.Count > 0)
    {
    //Evento ejecutado al cerrar
    Closing += MainClosing;
    // Escogemos el primer sensor kinect que tengamos conectado. Puede haber más de un kinect conectado
    miKinect =Microsoft.Kinect.KinectSensor.KinectSensors[0];
    // Habilitamos la cámara elegiendo el formato de imagen.
    miKinect.ColorStream.Enable(Microsoft.Kinect.ColorImageFormat.RgbResolution640x480Fps30);
    // Arrancamos Kinect.
    miKinect.Start();
    // Nos suscribimos al método
    miKinect.AllFramesReady += KinectAllFramesReady;
    }

    }

    void KinectAllFramesReady(object sender, Microsoft.Kinect.AllFramesReadyEventArgs e)
    {
    //Obtenemos el frame de imagen de la camara
    using (var colorFrame = e.OpenColorImageFrame())
    {
    // Si este es null no continuamos
    if (colorFrame == null) return;
    // Creamos un array de bytes del tamaño de los pixel del frame.
    byte[] pixels = new byte[colorFrame.PixelDataLength];
    //Copiamos los pixel del frame a nuestro array de bytes.
    colorFrame.CopyPixelDataTo(pixels);
    // Colocamos los pixel del frame en la imagen del xml
    int stride = colorFrame.Width * 4;
    imageKinect.Source = BitmapSource.Create(colorFrame.Width, colorFrame.Height, 96, 96, PixelFormats.Bgr32, null, pixels, stride);
    //imageKinect es el objeto imagen colocado en el xaml
    }
    }

    void MainClosing(object sender, EventArgs e)
    {
    // Al cerrar paramos Kinect
    if (miKinect != null)
    {
    miKinect.Stop();
    }
    }
    }
    }


    codigo en vb2012

    ResponderEliminar
  5. gracias por el tutorial está muy bien explicado¡¡

    ResponderEliminar
  6. Hola soy nuevo en C# y no entiendo porque el código me arroja estos errores

    Error 1: The name 'InitializeComponent' does not exist in the current context
    Error 2: The name 'imageKinect' does not exist in the current context

    ResponderEliminar
    Respuestas
    1. InitializeComponent inicializa los componentes de la interfaz gráfica. imageKinect es el objeto Image de la interfaz. Parece que no estás accediendo al .cs asociado al .xaml de la interfaz.

      Eliminar