Saltar al contenido

Reconocer formas abiertas y cerradas opencv

El paso a paso o código que hallarás en este artículo es la resolución más eficiente y efectiva que hallamos a tus dudas o dilema.

Solución:

Simplemente use findContours() en su imagen, luego decida si el contorno está cerrado o no examinando la jerarquía pasada a la función findContours(). En la segunda figura, es más claro que ningún contorno tiene un contorno secundario en comparación con la primera imagen. Obtendrá estos datos del parámetro de jerarquía, que es un vector de salida opcional, que contiene información sobre la topología de la imagen. Tiene tantos elementos como número de contornos.

Aquí usaremos la jerarquía como

vector< Vec4i > hierarchy

donde para un i-ésimo contorno

hierarchy[i][0] = next contour at the same hierarchical level
hierarchy[i][1] = previous contour at the same hierarchical level
hierarchy[i][2] = denotes its first child contour
hierarchy[i][3] = denotes index of its parent contour

Si para el contorno i no hay contornos siguiente, anterior, principal o anidado, los elementos correspondientes de hierarchy[i] será negativo. Consulte la función findContours() para obtener más detalles.

Entonces al verificar el valor hierarchy[i][2] puede decidir que el contorno pertenece a cerrado o no, eso es para un contorno si el hierarchy[i][2] = -1 entonces no hay niño y pertenece a abierto.

Y una cosa más es que en la función findContours() debe usar CV_RETR_CCOMP que recupera todos los contornos y los organiza en una jerarquía de dos niveles.

Aquí está el código C++ de cómo implementar esto.

    Mat tmp,thr;
    Mat src=imread("1.png",1);
    cvtColor(src,tmp,CV_BGR2GRAY);
    threshold(tmp,thr,200,255,THRESH_BINARY_INV);

    vector< vector  > contours; // Vector for storing contour
    vector< Vec4i > hierarchy;
    findContours( thr, contours, hierarchy,CV_RETR_CCOMP, CV_CHAIN_APPROX_SIMPLE );

    for( int i = 0; i< contours.size(); i=hierarchy[i][0] ) // iterate through each contour.
    
        Rect r= boundingRect(contours[i]);
        if(hierarchy[i][2]<0) //Check if there is a child contour
          rectangle(src,Point(r.x-10,r.y-10), Point(r.x+r.width+10,r.y+r.height+10), Scalar(0,0,255),2,8,0); //Opened contour
        else
          rectangle(src,Point(r.x-10,r.y-10), Point(r.x+r.width+10,r.y+r.height+10), Scalar(0,255,0),2,8,0); //closed contour
    

Resultado:

ingrese la descripción de la imagen aquí

Si bien es correcta para el problema planteado, la útil respuesta de @Haris no debe tomarse como una solución general para identificar contornos cerrados mediante findContours().

Una de las razones es que un objeto relleno no tendrá contorno interno y, por lo tanto, devolverá hierarchy[i][2] = -1lo que significa que esta prueba por sí sola etiquetaría erróneamente tales contornos como 'abiertos'.

El contorno de un objeto relleno no debe tener elementos secundarios o principales en la jerarquía de contornos, es decir, debe estar en el nivel superior. Entonces, para detectar contornos cerrados de objetos llenos, al menos requeriría una prueba adicional: if(hierarchy[i][2] < 0 && hierarchy[i][3] < 0).

Creo que la respuesta de @Haris puede haber señalado este punto indirectamente, pero pensé que valía la pena aclararlo para las personas, como yo, que están aprendiendo a usar opencv.

Implementación de Python de la misma que se muestra a continuación.

import cv2


src = cv2.imread('test.png', cv2.IMREAD_COLOR)

#Transform source image to gray if it is not already
if len(src.shape) != 2:
    gray = cv2.cvtColor(src, cv2.COLOR_BGR2GRAY)
else:
    gray = src

ret, thresh = cv2.threshold(gray, 200, 255, cv2.THRESH_BINARY_INV)
contours, hierarchy = cv2.findContours(thresh, cv2.RETR_CCOMP, cv2.CHAIN_APPROX_SIMPLE)
hierarchy = hierarchy[0]

for i, c in enumerate(contours):
    if hierarchy[i][2] < 0 and hierarchy[i][3] < 0:
        cv2.drawContours(src, contours, i, (0, 0, 255), 2)
    else:
        cv2.drawContours(src, contours, i, (0, 255, 0), 2)
#write to the same directory
cv2.imwrite("result.png", src)

valoraciones y reseñas

Tienes la opción de respaldar nuestra ocupación poniendo un comentario o dejando una puntuación te lo agradecemos.

¡Haz clic para puntuar esta entrada!
(Votos: 0 Promedio: 0)



Utiliza Nuestro Buscador

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *