miércoles, 18 de abril de 2012

Procesamiento de imagen II: resumen y añadidos

Desde que comenzamos a escribir el blog hemos ido avanzando poco a poco en las tareas de procesamiento de vídeo. Esta entrada sirve de resumen de lo ya visto, pero además añadimos una modificación a nivel del escalado y un par de añadidos posteriores a la etapa de procesamiento.
Este post será actualizado más adelante con imágenes ilustrativas del proceso.

Actualmente, a cada fotograma capturado de 48x48 píxeles se le aplican los siguientes procesos (recordamos que debido a problemas con el tiempo que debía haber entre dos capturas sucesivas, no pudimos hacer la captura a 96x96 como planeábamos inicialmente):

UNO -Filtro de mediana con radio 1 (una explicación más detallada puede consultarse en esta entrada).

DOS -Escalado a la mitad.
Utilizamos un algoritmo equivalente al box filter que ya se explicó, pero esta vez dividiendo por 2 en vez de por 4. La implementación del nuevo escalado está algo menos optimizada; se trata de dos bucles for anidados que recorren la imagen, tomando una columna de cada dos y una fila de cada dos, y para cada pixel considerado llama a una función getUnos, también empleada en el autocalibrado. Dicha función simplemente cuenta el número de pixels a 1 en una imagen, en un parche cuyas coordenadas iniciales y coordenadas finales se pasan por parámetro. Se cuenta por tanto el número de unos en un parche de 2x2 desde el pixel considerado; si hay dos o mas se sustituye el parche por un 1, y si hay menos se sustituye por un 0. La imagen obtenida es por tanto de 24x24.

TRES- Centrado de la imagen en la coordenada vertical.
Para que las imágenes con las que debe trabajar el sistema se parezcan más entre sí y la red tenga más sencillo hacer su trabajo, hemos decidido aplicar un algoritmo de centrado en la coordenada vertical a cada fotograma. El proceso consiste en calcular la coordenada vertical del centro de masas de la imagen, y ver cuánto se desvía del centro real de la imagen. Después se aplica un desplazamiento al fotograma para que ambos centros coincidan. De esta forma nos independizamos de parte de los movimientos del brazo, quedando la imagen siempre centrada verticalmente; pudimos observar que los movimientos verticales, subiendo y bajando la mano, son muy comunes e involuntarios según se van realizando los gestos. Así, mientras la mano quepa verticalmente en el campo de visión de la cámara, la imagen que le llegará a la red neuronal será muy parecida independientemente de la posición vertical de la mano.

CUATRO- Alinear a la izquierda (alignLeft).
Nuestro alfabeto de gestos implica la extensión de uno o más dedos de la mano para la mayoría de los gestos, dando lugar a imágenes "largas" que tienden a ocupar todo el espacio horizontal del campo visual de la cámara. Pero aunque el usuario tiene menos libertad de movimiento en la coordenada horizontal, la variación sí puede llegar a ser significativa, con lo que implementamos un equivalente a un centrado horizontal.
No es posible utilizar el mismo método que para el centrado vertical, basado en el cálculo del centro de masas, dado que no sería efectivo por ocupar el brazo del usuario todo un lado de la pantalla. Hemos recurrido por tanto a otra alternativa:
Dada una imagen, la recorremos desde la izquierda para encontrar la primera columna en la que tengamos imagen de mano (1s). En ese momento, comenzamos a desplazar la imagen columna a columna, de tal forma que la primera columna con 1s quede a la izquierda del todo, la segunda justo al lado, etc. Donde antes estaba la imagen que se ha desplazado, rellenamos con todo 0s.
Obtenemos de esa forma una mano siempre a la izquierda del fotograma, pero con brazo inacabado.
Hacemos notar que el bucle de recorrido de columnas comienza en la columna 1 en lugar de en la cero. Esto es porque, si la mano ocupaba toda la imagen horizontalmente, al buscar el offset a aplicar resultaba ser 0 (en la primera columna ya hay imagen). En este momento copiaba la columna en si misma y después la borraba, con lo que obteníamos imágenes consistentes en todo ceros.
En lugar de hacer uso de estructuras if, simplemente comenzamos a verificar si las columnas contienen imagen a partir de la columna 1. En tal caso podría perderse la primera columna al ocupar una imagen toda la imagen horizontalmente, pero la diferencia no es significativa.

CINCO- Extensión del brazo (armGenerator)
Volvemos a recorrer la imagen, pero ahora desde la derecha en busca de la primera columna que tenga tres unos o más (el grosor del brazo nunca será de menos de 2 pixeles, con lo que si encontramos sólo dos unos o menos en una columna se tratará de ruido). En ese momento la identificamos como brazo, copiamos la columna y realizamos copias de ella en cada columna hacia la derecha hasta llegar al final de la imagen. De esta forma obtenemos un brazo completo que llega hasta el borde del fotograma.
Esto tiene la ventaja adicional de que hasta ahora era necesario arremangarse para utilizar el sistema. Desde este momento, bastará con despejar la muñeca para que el sistema mismo haga la extensión de brazo.

Código de alingLeft y armGenerator.

No hay comentarios:

Publicar un comentario