sábado, 13 de abril de 2013

Trabajando con contornos en OpenCV


Nudes with conts. Mike Rubbo


Manejar contornos con soltura es muy importante cuando se hacen trabajos en visión artificial. El contenedor <vector> de la biblioteca estándar facilita mucho el trabajo 


La biblioteca estándar de C++ proporciona una plantilla, denominada vector que se encuentra definida en el espacio de nombres std. La versión de C++ de OpenCV la emplea en numerosas ocasiones, ya sea como vector o como matriz (vector de vectores). Cuando se está trabajando con contornos es imprescindible manejar estos contenedores con soltura.

Por lo general, los contornos que calculamos pueden resultar excesivos, generándonos un gran número que no resultan ser representativos. Las técnicas ya vistas, combinación de  erode y dilate, junto con otras muchas, pueden resolver parte del problema. No obstante, una vez obtenido un conjunto de vectores que representan los contornos, podemos trabajar directamente con ellos. Por ejemplo, la siguiente imagen muestra los contornos obtenidos a partir de una imagen tratada adecuadamente (básicamente transformada en una imagen binaría y tratada con erode y dilate)  :

Nude. Leopold Reutlinger

Como puede comprobarse hay demasiados contornos que no dicen absolutamente nada. Hay varias formas de eliminar estos indeseables conjuntos, la siguiente función ilustra uno de ellos.



 Básicamente consiste en recorrer cada uno de los contornos, empleando para ello un iterador, a continuación se mide la longitud de cada contorno con:



Donde el booleano indica si el contorno es cerrado o abierto (false). De esta manera podemos controlar la longitud de los contornos con  min y max. El resultado, jugando con estas dos variables, es:


Como puede verse hemos eliminado  los pequeños contornos, quedándonos con los ojos, labios, rostro, parte del torso y los brazos, aunque no hemos logrado quitar algunas arrugas del ropaje. Existen otras formas de eliminar contornos, se puede recurrir, por ejemplo, al número de píxeles de cada contorno, para ello emplearemos:





O también, podemos emplear el área de los contornos como discriminador:




 También podemos intentar una combinación de varios criterios, intentando reducir los contornos a los que consideremos más representativos.

3 comentarios:

  1. Este comentario ha sido eliminado por el autor.

    ResponderEliminar
  2. double length;
    int j = 0;
    int h = contours.size() - 1 ;
    for (int i = 0 ; i <= h ; i++)
    {
    if (i==170)
    {
    i = 170;
    }
    length = arcLength(contours[i], false);

    if (length > 100 && length < 500)
    {
    dcontours.resize(j+1);
    dcontours[j] = contours[i];
    j++;
    }

    }

    ResponderEliminar