3 de febrero de 2013

Exportar gráficas

Muchas de las gráficas que realizamos con matplotlib son usadas como parte de escritos científicos, estadísticos o de cualquier otra índole por lo que en esta entrada veremos como podemos exportar estas gráficas en archivos de imágenes.

La primera opción seria usar el botón guardar que se encuentra en la ventana que se crea al momento de  graficar.


Evidentemente esta es la opción mas fácil si tenemos pocas imágenes para exportar, sin embargo, si queremos realizar operaciones como guardar muchas imágenes, o poner nombres en secuencia, o guardar imágenes sin verlas primero este método no resulta ser muy efectivo. 

Otra forma de exportar una gráfica creada con matplotlib es haciendo uso de la instrucción savefig.

import numpy as np
import matplotlib.pyplot as plt

plt.plot([2, 7, 3, 1, 4])
plt.savefig('imagen.png')

El código anterior nos crea la siguiente imagen con formato png en la misma ruta donde se encuentra el script que utilizamos para crear y guardar la imagen.


Podemos ver como la extensión del archivo es definida junto al nombre de la imagen en un solo string.

De esta manera podemos realizar programas un poco mas complejos como el siguiente


import numpy as np
import random
import matplotlib.pyplot as plt

for i in range(1,11):
    datos = [random.randint(-10,10) for j in range(0,100)]
    #Lista por comprension que genera los datos de cada grafica.
    #Generamos 100 datos aleatorios entre -10 y 10 para cada grafica
    plt.title('Imagen #{0}'.format(i))
    plt.xlabel('Muestras')
    plt.ylabel('Amplitud')
    plt.axis([0, 100, -15, 15]) #[xmin, xmax, ymin, ymax]
    plt.plot(datos)
    plt.savefig('imagen{0}.png'.format(i))
    print 'Imagen {0} lista'.format(i)
    plt.clf() #Quita la figura actual para que no interfiera con la siguiente

El programa anterior genera 10 gráficas cada una con datos diferentes de forma aleatoria y las guarda en disco


La función savefig cuenta con algunos argumentos que pueden ser de ayuda como por ejemplo transparent el cual recibe un valor boleano (True o False) y determina si la gráfica tiene un fondo o es completamente transparente. Esto es especialmente util si se desea insertar la gráfica en una pagina con fondo de algún color y no se quiere dejar la gráfica con un fondo blanco.


plt.savefig('imagen.png', transparent=True)


Imagen transparente sobre un fondo negro

Para mas información sobre los argumentos que puede recibir la función savefig podemos ver la documentación de matplotlib sobre esta.

30 de enero de 2013

Cuadro de etiquetas

En una gráfica es de vital importancia especificar que significa cada una de las lineas que se pueden visualizar. Para esto, vamos a utilizar la función legend la cual nos permite agregar etiquetas a cada una de la lineas que se encuentran en una figura.

import matplotlib.pylab as plt
import numpy as np

x = np.arange(-5,5,0.1)

f1 = np.sin(x)
f2 = np.cos(x)

plt.plot(x,f1, label='seno')
plt.plot(x,f2, label='coseno')

plt.legend()
plt.grid()
plt.show()

Y obtendríamos una gráfica así:


Como podemos ver, en el cuadro se listan las lineas dibujadas con su respectivo color y forma (en el caso  en que hubiéramos puesto lineas punteadas). También observamos que el cuadro con las etiquetas se ubico en la parte superior derecha la cual es la posición por defecto pero como vemos en la siguiente gráfica no siempre es la mejor opción.

Por suerte, podemos elegir la posición en la que deseamos ubicar el cuadro de etiquetas si la posición por defecto no nos convence usando el argumento con palabra clave loc el cual puede tomar los siguientes valores ya sea en forma de cadena de texto o como entero:

Cadena Entero Ubicación
'best' 0 -----> Mejor posición
'upper right' 1 -----> Superior derecha
'upper left' 2 -----> Superior izquierda
'lower left' 3 -----> Inferior izquierda
'lower right' 4 -----> Inferior derecha
'right' 5 -----> Derecha (es la misma que la 7)
'center left' 6 -----> Centro izquierda
'center right' 7 -----> Centro derecha
'lower center' 8 -----> Inferior centro
'upper center' 9 -----> Superior centro
'center' 10 -----> Centro

Según la tabla anterior si queremos que el cuadro de etiquetas se ubique en la parte central superior podemos poner la función legend tanto así

plt.legend(loc='upper center')

Como así

plt.legend(loc=9)

Y obtendríamos el mismo resultado:


De manera alternativa podemos especificar las coordenadas especificas donde queramos que se ubique el cuadro usando una tupla con dos valores entre 0 y 1 de la siguiente manera:

plt.legend(loc=(0.5,0.5))

Como en un semiplano cartesiano, la coordenada (0,0) ubicaría el cuadro en la posición inferior derecha, la coordenada (1,0) lo pondría en la parte inferior derecha por fuera de la gráfica (notese como el referente de ubicación del cuadro es la esquina inferior izquierda del mismo) de lo cual podemos inferir que podemos utilizar coordenadas que se encuentren fuera del rango entre 0 y 1 pero no seria de mucha utilidad.
Gráfica con el cuadro de etiquetas ubicado en la coordenada (1,0)

13 de diciembre de 2012

Etiquetas de los ejes y titulo

Toda gráfica bien hecha debería contar con un titulo y con etiquetas para los ejes, al fin y al cabo, una gráfica es solo un representación de algún tipo de información que permite visualizar los datos de una forma mas adecuada.

Para agregar el titulo a una gráfica hecha en matplotlib usamos la función title de la siguiente manera:

import matplotlib.pylab as plt
import numpy as np

x = np.arange(-5,5,0.1)
y = np.exp(-x)

plt.grid()

plt.axis([-6,6,-0.5,6])
plt.title('Grafica de la funcion exponencial "e^-x"')

plt.plot(x,y)
plt.show()


Lo que le falta a la gráfica para ser mas clara es la etiqueta que identifica los ejes, permitiendo de esta manera interpretar correctamente la imagen. Para agregar las etiquetas usamos las funciones xlabel y ylabel

import matplotlib.pylab as plt
import numpy as np

x = np.arange(-5,5,0.1)
y = np.exp(-x)

plt.grid()

plt.axis([-6,6,-0.5,6])
plt.title('Grafica de la funcion exponencial f(x)=e^-x')
plt.xlabel('X')
plt.ylabel('F(X)')

plt.plot(x,y)
plt.show()

Manejo de los ejes

Matplotlib asigna por defecto el tamaño de los ejes que permite tener una visualización completa de la gráfica. Sin embargo, es posible asignar el valor de los ejes que nosotros deseemos por medio de la función axis( ) del modulo matplotlib.pyplot. La función axis( ) recibe como argumento una lista con los valores de los ejes de la siguiente manera:

[Xmin, Xmax, Ymin, Ymax]

Digamos que queremos realizar la gráfica de seno(x). Para lo cual utilizaríamos el siguiente programa

import matplotlib.pyplot as plt
import numpy as np

x = np.arange(-5,5,0.1)
y = np.sin(x)

plt.grid()
plt.plot(x,y)
plt.show()

Y nos daría como resultado la siguiente gráfica
Aunque se ve toda la gráfica, podríamos obtener un mejor resultado si ampliamos los ejes de la imagen. Para lograr esto simplemente agregamos la función axis con los valores de los ejes que queremos.
import matplotlib.pyplot as plt
import numpy as np

x = np.arange(-5,5,0.1)
y = np.sin(x)

plt.grid()

#La funcion axis recibe una lista con los valores [Xmin,Xmax,Ymin,Ymax]
plt.axis([-6,6,-1.5,1.5]) 

plt.plot(x,y)
plt.show()
Adicionalmente podemos definir solamente los ejes que queremos modificar de la siguiente manera

plt.axis(ymin=1.5, ymax=1.5)


10 de diciembre de 2012

Cuadricula

Cuando realizamos una gráfica con matplotlib el fondo de la misma queda completamente blanco por defecto. En algunas ocasiones, el tener una cuadricula en la gráfica nos permite ver mas fácilmente puntos específicos de  la imagen que solo con el fondo blanco no serian tan evidentes. 

Para agregar una cuadricula a una gráfica con matplotlib basta con agregar la instrucción grid() del modulo matplotlib.pyplot. El siguiente código nos genera una gráfica de las  funciones:


import matplotlib.pyplot as plt
import numpy as np

x = np.arange(-10,10,0.1)
y1 = x**2
y2 = x + 2

plt.plot(x,y1,x,y2)
plt.show()


Como vemos, la gráfica se ve bastante bien pero no es muy claro observar los puntos de cortes en incluso el eje de la imagen. Para este tipo de casos , el dibujar una cuadricula facilitaría mucho las cosas. El código que realiza la gráfica anterior y dibuja una cuadricula es el siguiente:

import matplotlib.pyplot as plt
import numpy as np

x = np.arange(-10,10,0.1)
y1 = x**2
y2 = x + 2

plt.plot(x,y1,x,y2)
plt.grid()
plt.show()

Adicionalmente podemos usar la función grid() con argumentos ya sea grid(True) para activar la cuadricula o grid(False) para desactivarla

25 de octubre de 2012

Plantilla para crear programas con interfaz gráfica - Kinect SDK

Las aplicaciones que hemos realizado hasta el momento sirven perfectamente para ilustrar los primeros pasos que se deben llevar a cabo en cualquier desarrollo con el Kinect. Sin embargo, para aprovechar completamente las capacidades del Kinect es mucho mejor realizar programas que cuenten con una interfaz gráfica.

La gran mayoría de los programas que realizamos con el Kinect y C# tienen la misma estructura por lo que en esta entrada vamos a ver como crear la base de todos los programas que vamos a realizar.

1. Vamos a abrir  Microsoft Visual C# 2010 Express (cualquier versión de Visual Studio servirá pero uso la express porque es gratuita). Vamos a Archivo / Nuevo Proyecto. Esto abrirá una ventana en la seleccionamos "Aplicación WPF" y le damos cualquier nombre (en mi caso le puse "plantilla").

Como ya había dicho en una entrada anterior podemos realizar programas de consola, windows forms, y WPF (Windows presentation foundation) pero por su facilidad de describir la interfaz gráfica por medio de un lenguaje de marcado como lo es XAML es mejor trabajar con aplicaciones WPF.


Al darle aceptar nos va a crear dos pestañas. Una llamada MainWindow.xaml que contiene el XAML que describe la interfaz gráfica, en este caso, una ventana vacía. La segunda pestaña llamada MainWindow:xaml.cs contiene el código en lenguaje C#.

2. Como en los programas anteriores debemos agregar las referencias para poder tener control sobre el Kinect. (Cada vez que sale una nueva versión del Kinect SDK y la instalamos, debemos repetir este paso para que nuestro código siga funcionando)






3. Ahora que nuestro proyecto cuenta con las librerías mínimas necesarias podemos agregar al principio de nuestro programa la instrucción "using Microsoft.Kinect;". Sin ninguna cosa extra, nuestro código en el archivo MainWindow.xaml.cs debería ser así:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using Microsoft.Kinect;

namespace Plantilla
{
    /// 
    /// Lógica de interacción para MainWindow.xaml
    /// 
    public partial class MainWindow : Window
    {
        public MainWindow()
        {
            InitializeComponent();
        }
    }
}


4. Para interactuar con el Kinect, y como ya lo habíamos hecho en entradas anteriores, creamos una instancia de la clase KinectSensor adentro de la clase MainWindow. Una vez declarado este objeto podemos usarlo en cualquier parte del programa para que el Kinect realice alguna tarea en particular. Vamos a llamar a este objeto miKinect (el nombre puede ser cualquiera). El Kinect SDK puede controlar varios dispositivos Kinect a la vez y la única limitante es la capacidad del computador en el que se ejecuta el programa. Si fuéramos a usar mas de un dispositivo, tendríamos que crear diferentes instancias de la clase KinectSensor para cada uno.

Para declarar miKinect, entramos otra vez a el código fuente del programa que controla la ventana principal.  MainWindow.xaml.cs

Hay que declarar miKinect adentro de la clase MainWindow. De esa forma el programa puede hacer uso de esta variable para controlar el Kinect. Con la declaración de miKinect el código del programa debería lucir similar a este:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using Microsoft.Kinect;

namespace Plantilla
{
    /// <summary>
    /// Lógica de interacción para MainWindow.xaml
    /// </summary>
    public partial class MainWindow : Window
    {
        KinectSensor miKinect;
        
        public MainWindow()
        {
            InitializeComponent();
        }
    }
}

5. Ahora que declaramos nuestra variable miKinect, debemos asignar el Kinect que tenemos conectado a nuestra variable recién creada y esto debe ser realizado en el momento que se inicia el programa, por lo que lo vamos a poner en el método Window_Loaded . Este método es llamado al momento de cargarse la ventana principal cuando el programa es iniciado. Para crear este método vamos a usar las herramientas que nos brinda el Visual Studio realizando los siguientes pasos.

    1. Seleccionamos el diseñador de ventanas.
    2. Vamos a la pestaña eventos
    3. Hacemos doble clic en el evento Loaded



 De esa manera el Visual Studio nos agregara lo siguiente en nuestro código fuente:

        private void Window_Loaded(object sender, RoutedEventArgs e)
        {

        }

Lo que se encuentre dentro de este método se ejecutará al momento de iniciar el programa.

6. Adentro del método que acabamos de crear vamos a asignar nuestra variable miKinect. La clase KinectSensor provee una colección con todos los Kinects conectados en el computador por lo que debemos decirle al programa cual de todos sera el Kinect con el que trabajaremos. Para hacer esto agregamos la siguiente linea en el método Window_Loaded.

miKinect = KinectSensor.KinectSensors[0];

7. Ahora que tenemos un objeto que representa nuestro Kinect podemos comenzar a darle ordenes. Lo primero que hacemos es habilitar el dispositivo y decirle que tipo de datos debe entregarnos. Como esta entrada se trata de crear una plantilla para futuros programas vamos a habilitar los tres tipos de información que nos puede entregar el kinect. La imagen de color, la imagen de profundidad, y el rastreo de esqueleto. Los habilitamos de la siguiente manera:

miKinect.ColorStream.Enable();
miKinect.DepthStream.Enable();
miKinect.SkeletonStream.Enable();

Cada tipo de información que nos envía el kinect viene con unas características por defecto que pueden ser modificadas si pasamos argumentos a la función Enable(). Por ejemplo, las imágenes de color vienen por defecto a una resolución de 640x480 píxeles a una tasa de 30FPS pero podemos obtener imágenes de 1280x960 a 12FPS si activamos el flujo de información de esta manera:

miKinect.ColorStream.Enable(ColorImageFormat.RgbResolution1280x960Fps12);

8. El programa ya esta configurado para entregar los flujos de información disponibles. Sin embargo el programa no sabe que hacer con esta información. Para solucionarlo, debemos crear métodos que se disparen cada vez que el kinect tenga una imagen lista, ya sea de color, de profundidad, datos de esqueleto o las tres al tiempo. Estos métodos son conocidos como manejadores de eventos. En otras palabras, el manejador de eventos de la información a color se va a ejecutar 30 veces por segundo (ya que por defecto el ColorStream es de 30 FPS).

Para crear estos manejadores de eventos vamos a escribir, en el caso del manejador de eventos del ColorStream, lo siguiente:

miKinect.ColorFrameReady +=

y luego presionamos dos veces la tecla TAB. De esa manera el manejador de eventos para el flujo de información que entrega el kinect para las imágenes de color se crea automáticamente. Para crear los otros manejadores deberíamos hacer algo similar:

miKinect.DepthFrameReady +=

y

miKinect.SkeletonFrameReady +=

Por ultimo iniciaremos el flujo de datos del kinect con la linea:

miKinect.Start();

De esta manera nuestra plantilla esta lista para realizar programas complejos. En el caso que no necesitemos algún flujo de información de los que pusimos, se debe borrar todas las que hagan alución a el. Nuestra plantilla debería haber quedado de la siguiente manera:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using Microsoft.Kinect;

namespace Plantilla
{
    /// 
    /// Lógica de interacción para MainWindow.xaml
    /// 
    public partial class MainWindow : Window
    {
        KinectSensor miKinect;
        
        public MainWindow()
        {
            InitializeComponent();
        }

        private void Window_Loaded(object sender, RoutedEventArgs e)
        {
            miKinect = KinectSensor.KinectSensors[0];
            miKinect.ColorStream.Enable();
            miKinect.DepthStream.Enable();
            miKinect.SkeletonStream.Enable();

            miKinect.ColorFrameReady += new EventHandler<ColorImageFrameReadyEventArgs>(miKinect_ColorFrameReady);
            miKinect.DepthFrameReady += new EventHandler<DepthImageFrameReadyEventArgs>(miKinect_DepthFrameReady);
            miKinect.SkeletonFrameReady += new EventHandler<SkeletonFrameReadyEventArgs>(miKinect_SkeletonFrameReady);
            
            miKinect.Start();
        }

        void miKinect_SkeletonFrameReady(object sender, SkeletonFrameReadyEventArgs e)
        {
            throw new NotImplementedException();
        }

        void miKinect_DepthFrameReady(object sender, DepthImageFrameReadyEventArgs e)
        {
            throw new NotImplementedException();
        }

        void miKinect_ColorFrameReady(object sender, ColorImageFrameReadyEventArgs e)
        {
            throw new NotImplementedException();
        }

    }
}

El siguiente video permite ver de una manera mas clara el como se desarrolla esta plantilla que es la base de cualquier proyecto con el kinect.




10 de agosto de 2012

Cambiar angulo de elevación del kinect

En el anterior ejemplo hacíamos uso de la imagen de profundidad del kinect y explicaba que era necesario inicializar las cámaras que se iban a utilizar. El siguiente ejemplo no hace uso de ninguna de las cámaras del kinect por lo que es posiblemente el código mas sencillo que se podría hacer usando el kinect.

Como en el ejemplo anterior, es necesario agregar la referencia del kinect SDK para poder acceder a las funciones que este nos brinda. El código es el siguiente:


using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.Kinect;

namespace ConsoleApplication1
{
    class Program
    {
        static void Main(string[] args)
        {
            //Indicamos que sensor vamos a usar y lo inicializamos
            KinectSensor sensor = KinectSensor.KinectSensors[0];
            sensor.Start();

            while (true) //Ciclo sin fin
            {
                //Imprimimos el angulo actual de elevación
                Console.WriteLine("Angulo actual: " + sensor.ElevationAngle);
                //Solicitamos uno nuevo
                Console.Write("Nuevo angulo: ");
                //Convertimos el numero ingresado por el usuario en entero
                int angulo = Convert.ToInt32(Console.ReadLine());

                // Si el angulo ingresado se encuentra 
                // entre los valores permitidos por el kinect [-27,27]
                // Cambia el angulo de elevacion del kinect por el que fue
                // ingresado. Si el angulo no es valido
                // Muestra un mensaje y no realiza el cambio.
                if (angulo < sensor.MaxElevationAngle && angulo > sensor.MinElevationAngle)
                {
                    Console.WriteLine("Cambiando angulo...");
                    sensor.ElevationAngle = angulo;
                    Console.Clear();
                }
                else 
                {
                    Console.Clear();
                    Console.WriteLine("Angulo no valido, ingrese uno entre -27 y 27");
                }
            }
        }
    }
}

El resultado es una consola que nos indica el valor de inclinación actual del kinect y nos pide un valor nuevo de inclinación. Por las características físicas del kinect este valor de inclinación solo puede estar entre -27 y 27. Ademas debemos tener presente que el valor de inclinación del kinect se mide con respecto a la tierra gracias a su acelerometro interno y no con respecto a su base.



9 de agosto de 2012

Primer programa con el Kinect SDK

Todos los proyectos que realicemos usando el Kinect SDK van a tener varias a cosas en común.

1) Crear un nuevo proyecto

2) Referenciar la librería  Microsoft.Kinect.dll

3) Declarar el namespace del Kinect

Básicamente todos los proyectos que hagamos con el SDK Kinect van a necesitar esos pasos, no importa si estamos haciendo aplicaciones WPF, o aplicaciones Windows Form, un juego XNA o incluso una aplicación de consola.

Para entender correctamente como realizar aplicaciones con el Kinect debemos tener presente que el Kinect es un dispositivo de entrada a nuestro programa. Ademas esta mandando información de color, de profundidad, y de esqueletos todo el tiempo que este conectado y es importante manejar este flujo de datos.

La primera aplicación que vamos a realizar, es un programa de consola. El objetivo del programa es que se nos muestre en consola la información de profundidad que el Kinect entrega.

Para crear una nueva aplicación, abrimos el Visual Studio y creamos un nuevo proyecto de consola.



Una vez creamos el proyecto vamos a encontrarnos con una interfaz similar a esta:


Lo siguiente es referenciar la libreria del SDK Kinect. Hacemos clic derecho en "References" y damos clic en la opción "Agregar referencia"


En la ventana agregar referencia, en la pestaña .NET, buscamos la libreria "Microsoft.Kinect"


Ahora, en la parte de arriba de nuestro código .cs agregamos la linea "using Microsoft.Kinect;" y de esta manera agregamos toda la funcionalidad del SDK Kinect a nuestro proyecto. Ahora ya tenemos nuestro entorno listo para crear nuestro programa.

Vamos a realizar el siguiente código:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
//Incluimos la siguiente linea para decirle al programa que vamos a trabajar
//con la funciones del SDK Kinect
using Microsoft.Kinect;

namespace ConsoleApplication1
{
    class Program
    {
        static void Main(string[] args)
        {
            //Instanciar un objeto sensor de tipo KinectSensor. 
            //El indice "0" indica que es el primer kinect conectado
            KinectSensor sensor = KinectSensor.KinectSensors[0];

            //Inicializar las camaras
            sensor.DepthStream.Enable();
            //Declarar el evento que se ejecuta cuando un cuadro de profundidad
            //este listo para su uso.
            sensor.DepthFrameReady += new EventHandler(sensor_DepthFrameReady);

            //Comenzar a usar el sensor
            sensor.Start();
            //El programa se ejecuta hasta que se presione la tecla espacio
            while (Console.ReadKey().Key != ConsoleKey.Spacebar) { }
        }

        static void sensor_DepthFrameReady(object sender, DepthImageFrameReadyEventArgs e)
        {
            //Asigno a la variable cuadroProfundidad el frame que me entrega el kinect
            var cuadroProfundidad = e.OpenDepthImageFrame();
            //Si el cuadro esta vacio no retorna nada y sale del evento
            if (cuadroProfundidad == null) 
            {
                return; 
            }
            //Creamos un vector del mismo tamaño de los datos de la imagen de profundidad
            short[] datos = new short[cuadroProfundidad.PixelDataLength];
            //Copiamos los datos y los metemos al vector recien creado
            cuadroProfundidad.CopyPixelDataTo(datos);
            //Mostramos en consola el dato numero 1000 de ese vector
            Console.WriteLine(datos[1000]);
        }
    }
}

El kinect nos entrega una imagen de profundidad con unas dimensiones de 640x480 donde cada pixel representa una distancia (desde el kinect hasta el objeto que esta sensando). El kinect entrega esa imagen de profundidad como un vector (cada fila de la imagen una detras de otra en el vector) por lo que tenemos un vector de 307200 posiciones (640*480) cada posición del vector representa un pixel en la imagen de profundidad.

Lo único que hace el programa es mostrar el dato numero 1000 de ese vector cada vez que el Kinect manda una imagen nueva al programa.

18 de mayo de 2012

Instalación paso a paso SDK Kinect

A diferencia de otras opciones de desarrollo como OpenNI o OpenKinect, el SDK de Kinect para Windows es, como su nombre claramente lo indica, solo para Windows. Si bien no soy muy fanático del desarrollo ni uso de Windows, hay que reconocer que el SDK de kinect es la mejor opción para realizar aplicaciones con el kinect, aún con sus restricciones de uso en su licencia gratuita.

Kinect para Windows
El SDK de kinect funciona en Windows 7 para versiones de 32 y 64 bits, ademas cuenta con soporte para la versión actual de Windows 8 (Consumer preview). Los requerimientos de Hardware son los siguientes:

REQUERIMIENTOS DE HARDWARE

- Dual Core de 2.6 GHz o mas rapido
- Un puerto USB 2.0 dedicado (no usar hubs, preferiblemente y por la cantidad de datos que envia el kinect al computador, no tener otro dispositivo USB conectado) 
- 2 GB de RAM
- Un Kinect (Podemos desarrollar con el Kinect para Xbox 360 o con el Kinect para Windows) con adaptador de corriente. (El kinect que viene incluido con los Xbox 360, no incluye este adaptador por lo que se debe conseguir por aparte)

La función de el adaptador de corriente es proveer la energía necesaria para el funcionamiento del dispositivo ademas de adaptar la terminal del cable del kinect a un puerto USB (Cuidado: Aunque la terminal del kinect se parezca mucho a una terminal USB no son compatibles).

Como conectar el adaptador al kinect y luego al puerto USB

Terminal del Kinect el cual no es compatible directamente con un puerto USB

Ademas de los requerimientos de Hardware, para desarrollar con el kinect haciendo uso del SDK de Microsoft, se necesita cumplir los requerimientos de software.

REQUERIMIENTOS DE SOFTWARE

- Windows 7 (32 o 64 bits). El sistema operativo debe correr de manera nativa. El SDK Kinect no funciona si tenemos instalado el Windows en una maquina virtual. 

- Microsoft Visual Studio 2010. (En general sirve cualquier versión pero con la versión Express, la cual es gratuita, se puede desarrollar sin ningún problema)  

Con el SDK de kinect se puede desarrollar tanto en C++, como en Visual Basic (¿Realmente hay alguien que trabaje en visual basic?), y en C#, Siendo este ultimo en el que se ven enfocados los tutoriales oficiales de Microsoft y en realidad la mayoría de la documentación mayoría disponible en Internet.

La versión de Visual C# 2010 express se puede descargar de aquí.

- .Net framework 4.0 (Si es que no esta instalado).

Esos son los dos requerimientos básicos de software para poder comenzar a trabajar, pero existen otros para realizar trabajos mas específicos. Por ejemplo, podemos instalar el XNA para realizar juegos con el Kinect, o el Speech platform de Microsoft para trabajar con el reconocimiento del lenguaje hablado (Solo en ingles). También existe la posibilidad de usar Python por medio del proyecto PyKinect el cual hace parte de las Python Tools for visual studio.

INSTALACIÓN

Si ya cumplimos con los requerimientos necesarios, la instalación debería ser demasiado sencilla. Primero, voy a asumir que no teníamos instalada ninguna de las versiones anteriores del SDK (Beta 1 y Beta 2) ni del Speech Platform, si no es el caso, desinstalamos esas versiones y el driver para luego reiniciar el PC.

- Asegurarse de que el kinect no esta conectado al computador.

- Preferiblemente no tener ningún otro programas abierto (Especialmente Visual Studio).

- Descargamos el instalador desde aquí. Este sirve tanto para arquitecturas de 32 Bits como para las de 64 Bits.

- Abrimos el instalador y una vez la instalación se halla completado satisfactoriamente, conectamos el kinect por medio del adaptador a la corriente eléctrica y al computador por medio del puerto USB que brinda el adaptador.

- Esperamos unos momentos mientras los controladores se cargan automáticamente.

- En esta punto el kinect ya debería funcionar correctamente. Podemos comprobarlo si abrimos el Kinect explorer el cual se instalo con el SDK. En el, podemos encontrar ejemplos de códigos listos para correr o para estudiar su funcionamiento.

Si el driver instalo correctamente, en el kinect podemos ver un LED verde parpadeando, ademas el administrador de dispositivos de Windows debería verse similar a este:



Por otro lado, podemos usar el kinect como un micrófono en cualquier aplicación de Windows.

Si todo esta en orden, estamos listo para comenzar a desarrollar aplicaciones con el Kinect en Windows.

Antecedentes del SDK del Kinect


El Kinect de Microsoft llego para brindar una nueva forma en la que interactuamos con los computadores   por medio de las interfaces naturales de usuario (NUI). A diferencia de los accesorios de las otras consola, el PlayStation Move y el Wii remote, con el Kinect el jugador no debe sostener ningún control en sus manos por lo que el eslogan de "Tú eres el control", con el que Microsoft lo promociona, se cumple a cabalidad. El Kinect contiene 3 tipos de sensores internamente, un sensor de video por medio de una cámara de alta resolución, sensor de sonido con un arreglo de micrófonos, y un sensor de profundidad.   

                                    

El Kinect sostiene actualmente el récord del dispositivo mas vendido en menor tiempo, arrebatandoselo al ipod y al ipad, con mas de 8 millones de unidades en menos de 60 dias después de su lanzamiento en Estados Unidos el 4 de noviembre del 2010.

HACKEANDO EL KINECT 

La historia comienza con Johnny Chang Lee, la persona que hackeo el Wii Remote para implementar un "Finger Tracking" y que posteriormente fue contratado en el proyecto Natal (Nombre clave del proyecto que desarrollaba el Kinect) para trabajar en la parte de reconocimiento de gestos.

Hack del Wii remote  por Johnny Chang Lee

Chang fallo en el intento, trabajando ya en Microsoft, de liberar un controlador publico para el Kinect. En vista de eso, se acerco a AdaFruit, un distribuidor de kits electrónicos de código abierto, para que organizaran un concurso con el fin de hackear el Kinect. El concurso fue lanzado el día del lanzamiento con una recompensa de 1000 dolares y el mismo día, Microsoft saco un comunicado en el que anunciaban que el Kinect tenia la seguridad necesaria para evitar que cualquier persona accediera y manipulara la información que el Kinect brindaba, a lo cual AdaFruit respondió aumentando la recompensa a 2000 dolares.

El 6 de noviembre, dos días después del lanzamiento, un hacker conocido como AlexP fue capaz de controlar el motor del Kinect y leer la información del acelerometro, por lo cual AdaFruit aumento el premio a 3000 dolares haciendo crecer aun mas el interés en la comunidad hacker. 

Video de AlexP mostrando 

El lunes 8 de noviembre del 2010, el mismo AlexP publica un video en el que logra obtener los datos de color y profundidad del Kinect y mostrarlos en pantalla. A pesar de haberlo logrado prefirió no reclamar el premio ya que no deseaba liberar el código de su controlador. El mismo día y en vista de lo ocurrido, Microsoft realizo otro anuncio en el que cambia su actitud de prohibición de las intenciones de hackear el Kinect, ademas, aseguran que el Kinect no había sido hackeado ya que ni su código ni sus partes internas  habían sido modificadas, solamente reconocieron que alguien había creado controladores para usar el Kinect con dispositivos diferentes al Xbox 360. También recomendaban no hacer uso de esos controladores y solo usar el Kinect con el fin para el que fue creado.  

Primer video de AlexP mostrando la imagen de color y de profundidad del Kinect


Al día siguiente, el 9 de noviembre del 2010, AdaFruit publico datos entregados por el Kinect los cuales fueron obtenidos por medio de un analizador USB, el Beagle 480. En ese mismo momento la comunidad recientemente creada, OpenKinect, se puso inmediatamente a trabajar en el desarrollo del controlador haciendo uso de los datos publicados por AdaFruit. Al mismo tiempo, Héctor Martín, un español con estudios en ciencias de la computación, acababa de adquirir el Kinect y comenzó a trabajar usando los datos de Adafruit y en tan solo unas pocas horas había escrito un controlador y una aplicación para visualizar el video y la imagen de profundidad. Este fue el nacimiento de la librería   LibFreenect que actualmente es mantenida por el sitio OpenKinect. La recompensa de AdaFruit fue reclamada en tan solo 7 días después de ser anunciada.

Video de Héctor  Martín en el que muestra su controlador para el Kinect

Desde ese momento y durante todo noviembre, apareció una avalancha de videos en los que muchas personas creaban aplicaciones usando el Kinect. Entre ellas se podían encontrar expresiones artísticas, aplicaciones en robotica, realidad aumentada y muchas otras. A la par, aparecieron sitios web como Kinecthacks.net en los que se recopilaban estos videos. 

Mientras todo esto pasaba, Microsoft permanecía como un simple espectador tal vez porque no previeron todo el potencial que tenia el Kinect en otras áreas diferentes a la de los videojuegos.  

Un mes después del lanzamiento del controlador de Héctor Martín, el 10 de Diciembre del 2010, PrimeSense, la compañía Israelí que posee la patente del sensor de profundidad que tiene el Kinect internamente, anuncio el lanzamiento de sus propios controladores de código abierto ademas de librerías para hacer uso de la información entregada por el Kinect. La principal novedad del anuncio de PrimeSense era la posibilidad de hacer uso del framework OpenNI el cual brinda capacidades de mas alto nivel como el skeleton tracking o rastreo de esqueleto aunque para conseguirlo el usuario tuviera que realizar un pose especifica. Esta nueva característica hizo que muchos de los proyectos realizados con Libfreenect comenzaran a migrar a OpenNI.

Posteriormente, el 17 de junio del 2011, Microsoft lanza Kinect SDK beta al publico bajo una licencia gratuita no comercial. Este SDK solo funcionaba bajo Windows pero en contra parte contaba con características como el rastreo de esqueleto sin pose de inicialización, el soporte para reconocimiento de lenguaje natural, entre otras.

El 1 de febrero de 2012 Microsoft anuncia la salida de la versión final 1.0 con múltiples novedades, como la posibilidad de trabajar con múltiples dispositivos Kinect a la vez, y la salida de una licencia de pago para uso comercial.

El 8 de octubre de 2012 salio la versión 1.6 con novedades como soporte para Windows 8 y visual studio 2012 y acceso a la imagen infraroja, mejoras en el rendimiento, entre otras.




4 de enero de 2012

Subplot

Una gráfica bastante común es en la que se desean mostrar mas de una gráfica (subgráficas). Esto es especialmente útil cuando se quieren evidenciar datos relacionados por lo que las gráficas deben estar juntas pero los ejes de cada gráfica son distintos.

Vamos a ver un pequeño ejemplo:

import matplotlib.pyplot as plt
import numpy as np

def f(t):
    return np.exp(-t) * np.cos(2*np.pi*t)

t = np.arange(0.0, 5.0, 0.01)

plt.subplot(211)
plt.plot(t, f(t))

plt.subplot(212)
plt.plot(t, np.cos(2*np.pi*t))

plt.show()


Resultado del código


En este código aparecen cosas nuevas. La primera de ellas es la definición de un función en Python llamada "f" con un solo parámetro llamado "t". Cuando se llama esta función se quiere evaluar la siguiente función matemática:


La segunda novedad es la función subplot la cual permite escoger el lugar de la ventana en la que se va a poner la gráfica. Subplot necesita 3 argumentos: número de filas, número de columnas, y pos poición en la figura. Este ultimo tiene un rango desde 1 hasta (número de filas por número de columnas). En subplot podemos poner los tres valores como un solo numero siempre y cuando sean menores de 10. Esto quiere decir que subplot(2,1,1) es igual a subplot(211), pero cuando, por ejemplo el número de columnas o filas es mayor a 10, se requiere que las comas sean puestas asi: subplot(10,15,7).

Distribución de un subplot de 2x2
De esta manera podemos realizar gráficas completamente distintas conviviendo en la misma ventana incluso usando ejes con rangos diferentes.


Gráficas multilineas

Muchas veces queremos graficar mas de una función en el mismo plano para poder realizar comparaciones. Matplotlib nos permite realizar esto de una manera muy sencilla.

Para explicarlo mejor voy a mostrarles el primer código:

import matplotlib.pyplot as plt
import numpy as np

pendientes = [2,4,6]
x = np.arange(-10,10,0.01)

y1 = 2*x + pendientes[0]
y2 = 2*x + pendientes[1]
y3 = 2*x + pendientes[2]

plt.plot(x,y1)
plt.plot(x,y2)
plt.plot(x,y3)
plt.show() 

Podemos ver en este código, la manera en que definí 3 funciones (ecuaciones de recta) similares pero con diferente pendiente (una con 2, otra con 4 y otra con 6). También vemos que gráfique las tres funciones usando el mismo x.

El resultado es el siguiente:

Matplotlib se encarga de asignar un colo diferente a cada gráfica para que podamos diferenciarlas fácilmente.
Aunque el último código es correcto existe una forma mas compacta de realizar la gráfica de varias funciones y es simplemente pasarle todos los argumentos a una sola función plot.

import matplotlib.pyplot as plt
import numpy as np

pendientes = [2,4,6]
x = np.arange(-10,10,0.01)

y1 = 2*x + pendientes[0]
y2 = 2*x + pendientes[1]
y3 = 2*x + pendientes[2]

plt.plot(x,y1,x,y2,x,y3)
plt.show() 

Como vemos el código se redujo a escribir una sola función plot con 6 argumentos ( 1x, 1y, 2x, 2y, 3x, 3y).

Matplotlib pone por defecto en la misma gráfica todas las funciones que le pasemos. Esto se debe a que la propiedad "hold" esta activada por defecto (esto significa que mantiene todas las funciones y las gráfica en un solo plano).

Si queremos obtener gráficas en diferentes ventanas debemos decirle a matplolib que estamos graficando figuras diferentes de la siguiente manera:

import matplotlib.pyplot as plt
import numpy as np

pendientes = [2,4,6]
x = np.arange(-10,10,0.01)

y1 = 2*x + pendientes[0]
y2 = 2*x + pendientes[1]
y3 = 2*x + pendientes[2]

plt.figure(1)
plt.plot(x,y1)

plt.figure(2)
plt.plot(x,y2)

plt.figure(3)
plt.plot(x,y3)

plt.show() 

De esa manera, le decimos al programa explicitamente que queremos que grafique en ventanas diferentes y por lo tanto obtenemos gráficas totalmente distintas.

3 de enero de 2012

Primer gráfica con Matplotlib

Una de las grandes ventajas de matplotlib es la facilidad con la que podemos comenzar a realizar gráficas.
La gráfica mas sencilla que podemos realizar es la siguiente:

import matplotlib.pypĺot as plt
plt.plot([3,5,1,6,2])
plt.show()

Con este código obtenemos la siguiente gráfica:


La primera linea importa el sub-modulo pyplot que pertenece a matplotlib y aunque este contiene todas las funciones necesarias para realizar nuestras gráficas no es el único sub-modulo que tiene matplotlib, pero esto lo explicare mas adelante. Luego de importar el modulo le asigno el identificador "plt".

La segunda linea "plt.plot([3,5,1,6,2])" le indica al interprete de Python, que quiero graficar esa lista de valores. Normalmente todas las gráficas contienen mínimo dos conjuntos de valores, uno para el eje X y otro para el eje Y, pero como podemos ver en este ejemplo solo le pasamos una lista. En este caso como solo tiene un único conjunto de valores, la función gráfica el valor con respecto a su posición en la lista. Es decir, que el item con indice 0 en la lista tiene un valor de 3 mientras que el item 1 tiene un valor de 5.

Por ultimo, le decimos a Python que nos muestre la gráfica que acabamos de crear. Este paso puede parecer que no es necesario pero nos daremos cuenta de su utilidad cuando queramos mostrar mas de una función en la misma gráfica.

Ahora vamos a hacer una gráfica asignándole los valores tanto de X como de Y. Primero una sencilla:
  
import matplotlib.pyplot as plt

x = range(10)
y = range(10)

plt.plot(x,y)
plt.show() 
En la anterior gráfica usamos una función propia de Python llamada "range()" con la cual generamos una lista de número enteros. En este ejemplo "x = range(10)" x es una lista de enteros que va desde 0 hasta 9. La función range también permite especificar desde comienza la secuencia y hasta donde termina ademas de poder decidir la distancia entre cada termino (de dos en dos, de tres en tres, etc...).

El siguiente código se vuelve un poco mas complejo:

import matplotlib.pyplot as plt

x = range(0,10,2)
y = [Xn**2 for Xn in x]

plt.plot(x,y)
plt.show()

En este nuevo código cambian solamente dos cosas. La definición de x y la definición de y.
x usa la función "range" de una manera mas elaborada especificando el inicio, el fin, y la distancia entre terminos. En este caso x comenzara en 0 y avanzara en pasos de a 2 hasta llegar a 10 (sin incluirlo).

Para crear y usamos una herramienta Python llamada listas por comprensión. Si tratara de leer esa linea seria algo como: "a cada Xn de la lista x sacarle su cuadrado y guardarlo en la lista y". Las listas por comprensión son una manera muy practica de generar listas a partir de otras.

Este es el resultado del código:

La gráfica esta bien pero tiene un problema y es que tiene muy pocas muestras y por lo tanto no se ve como una curva sino como varias rectas unidas. Aquí es donde podemos hacer uso de numpy y su función "arange".
arange es muy parecida a range con la diferencia de que podemos especificar pasos mas pequeños. Esto quiere decir que en vez de aumentar de 1 en 1, ó 2 en 2 como hacemos con range, podemos aumentar de 0.01 o 0.5, etc.

Este el nuevo código haciendo uso de arange:

import matplotlib.pyplot as plt
import numpy as np

x = np.arange(0,10,0.01)
y = [Xn**2 for Xn in x] 

plt.plot(x,y)
plt.show() 

De esta manera obtenemos una gráfica mas definida al contar con un mayor número de muestras.


27 de diciembre de 2011

Instalación

- Instalando matplotlib en Linux
La instalación de matplotlib en linux varia un poco según la distribución que estemos usando pero en las mas populares podemos hacerlo buscando el paquete python-matplotlib. Para Ubuntu y similares podemos usar:

sudo apt-get install python-numpy python-matplotlib libpng12-0

- Instalando matplotlib en windows
Para instalar matplotlib en windows primero debemos satisfacer sus dependencias basicas. Primero debemos descargar e instalar Python de aquí (versión 2.7.2 ya que matplotlib aun no funciona con Python3). Luego descargamos el instalador de Numpy desde aquí.
Ahora que instalamos las dependencias de matplotlib, procedemos a descargarlo desde aquí eligiendo la versión que aplique a nuestro sistema. En mi caso es matplotlib-1.1.0.win32-py2.7.exe.
Los instalamos y ya deberíamos estar listos.

Nota: La forma mas fácil de tener todo listo en windows es instalando Python (x,y) que ya viene con lo necesario.

- Probando la instalación
Para comprobar que todo fue instalado correctamente entramos a la consola interactiva de Python y tecleamos:

import numpy
print numpy.__version__
import matplotlib
print matplotlib.__version__

Si todo funciona correctamente debería mostrarnos las versiones correspondientes de numpy y de matplotlib que tenemos instaladas.


Si no presenta ningún error y se muestra como en la imagen. Estamos listo para trabajar con Matplotlib.

Formatos de salida

El objetivo de Matplotlib es producir gráficas, pero lo importante es lo que queremos hacer con esas gráficas y básicamente tenemos dos opciones: Visualizarlas para evidenciar y monitorear datos o Exportarlas para usarlas como parte de artículos, documentos, textos y demás.

Si las queremos queremos exportar contamos con dos categorías de imágenes, las rasterizadas y las vectorizadas. Las imágenes rasterizadas son aquellas que podemos encontrar en las paginas web o las que normalmente nos entregan las cámaras digitales. Los formatos mas comunes de imágenes rasterizadas son JPG, PNG, y BMP. Estas imágenes son en esencia una matriz con filas y columnas y cada celda de esta matriz, llamadas píxeles, contiene información del color de la imagen. Este tipo de imágenes son dependientes de la resolución ya que el tamaño de la imagen es definido al momento de la creación de la misma y por este motivo cuando se va a realizar un zoom o modificar el tamaño de la imagen se pierde calidad.

Las imágenes vectorizadas contienen una descripción de la imagen en forma de ecuaciones matemáticas y figuras geométricas básicas ( puntos, lineas, polígonos, formas ). Podemos pensar en este formato como una serie de instrucciones para dibujar la imagen: "Dibujar un punto aquí, dibujar una linea entre dos puntos, etc" por esto las imágenes vectorizadas son independientes de la resolución ya que el programa visualizador de la imagen es el que se encarga de codificarla usando los parámetros de tamaño que se le den. Algunos formatos de imágenes vectorizadas son PDF, EPS, SVG, PS.

¿Que es matplotlib?


Matplotlib es una librería de Python que permite realizar gráficas 2D de excelente calidad. Es multiplataforma y puede ser usada desde scripts o desde la consola de Python.

Podemos definir el objetivo de matplotlib con las propias palabras de su creador John Hunter -- "matplotlib tries to make easy things easy and hard things possible" --


Matplotlib fue creado tomando como base a Matlab por lo que para las personas que han gráficado alguna vez en su vida con Matlab, Matplotlib les va a resultar muy familiar. Podemos exportar nuestras gráficas en los formatos de imágenes mas populares e incluso a formato latex para su inclusión en artículos científicos.


- ¿Si Matplotlib fue creado pensando en Matlab, porqué debería usarlo en vez de usar el mismo Matlab?


Existen varias razones. Es cierto que Matplotlib se baso en Matlab pero específicamente en su facilidad de uso. Matplotlib no trata de ser un reemplazo a Matlab como si lo es Octave. Matplotlib es un librería para Python que permite realizar gráficas brindando múltiples facilidades para lograr ese objetivo. Si queremos realizar gráficas de cualquier tipo y no necesitamos toda la cantidad de toolboxes que vienen con Matlab, matplotlib es justo lo que necesitamos.
Por otro lado, y no menos importante. Matplotlib es una librería libre lo cual quiere decir entre otras cosas que podemos usarla completamente gratis, lo cual es una ventaja de entrada frente a Matlab.