Instalando javacvPro para manipular OpenCV 2.3 desde Processing en GNU/Linux Ubuntu y Mint

Introducción

Después de experimentar con la versión 2.1 en Processing que era provistra por ubaa.net he decidido probar con otra diferente ya que esta al parecer ha dejado de ser actualizada.

En este caso estoy probando javacvPro la cual se ve muy prometedora a pesar de que su sitio web y documentación se encuentra escrito en francés.

Requisitos

Es necesario contar los paquetes de la librería OpenCV 2.3 instalados.

Instalación

Descargar la versión mas reciente de la librería desde el siguiente enlace.  Ver la sección Téléchargement.

http://www.mon-club-elec.fr/pmwiki_reference_lib_javacvPro/pmwiki.php

En este caso se utilizó la versión 0.3 disponible actualmente.

Descomprimir el paquete recién descargado.

$ unzip javacvPro-0.3.zip

Crear el directorio para las librerías de Processing (si este aún no existe).

$ mkdir -p ~/sketchbook/libraries

Ubicar la librería en esta ubicación para que esté disponible para Processing.

$ mv javacvPro ~/sketchbook/libraries

Enlaces

Instalando OpenCV 2.3 en GNU/Linux Ubuntu/Mint 12

Introducción

Después de realizar algunas pruebas y experimentos con la versión 2.1 he decidido actualizar la versión de OpenCV a su versión mas reciente (2.3.1 agosto de 2011) para utilizar nuevas librerías mas avanzadas.

Para esto, en lugar de construír la librería desde fuentes, voy a utilizar el repositorio que hábilmente ha creado @gijzelaerr en Launchpad con esta versión.

Instalación

Agregar los repositorios necesarios al sistema operativo.

$ sudo add-apt-repository ppa:gijzelaar/cuda

$ sudo add-apt-repository ppa:gijzelaar/opencv2.3

Actualizar la lista de índices de los paquetes en los repositorios.

$ sudo apt-get update

Instalar el OpenCV y sus dependencias.

$ sudo aptitude install libcv-dev

Enlaces

Detectando movimiento con OpenCV y Processing

Introducción

Una de las características que quería aprender a implementar con OpenCV era la detección de movimiento, esto me permitirá implementar formas de interacción interesantes (y bastante simples de generar) entre el usuario y el sketch a través de la cámara web.

En pocas palabras, la técnica para detectar movimiento que se describe a continuación se basa en generar una imagen monocromática con los píxeles que han cambiado entre dos cuadros del video.  Para hacer esto se siguen los pasos mostrados a continuación.

  1. Obtener una nueva imagen de la cámara web
  2. Invertir la imagen horizontalmente (opcional)
  3. Calcular la diferencia entre la imagen recién obtenida y la almacenada en memoria (recordada)
  4. Procesar la imagen para facilitar su manejo: convertirla a escala de grises, suavizar la imagen y reducir el ruido eliminando los valores demasiado altos o bajos.
  5. Mostrar la imagen de movimiento (opcional)
  6. Recordar la imagen actual para ser procesada nuevamente en la siguiente iteración

opencv.read();

opencv.flip(OpenCV.FLIP_HORIZONTAL);

opencv.absDiff();

opencv.convert(OpenCV.GRAY);

opencv.blur(OpenCV.BLUR, 3);

opencv.threshold(20);

image(opencv.image(), 0, 0);

opencv.remember(OpenCV.SOURCE, OpenCV.FLIP_HORIZONTAL); 

Para verificar si ha sucedido movimiento en una determinada área de la imagen se debe verificar si los píxeles que pertenecen a esa área se encuentran blancos (si hubo) o no.  Esta información se obtiene utilizando el método get(int x, int y) del objeto PImage el cual retorna el color del píxel seleccionado.  Por facilidad se recomienda que se obtenga el brillo (brightness(color)) de este píxel para su comparación.

El siguiente código revisa un área cuadrada de píxeles en búsqueda de movimiento en esa zona.

for(int px=x; px<x+size; px++)  
    for(int py=y; py<y+size; py++)     
        if (px < width && px > 0 && py < height && py > 0)       
            if (brightness(mImage.get(px, py)) > 127)
                count ++;

Screenshot

Imagen de movmiento sobre el objetivo (modo buffer)
Imagen de movmiento sobre el objetivo (modo buffer)

 

Enlaces

Poniendo sombreros a las personas con OpenCV y Processing

Introducción

Como una versión un poco mas elaborada de la publicación anterior he preparado este sketch que toma el flujo de video proveniente de la cámara web,  encuentra en él los rostros de las personas y les pone un sombrero.  Se incluyen diferentes sombreros que pueden cambiarse mediante el teclado.

q – terminar el sketch
a – mostrar/ocultar el rectángulo rojo alrededor de cada cara encontrada
s – mostrar/ocultar la máscara sobre cada cara encontrada
z/x – alternar entre las imágenes de máscaras disponibles

Screenshots

Demostración con varias personas en la misma imagen
Demostración con varias personas en la misma imagen
Demostración con la foto de un rostro
Demostración con la foto de un rostro

Agradecimientos para Martha, Diego y Jennifer Connerlly por participar como modelos para las fotos del artículo.

Acerca de la ubicación de los rostros

Hasta el momento el perfil que mejores resultados me ha dado para ubicar los rostros de las personas ha sido OpenCV.CASCADE_FRONTALFACE_ALT_TREE (haarcascade_frontalface_alt_tree.xml).  Este encuentra los rostros con el menor número de errores (identificación equivocada de un objeto inanimado como si fuera un rostro), sin embargo parece tener poca tolerancia a las variaciones de posición del rostro de las personas, si ellas agachan o rotan un poco la cara probablemente ya no serán renocidas.  Un trabajo a futuro consistirá en encontrar como mejorar estos resultados de la ubicación de rostros.

Estos son los perfiles de reconocimiento disponibles a través de OpenCV según la instalación que se realizó de la librería.

Los siguientes perfiles se encuentran disponibles como constantes asociadas a la clase OpenCV de Processing.

  public static final String CASCADE_FRONTALFACE_ALT_TREE
  public static final String CASCADE_FRONTALFACE_ALT
  public static final String CASCADE_FRONTALFACE_ALT2
  public static final String CASCADE_FRONTALFACE_DEFAULT
  public static final String CASCADE_PROFILEFACE
  public static final String CASCADE_FULLBODY
  public static final String CASCADE_LOWERBODY
  public static final String CASCADE_UPPERBODY

A continuación se listan todos los archivos XML de los perfiles de reconocimiento que también pueden ser utilizados directamente en Processing.

  haarcascade_eye_tree_eyeglasses.xml   
  haarcascade_frontalface_default.xml  
  haarcascade_mcs_eyepair_small.xml  
  haarcascade_mcs_upperbody.xml
  haarcascade_eye.xml                   
  haarcascade_fullbody.xml             
  haarcascade_mcs_lefteye.xml        
  haarcascade_profileface.xml
  haarcascade_frontalface_alt2.xml      
  haarcascade_lefteye_2splits.xml      
  haarcascade_mcs_mouth.xml          
  haarcascade_righteye_2splits.xml
  haarcascade_frontalface_alt_tree.xml  
  haarcascade_lowerbody.xml            
  haarcascade_mcs_nose.xml           
  haarcascade_upperbody.xml
  haarcascade_frontalface_alt.xml       
  haarcascade_mcs_eyepair_big.xml      
  haarcascade_mcs_righteye.xml 

Enlaces

Ubicando caras en una webcam con OpenCV y Processing

Introducción

En este sketch se aprovecha la agilidad para desarrollar en Processing con la facilidad que provee OpenCV para ubicar los rostros de las personas en el flujo de video proveniente de una cámara web.  En este caso el sketch mostrará una cara sonriente cuando se encuentra acompañado por una persona y una cara triste cuando está solo.

Screenshots

Sketch feliz
Sketch feliz

Sketch triste
Sketch triste

Enlaces

Instalación de la librería de OpenCV en Processing bajo GNU/Linux Mint 12

Introducción

En el presente artículo se describirán los pasos necesarios para instalar el software de OpenCV y su correspondiente librería para desarrollar sketches con él utilizando Processing.

Durante el desarrollo de la instalación se utilizó GNU/Linux Mint 12 sin emgbargo el procedimiento debe ser compatible con Ubuntu.

Aviso! La versión de OpenCV que se encuentra en los repositorios del sistema operativo (2.1.0-7build1) es un poco antigua, sin embargo se encontraron problemas para compilar la parte nativa de la librería con una versión mas reciente.  Por este motivo se decidió utilizar la versión disponible y experimentar posteriormente una posible actualización.

Procedimiento

Instalar OpenCV

$ sudo aptitude install libcv-dev libhighgui-dev libcvaux-dev opencv-doc

Instalar la librería de Processing

Nota!  Se recomienda descargar la última versión disponible de la página web del desarrollador.  En este caso se utilizó opencv_01.zip.

Crear el directorio donde se almacenarán las librerías de Processing del usuario.

$ mkdir -p ~/sketchbook/libraries ; cd ~/sketchbook/libraries

Descargar la librería y los ejemplos de la misma.

$ wget http://ubaa.net/shared/processing/opencv/download/opencv_01.zip
$ wget http://ubaa.net/shared/processing/opencv/download/opencv_examples.zip

Descomprimir los paquetes recién descargados

$ unzip opencv_01.zip
$ rm opencv_01.zip
$ unzip opencv_examples.zip
$ rm opencv_examples.zip

Ubicar correctamente el directorio con los ejemplos.

$ mv OpenCV examples/ OpenCV/examples

Recompilar el módulo nativo de la librería

La librería incluye una librería del sistema operativo (libOpenCV.so) enlazada dinámicamente con OpenCV.  La incluída con la distribución de la librería recién instalada fue compilada con versiones anteriores de OpenCV motivo por el cual no se cumplen sus dependencias y en el momento de compilar los sketches se obtiene el siguiente mensaje de error.

!!! required library not found : /home/jimezam/sketchbook/libraries/OpenCV/library/libOpenCV.so: libcxcore.so.1: cannot open shared object file: No such file or directory
Verify that the java.library.path property is correctly set and ‘libcxcore.so’, ‘libcv.so’, ‘libcvaux.so’, ‘libml.so’, and ‘libhighgui.so’ are placed (or linked) in one of your system shared libraries folder

Exception in thread “Animation Thread” java.lang.UnsatisfiedLinkError: hypermedia.video.OpenCV.capture(III)V
    at hypermedia.video.OpenCV.capture(Native Method)
    at hypermedia.video.OpenCV.capture(OpenCV.java:945)
    at sketch_jan12b.setup(sketch_jan12b.java:35)
    at processing.core.PApplet.handleDraw(Unknown Source)
    at processing.core.PApplet.run(Unknown Source)
    at java.lang.Thread.run(Thread.java:662)

Por este motivo es necesario recompilar el módulo nativo con las versiones actuales.  Para hacer esto se deben seguir los siguientes pasos.

$ cd ~/sketchbook/libraries/OpenCV/library/

Crear una copia de seguridad del módulo nativo a recompilarse.

$ mv libOpenCV.so libOpenCV.so.OLD

Generar la cabecera del módulo nativo de Java (JNI).

$ javah -classpath OpenCV.jar -jni hypermedia.video.OpenCV

Recompilar el módulo nativo.

$ g++ -shared ../source/cpp/OpenCV.cpp -o libOpenCV.so -I/usr/include/opencv/ -I/usr/lib/jvm/java-1.6.0-openjdk/include/ -I. -lcv -lhighgui -fPIC

Finalmente se obtienen los siguientes archivos.

$ ls -l

-rw-rw-r– 1 jimezam jimezam  10748 2012-01-12 14:43 hypermedia_video_OpenCV.h
-rwxr-xr-x 1 jimezam jimezam  80088 2009-05-27 13:15 libOpenCV.jnilib
-rwxrwxr-x 1 jimezam jimezam  41953 2012-01-12 16:16 libOpenCV.so
-rwxr-xr-x 1 jimezam jimezam  42861 2009-05-27 13:15 libOpenCV.so.OLD
-rwxr—– 1 jimezam jimezam 515184 2009-05-27 13:15 OpenCV.dll
-rw-r–r– 1 jimezam jimezam  12116 2009-05-27 13:15 OpenCV.jar

Instalar los perfiles de reconocimiento

Los perfiles de reconocimiento son archivos XML donde se estructura el conocimiento que le permite a la librería reconocer rostros sin la necesidad de mayor entrenamiento.  La versión actual de los paquetes de OpenCV en los repositorios instala estos perfiles en una ubicación que no permite que sean utilizados fácilmente desde Processing.  Los siguientes pasos corrígen esta situación.

$ sudo cp -R /usr/share/doc/opencv-doc/examples/haarcascades /usr/share/opencv/
$ sudo gunzip /usr/share/opencv/haarcascades/*.gz

Sketch de prueba

Una vez instalada la librería se podrán desarrollar sketches con ella, a continuación se presenta el sketch mas sencillo posible que muestra la imagen proveniente de la cámara web utilizando OpenCV.

import hypermedia.video.*;

OpenCV opencv;

void setup()
{
  size(640, 480);

  opencv = new OpenCV(this);

  opencv.capture(width,height);
}

void draw()
{
    opencv.read();

    background(opencv.image());
}

Enlaces