Proyecto Fin de Carrera

Robótica, software y telecomunicaciones.

Llegó la versión 2.3 de OpenCV

En entradas anteriores comentaba los problemas que nos podemos encontrar al usar distintas versiones de OpenCV, cómo la mayoría del código que podemos encontrar en internet es para OpenCV1.x o OpenCV2.0, mientras que en mi caso particular usaba OpenCV2.2, la más actual hace tan sólo unos días, porque la semana pasada se publicó la versión OpenCV2.3.

Dicha versión parece que como las anteriores, mantiene la compatibilidad hacia atrás conla mayoría de las funciones, pero introduce algunos cambios en otras. Pero en principio no habrá mucho problema dada la aceptación que tienen las nuevas versiones de esta potente librería de computación gráfica, en una semana sólo se ha descargado 50 veces, y la mayoría de esas descargas son la versión de Windows.

Yo por mi parte no perderé el tiempo en actualizar todo mi código a esta nueva versión, pero sí que la tendré en cuenta para futuros proyectos.

Podéis descargarla en el siguiente enlace: http://sourceforge.net/projects/opencvlibrary/files/opencv-unix/2.3/

11 julio 2011 Posted by | all | | Deja un comentario

Algoritmo Predator — OpenTLD

Hace unos días leía en el Grupo de discusión de OpenKinect sobre un algoritmo de tracking(rastreo o seguimiento) revolucionario conocido como Predator Algorithm.

Predator usa una combinación de tracking + detección + ROI (Region Of Interest), y como sus autores comentan, el algoritmo aprende sobre la marcha.

En primer lugar debemos tener una captura del objeto a seguir, que se puede indicar en el momento que iniciamos el algoritmo, posteriormente escaneará cada frame buscando similitudes con el objeto que debe seguir, un vez se detectan objetos similares, se toman capturas de estos y se añaden en la base de datos, mientras tanto vamos obteniendo más y más capturas en la base de datos, se analizan las capturas y se clasifican como positivas o negativas en base a una restricciones que nosotros queramos, por ejemplo una ROI.

Cuando se tiene un número considerable de capturas, automáticamente descartamos las que aparecen con menos probabilidad, tanto de las negativas como de las positivas, creando un método muy robusto que “va aprendiendo” y mejorando.

En el siguiente vídeo se puede ver varias demostraciones de su potencial:

Pues bien, a los pocos dias se publicó el código con licencia GPLv3, lo que ha aumentado las espectativas sobre este nuevo algoritmo, ya que de este modo es posible que se porte a diversos entornos y entre todos podamos mejorarlo.

De momento se ha creado otro Grupo de Discusión  para OpenTLD, ya que el algoritmo Predator también se conoce como TLD (Tracking+Learning+Detection), y en dicho grupo ya hay gente con ganas de portarlo a GNU/Linux y MacOSX.

Uno de los mayores problemas de Predator es que hasta ahora sólo funciona bajo Windows con Matlab 2009a y archivos MEX, en el grupo de discusión comentaban sobre eliminar la dependencia con MatLab y pasarse a Octave.

También se puede encontrar más información en la página de uno de los desarrolladores.

14 abril 2011 Posted by | all | , , , , , , , , | Deja un comentario

Documentación de OpenCV 2.2

Hasta ahora no había encontrado la documentación de OpenCV 2.2 y estaba usando la disponible para OpenCV 2.1, pensando que la nueva aún no estaría disponible por encontrarse en desarrollo. Sin embargo parece ser que no es así, sino que por algún motivo la documentación de OpenCV 2.2 se encuentra en la página con el dominio de Japón, es la siguiente:

http://opencv.jp/opencv-2.2_org/cpp/index.html

12 abril 2011 Posted by | all | | Deja un comentario

Filtrando con OpenCV2.2

Como he comentado en otras entradas, en OpenCV2.2 se trabaja con Mat en lugar de las típicas IplImage o cvMat, por lo que la mayoría de la documentación existente que hace referencia a estas clases no nos sirve.

En ese caso, lo mejor es buscar la forma de hacer lo que necesitemos desde la documentación de OpenCV.

Hasta el momento he conseguido realizar un suavizado (blur) usando el filtro de mediana y una binarización por umbral (threshold), los cuales se pueden observar en la siguiente captura.

El código utilizado ha sido el siguiente:

 cv::cvtColor(imageCVrgb, imageCVrgb, CV_BGR2RGB);
 cv::cvtColor(imageCVrgb,imageCVir,CV_BGR2GRAY);
 cv::medianBlur(imageCVrgb, imageCVrgb, 7);
 cv::adaptiveThreshold(imageCVir, imageCVir, 255, 0, 0, 7, 0);
 imshow("newWindow",imageCVrgb);
 imshow("newWindow2",imageCVir);
 waitKey(2);

Por supuesto, ha sido necesario declarar las variables correspondientes en worker.h y la inicialización de las ventanas en el constructor de worker.cpp.

11 abril 2011 Posted by | all | | Deja un comentario

Cómo usar OpenCV 2.2 en RoboComp

Una de las tareas que me han costado más esfuerzo del esperado es utilizar OpenCV 2.2 en mi componente. Ya en otra entrada explicaba como instalar OpenCV 2.2 en Ubuntu 10.10 y dejarlo preparado para trabajar con RoboComp y las IPP de Intel. Sin embargo, la simple tarea de mostrar la imagen RGB capturada por la Kinect se me ha complicado más de lo esperado.

Antes que nada tenemos que tener en cuenta que OpenCV no está diseñado para trabajar con la Kinect y mucho menos con RoboComp. En cambio OpenCV sí está pensado para capturar imágenes desde webcams, cámaras IP o cámaras Firewire, capturando las imágenes en los formatos IplImage, cvMat o Mat directamente. OpenCV también dispone de una GUI que te permite ver el procesado aplicado a las imágenes.

Entonces, ¿porqué usar RoboComp y QT si OpenCV puede capturar, procesar y mostrar con su GUI? Es cierto que RoboComp tiene un formato de imagen, QT otro y OpenCV otro más, lo que puede resultar engorroso a la hora de programar, pero hay una serie de ventajas en usar Robocomp y QT:

  • La gran ventaja de RoboComp es que si tenemos un componente dedicado a servirnos los datos de un determinado hardware, cualquier componente puede usar ese hardware sin interferencias. Por ejemplo con OpenCV, si un programa está capturando de la cámara, esta queda bloqueada para otros programas. En cambio con RoboComp podríamos usar la misma cámara desde distintos componentes que se ejecuten en distintos ordenadores. Esto no parece ser una gran ventaja cuando el precio de una webcam ronda los 20€, pero es muy útil cuando una Kinect cuesta unos 150€ y no podemos tener una para cada ordenador del laboratorio.
  • Respecto a QT, nos ofrece un abanico de posibilidades muy superior a la GUI de OpenCV, la documentación de QT está mejor estructurada que la respectiva de OpenCV, QT se integra mejor en el sistema operativo, pero la mayor de las ventajas es la facilidad para editar la GUI con QT Designer sin necesidad de escribir un código complejo.

Mis problemas con OpenCV, derivan principalmente del cambio de nomenclatura que están llevando a cabo y a que tienen una forma particular de hacer las cosas.

Por ejemplo, la función para dibujar en una ventana es:

imshow("newWindow",imageCV);

Sin embargo necesitaba escribir lo siguiente para que mostrase la imagen, pues de lo contrario se mostraba la ventana vacía:

imshow("newWindow",imageCV);
waitKey(2);

Otro de los problemas es que OpenCV trabaja en el espacio de color BGR por defecto en lugar del RGB, el resultado es el de la imagen que se muestra a continuación.

Para solucionar esto, debemos escribir lo siguiente tras rellenar la imagen del formato de OpenCV:

cvtColor(imageCV,imageCV,CV_BGR2RGB);

De todos modos, los pasos serían los siguientes:

9 abril 2011 Posted by | all | , , , , | 4 comentarios

OpenCV2.2 con IPP activas en Ubuntu 10.10

Parece ser que se ha dado un salto de OpenCV2.1 (versión en los repositorios oficiales de Ubuntu 10.10) a OpenCV2.2 (última versión estable en los repositorios de WillowGarage -Marzo 2011- ) en cuanto a la forma de trabajar con imágenes. Si bien se guarda la compatibilidad con los formatos anteriores como IplImage o cvMat, a partir de ahora lo ideal sería trabajar con imágenes de la clase Mat, aunque de momento muchas funciones o métodos de OpenCV las admiten por igual como argumento.

Como puede complicarse un poco la instalación de la instalación y puesta a punto de esta versión 2.2 de OpenCV, voy a intentar explicar el método paso a paso para tenerlas configuradas para trabajar con IPP.

Antes que nada, doy por supuesto que tienes instalada la última versión de IPP en Ubuntu, en una entrada anterior explico como instalarlas junto a RoboComp.

  • Descomprimimos el archivo en nuestra carpeta de usuario.
  • Abrimos un terminal y nos desplazamos a la carpeta de OpenCV que se nos ha creado:
cd /home/my_user/OpenCV-2.2.0/
  • Ahora editamos el archivo CMakeLists.txt con nuestro editor favorito, por ejemplo gedit:
gedit CMakeLists.txt
  • Dentro de este archivo tenemos que buscar las siguientes líneas: (*Error:¡ Ver aclaración al final del documento!)
if(IPP_FOUND AND USE_IPP)
message(STATUS "    Use IPP:                   ${IPP_PATH}")
else()
message(STATUS "    Use IPP:                   NO")
endif()
  • Donde vamos a cambiar un NO por un YES en la posición marcada con negrita. Es la línea 1404 del archivo.
  • Guardamos y cerramos gedit y desde la consola (suponemos que estamos en /home/my_user/OpenCV-2.0.0/) ejecutamos:
cmake .
make
sudo make install

Con eso ya tendríamos OpenCV2.2 listo para trabajar con las IPP en Ubuntu 10.10 Maverick.

Para utilizar las recién instaladas en RoboComp, simplemente tenemos que modificar el CMakeLists.txt de nuestro componente (no olvidar borrar el CMakeCache.txt y hacer cmake . antes de compilar con el CMakeLists.txt modificado) y añadir el #include a la cabecera de nuestro worker.h:

  • En CMakeLists.txt de la carpeta mycomponentComp/src/ añadimos lo que está en negrita:
ADD_DEFINITIONS( -Wall -DQT_DLL -DQT_GUI_LIB -DQT_CORE_LIB )
FIND_PACKAGE( Qt4 REQUIRED )
FIND_PACKAGE( OpenCV REQUIRED )
SET( QT_USE_QTGUI TRUE )
SET( QT_USE_QTOPENGL TRUE )
SET( QT_USE_QTXML TRUE )
INCLUDE( ${QT_USE_FILE} )
QT4_WRAP_CPP( MOC_SOURCES ${HEADERS} )
QT4_WRAP_UI( UI_HEADERS ${UIS} )#MODIFICADO LANDER PARA DIBUJAR LA UI

# Specify construction and link process
ADD_EXECUTABLE( leandroComp ${SOURCES} ${MOC_SOURCES} ${RC_SOURCES} ${UI_HEADERS} )
TARGET_LINK_LIBRARIES( leandroComp ${QT_LIBRARIES} ${LIBS} ${OpenCV_LIBS})
  • En worker.h de nuestro componente, inmediatamente encima o debajo de otros #include añadimos la siguiente línea:
#include <opencv2/opencv>

Y ya podemos usar las funciones de OpenCV en nuestro componente. Tener en cuenta que si queremos usar las funciones de OpenCV tendríamos que usar el operador de ámbito de la forma cv::funcionDeOpenCV() o añadir:

using namespace cv;

en la cabecera del worker.h para poder usar las funciones como funcionDeOpenCV(), como explico en esta entrada.

* El punto que está tachado es un error bastante grave, ya que con eso no solucionamos la instalación de OpenCV con IPP, sino que lo único que cambiamos es el mensaje de error cuando al hacer cmake . a OpenCV2.2 y éste no encontrar las IPP, nos dirá que todo está OK aunque en realidad no fuera así. Lo cual, además de no ser la solución, nos conduce a un grave error pensar que OpenCV está usando IPP cuando en realidad no es así.

Buscamos en el CMakeLists.txt las siguientes líneas y las modificamos según el texto rojo:

foreach(v "6.1" "6.0" "5.3" "5.2" "5.1")
    if(NOT IPP_FOUND)
        if(WIN32)
            find_path(IPP_PATH "ippi-${v}.dll"
                PATHS ${CMAKE_PROGRAM_PATH} ${CMAKE_SYSTEM_PROGRAM_PATH}
                DOC "The path to IPP dynamic libraries")
            if(NOT IPP_PATH)
                find_path(IPP_PATH "ippiem64t-${v}.dll"
                    PATHS ${CMAKE_PROGRAM_PATH} ${CMAKE_SYSTEM_PROGRAM_PATH}
                    DOC "The path to IPP dynamic libraries")
            endif()
        endif()
        if(UNIX)
            find_path(IPP_PATH "libippi.so.6.1"
                PATHS ${CMAKE_LIBRARY_PATH} ${CMAKE_SYSTEM_LIBRARY_PATH} ENV ${OPENCV_LOADER_PATH} /opt/intel/ipp/6.1.2.051/ia32/sharedlib
                DOC "The path to IPP dynamic libraries")
            if(NOT IPP_PATH)
                find_path(IPP_PATH "libippiem64t${CMAKE_SHARED_LIBRARY_SUFFIX}.${v}"
                    PATHS ${CMAKE_LIBRARY_PATH} ${CMAKE_SYSTEM_LIBRARY_PATH} ENV ${OPENCV_LOADER_PATH}
                    DOC "The path to IPP dynamic libraries")
            endif()
        endif()

En mi caso tenía instalada la versión 6.1 en 32 bits, pero si tienes una versión posterior tendrías que añadirla en la primera línea de las que comento, por ejemplo añadiendo “7.0” si fuera el caso, después modificar el nombre de archivo libippi.so.6.1 a libippi.so.7.0 (por ejemplo) en caso de la versión de 32 bits o la zona naranja a libippiem64t.so.7.0 en caso de ser de 64 bits. Y después, tal y como destaca la ruta de color rojo, añadir la ruta donde se encuentre el archivo anterior, que en caso de 64 bits sería en la línea siguiente a la que tiene marcado el nombre naranja.

Esta forma es un poco chapucera porque es un método “a mano”, pero de momento parece que funciona. Espero no haber metido la pata esta vez, pero si alguien tiene sugerencias, se admiten todas.

Pido disculpas por los inconvenientes que he podido ocasionar por el error inicial.

1 abril 2011 Posted by | all | , , , | 4 comentarios

Por qué calibrar la Kinect

Hace tiempo publiqué una entrada en la que hablaba del último cambio de rumbo del proyecto, cambio que entre otras cosas me llevaba a usar la kinect. En la siguiente, os contaba sobre la kinect, y los primeros problemas que tenía para hacerla funcionar, pero que finalmente solucioné.

Trabajando con ella conseguí pintar encima de la imagen de la cámara de vídeo en función de la profundidad que detectaba el sistema de infrarojos, y conseguí pintar en otro color, los objetos a determinada distancia y determinado margen de error, todo controlado con unos sliders (barras desplazadoras) de QT4. En otra entrada comentaré lo que he aprendido sobre la GUI con QT4 y el tema de los sliders.

Al observar la imagen resultante por la pantalla se apreciaba claramente un nuevo problema, y era que la imagen de la cámara RGB y la información de profundidad que nos da el sistema infrarojo no coincidían. Se puede apreciar claramente en la siguiente imagen. El error se incrementaba con la distancia, pero una barra vertical derecha sin información de profundidad permanecía constante.

Entonces, tenía que buscar una explicación al problema, y una vez entendido, intentar solucionarlo.

La explicación de la barra vertical derecha puede observarse en la siguiente imagen, se trata de la diferencia del ángulo de visión de ambas cámaras (IR y RGB) y la distancia ente ellas:

En cuanto al otro error es algo más complejo. Por una parte tenemos que entender que existe una traslación entre la imagen de la cámara RGB y de la imagen captada por la cámara IR debido a la separación que hay entre ambas. Por otro lado hay que tener en cuenta que la lámpara IR está desplazada hacia la derecha respecto a la cámara IR, lo que generará una “sombra IR” a la izquierda de cualquier objeto.

En este caso, la cámara infraroja sólo podría ver la cara b.

La traslación entre los ejes focales de las dos cámaras (IR y RGB), se puede calcular a groso modo midiendo la distancia entre las dos cámaras, que nos la podría dar el fabricante. Sin embargo, hay que tenen en cuenta que la precision en la fase de construcción de la Kinect no es perfecta, y por este motivo cada Kinect tiene una traslación específica. Es más, estamos suponiendo que existe una traslación entre los dos ejes focales, pero que estos se mantienen paralelos entre sí, cuando en realidad, por el mismo motivo anterior, cada kinect tiene una desviación característica entre esos dos ejes.

De ahí la necesidad de calibrar cada kinect con la que queramos trabajar.

Hasta ahora he encontrado 2 formas de calibrar las kinects, una que desarrollan desde la gente de ROS(un sistema operativo para robots), y otra que se está desarrollando en el entorno de OpenKinect.

La gente de ROS ha calculado los valores de las matrices de Traslación y Rotación genéricos que podemos encontrarlos aquí.

Por su parte, Nicolas Burrus junto con la comunidad OpenKinect desarrollan un programa llamado RGBDemo para que cada uno calibre su kinect, calculando los valores de las matrices basándose en el método de la calibración de cámaras estéreo de OpenCV. Además están trabajando en añadir características al programa como estabilizador de imagen de profundidad, relleno de huecos predecibles, detección de objetos, tracking humano, etc.

3 marzo 2011 Posted by | all | , , , , | 3 comentarios

Información para programar

La información que podemos obtener en la API de Robocomp, en QTAssistant, o en la wiki de OpenCV es realmente útil y necesaria para mi PFC, sin embargo, tenía la necesidad de obtener de forma resumida la información que necesitaba.

Para casi cualquier tema podréis encontrar en internet unas hojas a modo de chuleta que sintetizan la información necesaria, simplemente buscando en google “cheatsheet tema” o “tema reference” obtendremos muchos enlaces que nos llevan a archivos pdf de pocas páginas.

Yo he estado buscando de los temas relacionados con mi proyecto y me gustaría compartilos con vosotros:

  • ASCII Reference: Muy útil para escribir caracteres ASCII por el terminal, o manipular caracteres.
  • C Reference: Aunque vaya a usar C++, no viene nada mal tener a mano este documento.
  • C++ Reference: Es útil cuando empezamos con C++, luego ya esto te lo conoces como la palma de tu mano.
  • SVN Reference: No sé si ya he mencionado a Subverson antes, pero es un controlador de versiones de código, usamos un servidor en Robolab y también otro en la forja RedIris.
  • OpenCV Reference: De momento es la que mejor me viene, pues no termino de sentirme cómodo con la documentación oficial de OpenCV.
  • LaTeX Reference: Es ideal para mí, ya que quiero documentar todo mi PFC con LaTeX sin haberlo usado anteriormente.
  • UML Reference: En unos de mis primeras entradas publiqué mi intención de usar diagrmas UML para explicar mi código, sé que siempre debería dibujar los gráficos UML antes que generar código, sin embargo me temo que tendré que hacerlo al revés, espero que con la ayuda de este archivo me sea más fácil.

Pero no todo iban a ser chuletas, éstas son sólo un apoyo, el resto se aprende programando, pidiendo ayuda y consejo a compañeros de Robolab y mi tutor del PFC, buscando información en libros, blogs, foros…

A continuación os dejo una lista de libros o manuales que estoy utilizando para aprender:

  • Aprende C++ como si estuviera en primero.
  • Aprende UML en 24 horas.
  • Robocomp for Dummies.
  • Robex and Robocomp: Building intelliget robots.
  • Distribuited Programming with ICE.
  • Metodología para el desarrollo de aplicaciones orientadas a objetos.
  • Programación vanzada en Shell.

27 febrero 2011 Posted by | all | , , , | Deja un comentario

Herramientas de trabajo

Las herramientas que uso para la programación de mi componente son un gran abanico de aplicaciones y librerías que si bien están lejos de formar un TodoEnUno compacto, a la hora de usar estas herramientas uno se siente cómodo trabajando, y se da cuenta que a pesar de ser independientes, trabajan bien juntas.

Las aplicaciones que utilizo son las siguientes:

  • Kdevelop-> Es un IDE (Entorno de Desarrollo Integrado) muy completo y fácil de usar, con él escribo el código y lo compilo. Su opción de autocompletado funciona realmente bien y te ayuda a avanzar mucho más rápido porque no tienes la necesidad de memorizar los nombres de todos los métodos y variables.
  • QTDesigner-> Es un diseñador de GUI (Interfaz Gráfica de Usuario), simplemente tenemos que maquetar nuestra GUI, y QTDesigner nos genera todo el código necesario para que funcione.
  • QTAssistant-> Nos proporciona todo tipo de información sobre las librerías QT, si bien en kdevelop podemos acceder a cierta información sobre las funciones que usamos, QTAssistant nos dará toda la información.
  • Yakuake-> Es un emulador de terminal similar a la consola de comandos del videojuego Quake, se despliega y se contrae a nuestro gusto, es muy configurable y cómodo de usar. Necesito un terminal para la compilación, navegar por los archivos, arrancar y pasar procesos, etc.
  • Gedit-> Normalmente todo el código lo edito con Kdevelop, sin embargo hay veces que es más rápido y cómodo editar con Gedit, por ejemplo los archivos de configuración de ICE.
  • Kile-> Es el programa que estoy empezando a usar para la documentación del PFC. Kile es una especie de IDE para LaTeX.
  • Cmake-> Es un programa de terminal que se encarga de enlazar todos los archivos para que la compilación sea algo muy sencillo. Sigue la configuración indicada en CMakeLists.txt, por eso ese archivo es tan importante.

Las librerías que utilizo son las siguientes:

  • QT4: Son unas librerías muy completas, desarrolladas por TrollTech (ahora es parte de Nokia), en algún sitio he leído que son la equivalencia a las MCF(Microsoft Class Foundation) de Windows en GNU/Linux. Pero lo cierto es que QT tiene soporte en GNU/Linux, Windows y MacOS. El escritorio KDE ha sido desarrollado completamente con las QT, y por esto rápidamente se asocia esta librería a las interfaces gráficas, pero lo cierto es que son mucho más que unas librerías puramente gráficas.
  • STD: Son las librerías estándar de C++, aunque no se puede decir que le doy un gran uso, son muy fáciles de usar, y lógicamente se puede encontrar muchísima información sobre ellas en internet.
  • OpenCV2: Ya he hablado anteriormente de OpenCV, las librerías para el procesamiento de imágenes. Son las librerías que usaré para el núcleo de mi componente, pues con ellas realizaré el traking y la detección.

A parte de lo anterior tengo que lidiar con ICE(la interface de comunicación entre componentes que usa Robocomp), con las herramientas de Robocomp(replayComp, managerComp, etc.), así como todo lo relacionado con la Kinect(Freenect, kinectComp, etc.).

26 febrero 2011 Posted by | all | , , , , , , , , , | Deja un comentario

¿Por dónde empezar?

Seguramente esta pregunta nos la hacemos todos los ingenieros cuando nos llega la hora de comenzar el Proyecto Fin de Carrera (PFC). Una de las cosas que aprendí de la asignatura de Proyectos, es que tener claros los objetivos y planificación del mismo es un punto muy importante si queremos garantizar el éxito. Cambiar de objetivos en mitad del desarrollo es algo muy costoso y muchas veces hasta resulta inviable.

Por este motivo, debemos empezar por ahí, por fijar los objetivos y tomar decisiones que sean claves para el desarrollo del proyecto. Aunque también es cierto que si nos podemos permitir el lujo de probar antes de tomar una elección, esto siempre nos ayudará a decidirnos.
Bien, mi proyecto se basará en OpenCV, estará escrito en C/C++ y ejecutable en la plataforma GNU/Linux.

OpenCV C/C++

Sigue leyendo

14 noviembre 2009 Posted by | Recursos | , , , , | Deja un comentario

A %d blogueros les gusta esto: