2011-06-12 17 views
15

Estoy escribiendo una pequeña aplicación para detectar formas. Lo que tengo que hacer en primer lugar es encontrar la forma más significativa en una imagen. Comencé con algunos procesos previos, incluida la conversión de imágenes a escala de grises, umbralización y detección de bordes. Imagen antes y después de estas operaciones se presenta a continuacióndetección de formas - aproximación del contorno con OpenCV

Antes

enter image description here

Después

enter image description here

Así como se puede ver la forma principal es visible (sin embargo, es un poco dispersa) y también hay algunos ruidos (árboles pequeños, etc.). Lo que tengo que hacer es extraer de alguna manera solo la forma más significativa (la más grande); en este caso, es una torre. Lo que quería hacer es usar la función de búsqueda de contorno en opencv y de alguna manera aproximar las conturs encontradas con el polígono. Luego, (de alguna manera) calcularía el área de los condados y seleccionaré solo el más grande. Hasta ahora me manejadas (sólo) para encontrar contornos usando

cvFindContours(crated,g_storage,&contours); 

Sé que hay una función

cvApproxPoly 

, sin embargo yo no soy capaz de conseguir cualquier información útil para el resultado de esta función . Podría alguien decirme si es posible calcular el área del contorno o aproximar el contur con el polígono. ¿Tal vez tienes una mejor idea de cómo extraer solo la forma más importante?

Respuesta

5

Su problema principal es que el contorno de la torre está disperso. Será difícil recrear todo el contorno de esas pequeñas piezas. Optimizar su fase de detección de bordes (tratar cvAdaptiveThreshold), o utilizar enfoque diferente (tal vez algo como object segmentation)

Una vez que tenga su contorno en una sola pieza, se puede comprobar su zona como esta:

CvSeq* convex_hull=cvConvexHull2(contour, storage, CV_CLOCKWISE, 2); 
CvSeq* quad=cvApproxPoly(convex_hull, sizeof(CvContour), storage, CV_POLY_APPROX_DP, cvContourPerimeter(contour)*0.02, 0); 
float size=fabs(cvContourArea(quad,CV_WHOLE_SEQ,0)); 

Se hará necesidad de ajustar los parámetros. Fue usado para detectar rectángulos.

8

Aquí no tiene que hacer la detección de bordes. Solo ingrese el umbral de una imagen binaria y luego encuentre los blobs (cvFindContours) en eso. Puede usar cvContourArea en cada CvSeq devuelto para encontrar su área.

2

Puede utilizar operaciones morfológicas para suprimir su "ruido de contorno" (dilatación en su caso). Pero debes recordar que la usabilidad de las operaciones morfológicas depende de la tarea actual. Por ejemplo, si tiene dos objetos colocados uno cerca del otro, la dilatación puede hacer un objeto a partir de ellos.

6

Si siempre tiene un fondo controlado, me gustaría ir a estos pasos (como se sugiere también por @damian):

  1. binarización, es decir, la creación de una imagen como el fondo = 0 y el regiones objeto = 1 (o 255). Después de eso, tendrá varias regiones blancas en su imagen. Hay varios métodos para hacer esto, pero si su fondo está controlado, puede usar un umbral fijo. Tenga en cuenta que aquí ha eliminado el ruido dentro de los objetos.En la imagen binaria, siempre puede usar la apertura/cierre morfológico para suavizar los objetos
  2. Use cvFindContours para encontrar todos los objetos: ahora debería ser más fácil.
  3. Rellene los contornos más pequeños con el color de fondo utilizando cvFloodFill.
+0

Como una adición al proceso de Binarización. Siempre es difícil encontrar un buen valor umbral. Siempre calculo un Hisogram y busco un "punto bajo". Allí usualmente tienes un valor umbral de nive. Si está utilizando archivos JPEG, es posible que este método no funcione tan bien. –

Cuestiones relacionadas