lunes, 13 de mayo de 2013

Reporte de Proyecto: Detección de Movimiento

Link al Proyecto en Github: https://github.com/synnick/cvision-project/

Presentación:




Propósito 

El propósito del proyecto es la detección de objetos en movimiento en base a técnicas de visión computacional. Dichos objetos son grabados por una cámara, de la cual se extraen frames consecutivos para poder realizar las operaciones.

Justificación

La justificación del proyecto son sus aplicaciones.

La mayoría de ellas relacionadas con seguridad, ya que al poder detectar el movimiento de algun objeto sospechoso, una cámara de seguridad puede hacer acercamientos y tomar/almacenar fotografías, o en cambio puede utilizar dicho movimiento para cambiar su posición, y permitir cubrir un área mayor.

IPS Analytics (2012) IPS Motion Detection. [imagen en línea]
Disponible en: http://www.ips-analytics.com/uploads/media/ips_activity_detection_05.j
pg
También existen aplicaciones en el área de entretenimiento. Una forma más avanzada de simple detección de movimiento para esto, sería el poder seguir los movimientos de un objeto conocido, como las manos o piernas, para poder con ello realizar algún procesamiento en un videojuego como es el caso del dispositivo Kinect de Microsoft.



Kinect Hacks (2011) Kinect BVH Motion Capture. [imagen en líinea] 

Disponible en: http://cdn.kinecthacks.com/wp-content/uploads/2011/09/appscreen1.jpg.


Otra aplicación interesante en el área de cómputo ubicuo y automóviles inteligentes es un dispositivo que permite al automóvil conducirse por si mismo. Esto es posible gracias a una combinación de sensores y cámaras, y por lo menos una de ellas es usada para detectar el movimiento de peatones y objetos diversos para poder además predecir sus desplazamientos y tomar una decisión sobre que hacer (frenar, girar, acelerar, etc).



Vinoth Ragunathan (2011) A look inside Google's "Driverless Car". [video en línea] 

Disponible en: http://www.youtube.com/watch?v=J17Qgc4a8xY.


Descripción Textual


Básicamente, lo que el programa hace es detectar objetos en movimiento en una secuencia de imágenes (video). De estos objetos conoceríamos su posición actual, y anterior (o actual y siguiente, no realmente importa) y en base a ellos, obtener la dirección de movimiento. A continuación se presenta un diagrama para explicar de forma más sencilla el funcionamiento del programa:


Se obtienen dos frames (imágenes) de un video. Estos se usarán para tanto la detección de áreas de movimiento como para el tracking de todo lo que se movió de uno a otro. Primero para la detección de movimiento se hace un pre-procesamiento para eliminar ruido (más información en la siguiente sección). Después se obtiene una diferencia entre esos frames para encontrar los objetos que se movieron, obtenemos sus contornos y a partir de ellos sacamos el área del objeto (zonas de movimiento).

Además con los dos frames se hará el tracking, buscando en el primero características importantes de la imagen (esquinas) y buscando esas mismas características en el segundo frame. De esta forma podemos saber la posición actual y anterior del objeto, y podemos trazar flechas y obtener la dirección de movimiento. Utilizando las zonas de movimiento localizadas anteriormente eliminamos aquellas posiciones obtenidas que no se encuentran dentro de alguna zona de movimiento.

Diseño del Software

El diseño del software es como sigue. El proceso está separado en dos partes principales que es la detección de movimiento y el tracking o rastreo del mismo. Lo demás es procesamiento y tratamiento de los frames para obtener solo lo necesario, que se mencionará dentro de las partes principales. Para cuestiones de ejemplo, se usarán las siguientes dos imágenes (el mismo principio aplica para video):

 
  • Detección de Movimiento

    La parte fundamental del proyecto consiste en detectar movimiento, que en sí cuando pensamos en imágenes es el cambio en los pixeles. Por ejemplo, cuando se tiene una imagen con un fondo constante obtenida de una cámara, y en el siguiente frame se agrega un elemento externo como una manzana sobre ese fondo, nosotros sabemos que hubo un cambio, y la forma de obtener este es substraer la imagen del fondo de la imagen que contiene el objeto. Esto nos dara una mancha de pixeles en las posiciones donde hubo cambio, que naturalmente serán las que cubren al objeto externo que fue introducido en el fondo.

    Esta es la forma más básica, pero cuando pensamos en hacer esto en más de dos frames (es decir un video) las cosas se comienzan a complicar. Para obtener el movimiento en los frames consecutivos de un video es posible realizar lo anterior, PERO existe una gran cantidad de ruido en las cámaras, lo cual causaría que al sustraer la imagen de fondo menos la más actual, haga creer que hubo pequeños movimientos en todos lados de la imagen.

    Afortunadamente ruido de este tipo es gaussiano, lo que hace posible que sea eliminado mediante  un smooth o blur simple. Y para mejorar esto, se hace dicho smoothing no a la imagen de fondo, sino a un promedio obtenido de multiples frames consecutivos para obtener mejores resultados. De esta forma el ruido es mínimo, y podemos trabajar con las manchas mayores que corresponden a los movimientos reales.

    Resultado de la Diferencia

    El siguiente paso es convertir el problema en un problema de decisión: para cada pixel determinar si hubo movimiento o no. Para conseguir esto, teniendo a la imagen anterior primero se le aplica un filtrado a escala de grises, para poder binarizaar más fácilmente

    Resultado de filtro de escala de grises

    Después se aplica un umbral de binarizado para convertir los pixeles de un tono de grises a blancos y todo lo demás a negro, basados en un umbral. Así ahora tendremos manchas totalmente blancas donde hubo movimiento.

    Resultado de la binarización

    Aunque en la imagen anterior no es el caso, regularmente puede haber ruido aun en la imagen binarizada, por lo que se aplica de nuevo un filtro smooth y otro binarizado para eliminar tal ruido.


    Izquierda, aplicacion de smooth, derecha segundo binarizado. Se puede notar que desaparece el pequeño ruido en la esquina inferior derecha.

    Las manchas de los movimientos normalmente no son polígonos ni ninguna figura en específico, sino simple manchas. Para obtener una forma un poco más definida, se obtienen los contornos de TODAS las manchas detectadas anteriormente.

    Contorno de la mancha de movimiento

    Estos contornos corresponden simplemente a sus bordes, y ayudarán a definir un bounding box para cada mancha.

    Esto causa un nuevo problema: un mismo movimiento puede causar pequeñas manchas consecutivas cercanas en vez de una gran mancha definida. Para esto mismo se utilizan las bounding box anteriores. Buscando colisiones en ellas (cuando se sobreponen unas a otras) podemos suponer que fueron causadas por un mismo movimiento, para lo cual se juntan todas las bounding box que tienen colisiones y se hace una combinada, disminuyendo la cantidad de movimientos.

    Imagen final con movimiento localizado

    De esta forma ya podemos detectar todos los movimientos que ocurren en la pantalla, pero no hacia donde se hicieron (dirección orientación). Para ello se utilizan técnicas de rastreo.
  • Rastreo de Movimiento

    Con rastreo de movimiento, me refiero a seguir un objeto que en el paso anterior se detecto en movimiento. Esta técnica requiere mucho menos procesamiento de imágenes, pero debido al algoritmo usado requiere que exista suficiente iluminación en los videos.

    Con un par de frames del video, buscamos en el primero características importantes con la función GoodFeaturesToTrack, y después se buscan estas mismas características en el segundo frame utilizando el algoritmo Lucas Kanade[1], obteniendo las nuevas posiciones y por lo tanto el flujo óptico del movimiento.

    En base a la posición previa y la obtenida con el algoritmo, es posible calcular la dirección del movimiento y de esta forma colocar algún indicador como una flecha hacia donde se está moviendo el objeto.

    He aquí algunas capturas donde se detecta el movimiento de automóviles y motocicletas:



    Nota: Los cuadros blancos, el tag con el tipo de vehículo, y el bounding box blanco no forman parte de mi algoritmo, ya se encontraban en el video que usé (referencias más abajo).

    Como se puede observar, las flechas apuntan en la dirección del movimiento del vehículo, además de que con el método anterior de detección de movimiento se detecta el automóvil.
Librerías

La librería utilizada para el proyecto fue OpenCV para Python por su alta versatilidad y optimización para la manipulación de imágenes y videos. Contiene una gran cantidad de funciones para aplicar diferentes filtros sencillos y algoritmos complejos a las imágenes es como es el caso de:
  • Smooth: Función normalmente ue a diferencia de la primera trabaja con arreglos de numpy).usada para reducir el ruido en las imágenes. Existen diferentes tipos de smoothing con diferentes efectos, pero en este proyecto se usa el Gaussiano.
  • Running Average: Función usada para obtener un promedio de un número determinado de frames, también ayuda a reducir ruido causado por las cámaras.
  • CvtColor: Para pasar una imagen RGB a escala de grises, nada más.
  • Threshold: Función para obtener una imagen binarizada a partir de un umbral.
  • FindContours: Función usada para encontrar los contornos de una imagen binarizada.
  • GoodFeaturesToTrack: Función usada para encontrar características importantes de una imagen(esquinas) para después buscarlas en otra.
  • CalcOpticalFlowPyrLK: Función usada para calcular la nueva posición de características determinadas en una imagen utilizando el algoritmo Lucas Kanade para el flujo óptico.
Se realizó utilizando su primera versión cv (existe la versión cv2 que contiene sintaxis diferente en sus funciones, y trabaja con arreglos numpy).

Evaluación de Desempeño


Todo tipo de aplicación para algún sistema que trabaja con técnicas de visión computacional suele depender de una cosa: tiempo. Un programa de visión computacional que funciona de manera excelente puede ser inservible si en cuestiones de tiempo toma una eternidad en funcionar, en cambio un programa que se desempeña de forma correcta con pocos errores, pero es rápido puede ser una mucho mejor opción.

En el caso del proyecto, se realizaron pruebas, calculando el tiempo aproximado que se tarda el programa en realizar los cálculos de detección de movimiento en diferentes videos con diferentes resoluciones.

Las pruebas se realizaron en una notebook con las siguientes especificaciones:

Procesador: AMD Dual-Core Processor C-50 @ 1.0 Ghz
RAM: 1 GB DDR3
Tarjeta de Video: AMD Radeon HD 6250

El video usado fue:





(2012) Vehicle classification through multiple neural networks. [video en línea] 

Disponible en: http://www.youtube.com/watch?v=IsNLzhu_BKM 
[Fecha de acceso: 13 de Mayo de 2013].

Prueba de Grabado:

Una forma posible de mejorar el desempeño puede ser no mostrar el programa corriendo en vivo, es decir solo realizar los cálculos con los frames y guardar los resultados en un video de salida, sin mostrar las imágenes una por una. Los resultados fueron:

Sin mostrar resultados:
Promedio: 0.148833380858

Mostrando resultados:
Promedio: 0.151357673303


Los desempeños son similares, pero naturalmente el desempeño es mejor cuando no se muestra nada de los procesamientos en tiempo real.

Prueba de Threads

Debido a que los dos bloques principales del programa (Detección de Movimiento, Rastreo de Movimiento) son independientes uno de otro, es decir los calculos de uno no dependen directamente de los cálculos del otro (el orden si importa, debe calcularse la detección de áreas primero) me pareció posible crear un thread para alguno de los dos procedimientos para correr simultaneamente mientras se procesan otros datos.

En este caso, la detección de movimiento corre en una función de forma simultánea al flujo principal del programa. He aquí una comparativa en los tiempos de ejecucion total en cada frame procesado del video.


Promedio: 0.126680270547


Promedio: 0.138897460478


En conclusión, el uso de threads no mejoró el desempeño del programa, emporandolo ligeramente.

Trabajo a Futuro

Ahora mismo, no tengo intención de continuar con el proyecto en ninguna forma, a no ser que en el futuro surja la necesidad de hacerlo. Pensando en esa posibilidad, las futuras mejoras e ideas de que se puede hacer con este proyecto incluyen lo siguiente.
  • Adaptación a cv2. Debido a que cv2 de Python esta mucho menos documentado que cv, decidí realizar el proyecto en éste último. Pero aparentemente, en múltiples comparaciones hechas entre ambos, cv2 es mucho más eficiente que cv, principalmente debido a que trabaja con arreglos de numpy.

    Por lo tanto una posible adaptación a cv2 (probablemente no muy difícil con documentación apropiada)  podría ayudar a mejorar el rendimiento y sería una gran mejora al proyecto.
  • Adaptación con hardware. Me parece posible utilizar este proyecto en conjunto con proyectos que trabajen con cámaras para poder realizar algún procesamiento con el video que graban. Personalmente no me interesa esto por mi poca experiencia en electrónica, pero es una buena área para cualquiera interesado.
  • Aplicaciones de seguridad. Como mencioné al inicio del post, este tipo de proyectos tiene aplicaciones de seguridad. Combinado con una cámara con buena resolución bien colocada, y algún tipo de detección de rostros, debería ser posible hacer zoom al área donde se detecta movimiento y detectar rostros, en caso de que se desea tener una alta seguridad en un área determinada.
  • Aplicaciones científicas: Una aplicación interesante que encontré de este tipo de proyectos de detección de movimientos es el monitoreo de animales. En un experimento, se inyectaban roedores con neurotoxinas, y con una cámara se grababa y almacenaban todos los movimientos que realizaban dentro de su jaula, para buscar patrones o algo en concreto. Otra persona hizo algo similar, pero para monitorear roedores en diferentes iluminaciones. Este tipo de aplicaciones científicas pueden ser un buen acercamiento al uso del proyecto.
Referencias:

2 comentarios:

  1. Bien; falta subir las diapositivas de la presentación aquí a la entrada. 10 pts por la presentación; califico el reporte y el código posteriormente.

    ResponderEliminar
  2. Ojo con la ortografía. 9 pts por el reporte.

    El repositorio está bien; 10 pts.

    ResponderEliminar