2012-04-20 140 views
7

Actualmente estoy trabajando en el proyecto de procesamiento de imágenes. Estoy usando Opencv2.3.1 con VC++. He escrito el código de tal manera que la imagen de entrada se filtra solo al color azul y se convierte en una imagen binaria. La imagen binaria tiene algunos objetos pequeños que no quiero. Quería eliminar esos objetos pequeños, así que utilicé el método cvFindContours() de openCV para detectar contornos en una imagen binaria. pero el problema es que no puedo eliminar los objetos pequeños en la salida de la imagen. Usé la función cvContourArea(), pero no funcionó correctamente ..., la función erosionar tampoco funcionó correctamente.Contornos opencv: Cómo eliminar pequeños contornos en una imagen binaria

Así que por favor alguien que me ayude con este problema ..

La imagen binaria que obtuve:

enter image description here

La imagen resultante/salida que quiero para obtener:

enter image description here

Respuesta

1

¿Está seguro de que el filtrado por área de contorno pequeño no funcionó? Siempre me funcionó. ¿Podemos ver tu código?

Además, como mencionó el sue-ling, es una buena idea usar erosionar y dilatar para conservar aproximadamente el área. Para eliminar las pequeñas partículas ruidosas, primero use erosionar y, para rellenar los agujeros, primero use dilatar.

Y otro lado, es posible que desee comprobar hacia fuera el nuevo C++ versiones de las funciones cv * si no estaban al tanto de ellos ya (documentation para findContours). Son mucho más fáciles de usar, en mi opinión.

+0

Gracias por la sugerencia, pero no entiendo cómo escribir el código para encontrar el área de cada blob/contorno que se ha detectado. El código que he escrito está en el siguiente enlace. ¿Puedes corregirlo y responder? : http://textuploader.com/?p=6&id=YwRl. –

+0

¡oh! Me acabo de olvidar, el encabezado y el archivo cpp de cvutility se pueden encontrar en estos enlaces: http: //textuploader.com/? P = 6 & id = Dtnvj http://textuploader.com/?p=6&id=TSlRQ Incluirlos en directorio de origen e incluir rutas. –

+0

No estoy muy familiarizado con la api C, pero parece que solo estás calculando el área del primer contorno. Necesita iterar a través de los contornos y solo dibujar los con área> algún umbral. Si solo está tratando de encontrar ese objeto, debe dibujar el contorno con el área más grande. – fferen

0

A juzgar por las imágenes de antes y después, debe determinar el área de todas las áreas blancas o blobs, luego aplicar un valor de área de umbral. Esto eliminaría todas las áreas menores que el valor y dejaría solo la gran región blanca que se ve en la segunda imagen. Después de usar la función cvFindContours, intente usar 0 momentos de orden. Esto devolvería el área de los blobs en la imagen. Este enlace podría ser útil para implementar lo que acabo de describir. http://www.aishack.in/2010/07/tracking-colored-objects-in-opencv/

+0

Gracias por la sugerencia, pero no entiendo cómo escribir el código para encontrar el área de cada blob/contorno que se ha detectado. –

+0

Gracias por la sugerencia, pero no entiendo cómo escribir el código para encontrar el área de cada burbuja/contorno que se ha detectado. El código que he escrito está en el siguiente enlace. ¿Puedes corregirlo y responder? : http://textuploader.com/?p=6&id=YwRl. –

+0

¡oh! Me acabo de olvidar, el encabezado y el archivo cpp de cvutility se pueden encontrar en estos enlaces: http: //textuploader.com/? P = 6 & id = Dtnvj http://textuploader.com/?p=6&id=TSlRQ Incluirlos en directorio de origen e incluir rutas. –

10

Ok, creo que su problema podría resolverse con the bounding box demo recientemente introducido por OpenCV.

enter image description here

Como se habrá notado, el objeto que le interesa al debe estar dentro del rectángulo más grande dibujar en la imagen. Afortunadamente, este código no es muy complejo y estoy seguro de que puedes resolverlo investigando y experimentando con él.

+0

thnx .. lo comprobaré. –

7

Aquí está mi solución para eliminar pequeños contornos. La idea básica es verificar el largo/área para cada contorno, luego eliminar el más pequeño del contenedor vectorial.

normalmente obtendrá contornos como este

Mat canny_output; //example from OpenCV Tutorial 
vector<vector<Point> > contours; 
vector<Vec4i> hierarchy; 
Canny(src_img, canny_output, thresh, thresh*2, 3);//with or without, explained later. 
findContours(canny_output, contours, hierarchy, CV_RETR_TREE, CV_CHAIN_APPROX_SIMPLE, Point(0,0)); 

Con Canny() pre-procesamiento, obtendrá segmentos de contorno, sin embargo cada segmento se almacena con los píxeles de contorno como un anillo cerrado.En este caso, se puede comprobar la longitud y borrar el pequeño como

for (vector<vector<Point> >::iterator it = contours.begin(); it!=contours.end();) 
{ 
    if (it->size()<contour_length_threshold) 
     it=contours.erase(it); 
    else 
     ++it; 
} 

Sin Canny() de procesamiento previo, obtendrá contornos de los objetos. Similitud, también se puede utilizar el área para definir un umbral para eliminar objetos pequeños, como OpenCV tutorial se muestra

vector<Point> contour = contours[i]; 
double area0 = contourArea(contour); 

este contourArea() es el número de píxeles que no son cero

0

Creo que se puede utilizar morfológica operadores como erosionar y dilatar (leer más here)

Debe realizar la erosión con un tamaño de núcleo cerca del radio del círculo de la derecha (el que desea eliminar). seguido de dilatación usando el mismo núcleo para llenar los huecos creados por el paso de erosión.

FYI La erosión seguida de la dilatación usando el mismo núcleo se denomina apertura.

el código será algo como esto

int erosion_size = 30; // adjust with you application 
Mat erode_element = getStructuringElement(MORPH_ELLIPSE, 
         Size(2*erosion_size + 1, 2*erosion_size+1), 
         Point(erosion_size, erosion_size)); 
erode(binary_img, binary_img, erode_element); 
dilate(binary_img, binary_img, erode_element); 
0

No es una forma rápida, pero puede ser útil en algunos casos. Hay una nueva función en OpencCV 3.0 - connectedComponentsWithStats. Con él podemos obtener el área de componentes conectados y eliminar innecesarios. Así que podemos eliminar fácilmente el círculo con agujeros, con el mismo cuadro delimitador que el círculo sólido.

Cuestiones relacionadas