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:
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] = -1
lo 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.