Computer Vision con PythonFundamentos de VisionLección 5 de 12
Contornos y Analisis de Formas
Los contornos son curvas que conectan los puntos de borde de un objeto. Con findContours extraes las siluetas y luego puedes medir area, perimetro, centro de masa y clasificar formas geometricas.
Flujo tipico: 1. Convertir a gris → threshold o Canny para obtener binaria 2. findContours para extraer contornos 3. Filtrar por area (eliminar ruido) 4. Analizar cada contorno: area, perimetro, bounding box 5. Clasificar forma con approxPolyDP (vertices)
import cv2
import numpy as np
img = cv2.imread("formas.jpg")
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
_, thresh = cv2.threshold(gray, 127, 255, cv2.THRESH_BINARY_INV)
# Encontrar contornos
contornos, jerarquia = cv2.findContours(
thresh, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE
)
# RETR_EXTERNAL: solo contornos externos (ignora hijos)
# RETR_TREE: todos con jerarquia completa
for cnt in contornos:
area = cv2.contourArea(cnt)
if area < 100: # Filtrar ruido
continue
perimetro = cv2.arcLength(cnt, closed=True)
# Bounding box (rectangulo que encierra el contorno)
x, y, w, h = cv2.boundingRect(cnt)
cv2.rectangle(img, (x, y), (x+w, y+h), (0, 255, 0), 2)
# Circulo minimo
(cx, cy), radio = cv2.minEnclosingCircle(cnt)
# Centro de masa (momentos)
M = cv2.moments(cnt)
if M["m00"] > 0:
centro_x = int(M["m10"] / M["m00"])
centro_y = int(M["m01"] / M["m00"])
cv2.circle(img, (centro_x, centro_y), 5, (0, 0, 255), -1)
def clasificar_forma(cnt):
"""Clasifica forma geometrica por numero de vertices"""
perimetro = cv2.arcLength(cnt, True)
# approxPolyDP simplifica el contorno a un poligono
approx = cv2.approxPolyDP(cnt, 0.04 * perimetro, True)
vertices = len(approx)
if vertices == 3:
return "Triangulo"
elif vertices == 4:
# Diferenciar cuadrado de rectangulo
x, y, w, h = cv2.boundingRect(approx)
ratio = w / float(h)
return "Cuadrado" if 0.9 <= ratio <= 1.1 else "Rectangulo"
elif vertices == 5:
return "Pentagono"
elif vertices > 6:
# Verificar circularidad
area = cv2.contourArea(cnt)
circularidad = 4 * np.pi * area / (perimetro ** 2)
return "Circulo" if circularidad > 0.8 else f"Poligono ({vertices})"
return f"Poligono ({vertices})"
# Detectar y clasificar todas las formas
for cnt in contornos:
if cv2.contourArea(cnt) < 100:
continue
forma = clasificar_forma(cnt)
x, y, w, h = cv2.boundingRect(cnt)
cv2.putText(img, forma, (x, y - 10),
cv2.FONT_HERSHEY_SIMPLEX, 0.6, (255, 0, 0), 2)
cv2.drawContours(img, [cnt], -1, (0, 255, 0), 2)
ConsejoEl parametro epsilon de approxPolyDP controla la precision: 0.01*perimetro = muy preciso (muchos vertices), 0.05*perimetro = mas simplificado (pocos vertices). Usa 0.04 como punto de partida.
Practica esta lección
Resuelve los ejercicios del curso de Computer Vision con Python en la app, gratis y con corrección automática.
Empezar a practicar