Archive

Posts Tagged ‘openFrameworks’

Captura exclusiva del video por reacTIVision

Un problema que presenta reacTIVision respecto a ARToolKit, es que al acceder a la cámara desde su propio ejecutable (que se comunicará con nuestra aplicación por medio de un socket) un segundo proceso (nuestra aplicación) no tendría acceso, en principio, a la imagen original por ya estar siendo consumida.

Poder utilizarla podría ser interesante por ejemplo para agregarla a la salida visual de nuestra aplicación, dibujando la interfaz de usuario “aumentada” sobre la imagen capturada original, en caso de no estar usando un proyector. Utilizando ARToolKit esto no es un problema, dado que la herramienta se presenta en forma de una librería cuya funcionalidad se accederá (básicamente) invocando a una función que recibe un frame de imagen como parámetro y devuelve la información sobre la ubicación de los fiducials. En este escenario, la imagen puede utilizarse posteriormente como se quiera.

Por esto, antes de continuar quisimos estudiar la factibilidad de poder acceder a esta imagen también desde nuestra aplicación. Investigando un poco, encontramos software como SplitCam para Windows, que crea una segunda cámara virtual con la misma imagen que captura la original. Si bien podríamos buscar aplicaciones similares para las otras plataformas que intentaremos soportar (Mac OSX, Linux) preferimos encontrar una solución que sea en cierta medida independiente de la plataforma.

Para esto, estudiamos los fuentes del reacTIVision y encontramos el lugar donde la imagen es obtenida de la cámara y comenzada a procesar. La idea sería entonces tomar esa imágen antes de continuar el procesamiento y hacérsela llegar una aplicación externa.

La primer idea fue enviar el frame de video a una aplicación de ejemplo en openFrameworks utilizando OSC, ya que este será el protocolo de comunicación utilizado por los distintos módulos de nuestra aplicación. Para eso, se extendió el addon ofxOSC de openFrameworks para soportar el tipo de datos blob y poder enviar información binaria. Debido a la restricción de tamaño de los paquetes UDP (protocolo sobre el que se implementa OSC en ofxOSC), fue necesario dividir cada frame en una serie de mensajes de OSC enviados por separado, uno para cada línea horizontal de imagen.

El resultado de esta implementación no fue positivo: un gran porcentaje de los paquetes se perdían y los frames llegaban a la aplicación con una velocidad mucho menor (unos 10fps) a la que se generaban:

Fue ahí que hicimos el siguiente cálculo: estábamos intentando enviar 640 * 480 (resolución) * 3 (bytes por pixel en color 24-bits) * 30 (fps) = 26,4 MB/s utilizando los servicios de red. Sin mucha esperanza, hicimos una prueba adicional intentando enviar esa información por TCP y obteniendo resultados también negativos: si bien los paquetes ya no se perdían por ser TCP un protocolo que resuleve este problema, los frames tampoco llegaban en tiempo real.

La tercer alternativa, que finalmente tuvo éxito, fue utilizar memoria compartida entre procesos para hacer una copia del frame obtenido y poder accederlo desde nuestra aplicación. Para esto, se utilizó la librería multi-plataforma POCO (ya incluida en openFrameworks y que agregamos al proyecto de reacTIVision) compartiendo un mismo segmento de memoria entre el módulo reacTIVision (que realizaría la escritura) y nuestra aplicación (que leería la información escrita). La implementación resultó ser eficiente, entregando los frames en tiempo real y prácticamente sin variar la utilización del CPU.