Proyecto Fin de Carrera

Robótica, software y telecomunicaciones.

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:

  • Declarar las variables de OpenCV que vamos a usar en el worker.h:
Mat imageCV;
  • Inicializar en el constructor Worker::Worker(…) de worker.cpp tanto las variables a usar como la ventana:
imageCV.create(imgHeight,imgWidth,CV_8UC3);
namedWindow("newWindow",CV_WINDOW_NORMAL | CV_GUI_EXPANDED | CV_WINDOW_KEEPRATIO );

Inicializamos imageCV con el método create(), pasándole el alto, ancho y tipo de la imagen. CV_8U3C indica que es una imagen de 8 bits de profundidad con valores Unsigned de 3 Canales (Rojo, verde y azul).

Con nameWindow() inicializamos la ventana de OpenCV sobre la que dibujaremos, pasando los parámetros de la siguiente forma: nameWindow(“Nombre de la ventana”, OPCION1 | OPCION2 …) donde las opciones son opcionales, valga la redundancia. En este caso concreto las opciones significan lo siguiente:

CV_WINDOW_NORMAL: Permite al usuario redimensionar la ventana.

CV_GUI_EXPENDED: Permite que se pueda integrar varios widgets en la ventana, como menús, botones o barras.

CV_WINDOW_KEEPRATIO: Evita deformación de la imagen cuando el usuario redimensiona la ventana de OpenCV

  • En el compute() de worker.cpp rellenamos la imageCV con el valor de alguna imagen del formato RoboComp con un memcpy, y seguidamente transformamos el espacio de color de BGR a RGB:
memcpy(imageCV.data, &imageRGB[0], imgHeight*imgWidth*imgChanels);
cvtColor(imageCV,imageCV,CV_BGR2RGB);

Usamos el memcpy de la siguiente forma: memcpy(dirección_del_destino_de_datos, dirección_del_origen_de_datos, cantidad_de_datos_a_copiar). Mientras que la conversión de color la hacemos de la siguiente forma: cvtColor(imagen_CV_origen, imagen_CV_destino, tipo_de_conversión). Como se puede observar el origen y el destino en ambos casos siguen un orden distinto.

  • Por último, también en compute() en worker.cpp, debemos añadir las siguientes líneas para mostrar la imagen en la ventana:
imshow("newWindow",imageCV);
waitKey(2);

 

Anuncios

9 abril 2011 - Posted by | all | , , , ,

4 comentarios »

  1. Hola Leandro;
    Por lo que veo en la versión 2.2 de OpenCV hay unas cuantos cambios. ¿Me sabrías decir si actualizando la versión tendría problemas con algún componente ya creado? Mi versión actual es 2.1

    Saludos

    Comentario por Luismi | 7 junio 2011 | Responder

  2. Hola Luismi,

    En principio no tendrías ningún problema, ya que OpenCV 2.2 es compatible hacia atrás incluso con OpenCV 1.x.

    El único problema que hay es que en OpenCV 2.2, al convivir todas las funciones y los tipos de datos, los nuevos y los viejos, puedes tener problemas al intentar combinarlos.

    Normalmente las funciones viejas se reconocen por tener el prefijo cv que las nuevas no usan, ejemplo:

    Vieja: cvBlur(…)
    Nueva: Blur(…)
    Por este motivo se suele usar el operador de ámbito con las funciones nuevas, por lo que quedaría así:
    cv::Blur(…)

    Comentario por Leandro | 7 junio 2011 | Responder

  3. buenas,
    me podrias decir si es posible capturar las imagenes de una ipcam a la que solo se puede acceder via web, es decir q no se puede acceder por rtp…
    un saudo
    gracias

    Comentario por fermin | 1 junio 2012 | Responder

    • Hola Fermín,

      ¿Te refieres a usar una Cámara IP desde Robocomp? Si es así lo más seguro es que debas modificar el archivo config para que use MPlayer. Por supuesto deberás tener MPlayer instalado y configurado para que lea tu IPcam (supongo que será sencillo pero nunca lo he hecho porque no tengo una Cámara IP).

      Si lo que quieres es trabajar con OpenCV sin robocomp, más de lo mismo, deberás usar MPlayer o Motion para acceder al vídeo, y luego ya crearte el código que reemplace al CameraComp de RoboComp.

      Saludos.

      Comentario por Leandro | 1 junio 2012 | Responder


Responder

Introduce tus datos o haz clic en un icono para iniciar sesión:

Logo de WordPress.com

Estás comentando usando tu cuenta de WordPress.com. Cerrar sesión / Cambiar )

Imagen de Twitter

Estás comentando usando tu cuenta de Twitter. Cerrar sesión / Cambiar )

Foto de Facebook

Estás comentando usando tu cuenta de Facebook. Cerrar sesión / Cambiar )

Google+ photo

Estás comentando usando tu cuenta de Google+. Cerrar sesión / Cambiar )

Conectando a %s

A %d blogueros les gusta esto: