2011-09-14 19 views
10

Estoy trabajando en una imagen en blanco & color negro al igual que la primera del enlace: http://imageshack.us/g/33/firstwm.png/ Tiene mucho "ruido", así que apliqué un filtro Median sobre él para alisarlo, obteniendo así la segunda imagen.¿Cómo suavizo las curvas (contornos) en OpenCV?

cvSmooth(TempImage, TempImage, CV_MEDIAN, 5, 0); 

Después de esto obtengo los contornos y los dibujo en otra imagen como la 3 ª imagen del enlace. Mi problema es que los contornos están todavía un poco pixelados (afilados). ¿Hay alguna manera de suavizar la imagen B & W aún más para obtener mejores contornos? O tal vez hacer algo con los contornos. También he intentado Dilate y Erode con diferentes kernels, pero el problema sigue siendo el mismo. Gracias por cualquier cosa que ayude.

EDIT: También probamos:

cvSmooth(TempImage, TempImage, CV_GAUSSIAN, 9, 9, 3); 
cvThreshold(TempImage, TempImage, 127, 255, CV_THRESH_BINARY); 

mismos resultados que el filtro de mediana, bien, pero deja algunos contornos pixelados.

+1

pasándolo a través de un núcleo de Gauss, y después de umbrales debería suavizar los bordes. Quizás este es el resultado que quieres? – swalog

+0

Supongo que el "ruido" del que habla son los componentes de alta frecuencia que parecía haber eliminado en su segundo ejemplo. Es [this] (http://i.imgur.com/33GIT.png) un resultado deseado? Si solo se desea una salida binaria, un [umbral duro] (http://i.imgur.com/VelRg.png) sería lo más cercano. – swalog

+0

Sí, el resultado deseado es eliminar el ruido para tener los contornos más suaves posible. He intentado con Gaussian + umbral también a sugerencia suya, pero obtengo los mismos resultados que el filtro de mediana. – Adrian

Respuesta

8

enter image description here

Si este es el resultado de alisado que está buscando, que se puede obtener haciendo un desenfoque gaussiano, seguido de un umbral. Es decir. usando cvSmooth con CV_GAUSSIAN como el parámetro. Seguido por un cvThreshold.

Si desea una transición más suave que el umbral (como this), puede obtener eso con los niveles de ajuste (reasignando el rango de color para que se preserve parte de la transición de bordes).

actualización Para explicar cómo obtener el borde suave (sin alias) en el umbral, tenga en cuenta lo que hace el umbral. Básicamente procesa cada píxel en la imagen, uno a la vez. Si el valor del píxel es inferior al umbral, se establece en negro (0), si no se establece en blanco (255).

El operador de umbral es por lo tanto muy simple, sin embargo, se puede usar cualquier otra función de mapeo general. Básicamente es una función f(i), donde i es el valor de píxel de intensidad (rango 0-255) y f(i) es el valor asignado. Para el umbral de esta función es simple

f(i) = { 0, for i < threshold 
      255, for i >= threshold 

Lo que tenemos es una imagen suavizada (por cvSmooth usando un kernel de Gauss, que le da la suavización "más suave", si eso tiene sentido). Por lo tanto, tiene una transición suave de valores en los bordes, que van de 0 a 255. Lo que quiere hacer es hacer esta transición mucho más pequeña, para que obtenga una buena ventaja. Si se vuelve loco, va directamente de 0 a 255, que es lo mismo que el umbral binario que ya ha hecho.

Ahora, considere una función que mapea, tal vez un rango de 4 valores de intensidad (127 + - 4) en el rango completo de 0-255. Es decir.

  f(i) = { 0, for i < 123 
        255, for i >= 131 
     linear mapping, for 123 <= i < 131 

Y obtiene la salida deseada. Echaré un vistazo rápido y veré si ya está implementado en openCV. Sin embargo, no debería ser demasiado difícil codificarlo usted mismo.

actualización 2 La versión contorno sería algo como esto:

   f(i) = { 255, for  i < 122 
    linear mapping (255->0), for 122 <= i < 126 
         0, for 126 <= i < 127 
    linear mapping (0->255), for 127 <= i < 131 
         255, for 131 <= i 
+0

Oh, ahora entiendo lo que estás diciendo, para eso podría usar cvLUT en lugar de cvThreshold. Pero ahora que lo pienso después de aplicar cvFindContours para obtener los contornos, volveré al contorno pixelado :(. Gracias por la respuesta, si en unos pocos días aparece una mejor respuesta, marcaré la tuya como correcto. – Adrian

+0

Tenga en cuenta que tiene el borde de degradado suave después de la operación de suavizado. Todavía debería ser posible obtener una imagen de contorno atractiva utilizando cvLUT y los valores de tabla correctos. En resumen, tendría tres rangos, de blanco a negro (inicio de línea) de negro a negro (dentro de la línea) y de negro a blanco (final de línea). Si sigue la misma estructura que la anterior. Todos los valores que están fuera de esta también se mapean en blanco. Por lo tanto, terminas con un aspecto agradable contorno :) – swalog

+0

Ver la actualización 2 en la respuesta. También estoy adivinando buenos valores, por lo que es posible que desee jugar con eso :) – swalog

Cuestiones relacionadas