Información de la Tarea
- Estudiante: Andrés Cruz Chipol
- Curso: Aprendizaje Profundo
- Fecha de entrega: 16 de Junio, 2026
Descripción de la Tarea
Clasificador de imágenes de ocho formas. Realizar el software en OpenCV para probar el tiempo real los clasificadores realizados en el apunte del día 19.05.2026.
Introducción
El objetivo principal es detectar y clasificar ocho formas geométricas diferentes en cada fotograma del flujo de video.
Entrenamiento del Modelo en Scikit-Learn
Para el primer enfoque, el modelo utilizo un MLPClassifier de Scikit-Learn Tomado de los apuntes utilizando los momentos de Hu.
import numpy as npfrom sklearn.neural_network import MLPClassifierfrom sklearn.model_selection import train_test_splitfrom sklearn.preprocessing import StandardScaler
# Obtiene las características y las clasesdata = np.genfromtxt('Momentos_Hu.csv', delimiter=',')clases = np.array(["Cruz", "Estrella", "I", "Línea", "Óvalo", "Pentágono", "Rectángulo", "Triángulo"])
# Elimina los momentos de Hu 4, 5 y 6 debido a que no proporcionan informaciónX = np.delete(data[:,:7], (4,5,6), axis=1)y = data[:,7]
# Normalización: Media cero y desviación estándar unoescala = StandardScaler()X = escala.fit_transform(X)
# Genera los sets de entrenamientoX_train, X_test, y_train, y_test = train_test_split(X, y, random_state=21)
# Genera el modelo y lo entrenaclasificador = MLPClassifier(hidden_layer_sizes=(4,), solver="lbfgs", random_state=1, max_iter=400)clasificador.fit(X_train, y_train)
print("Score en entrenamiento:", clasificador.score(X_train, y_train))Entrenamiento del Modelo en PyTorch
Usando PyTorch. La arquitectura consta de capas lineales con funciones de activación Sigmoide y Softmax. Se entrenó durante 118 épocas utilizando el optimizador SGD con momento Nesterov.
import torchfrom torch import nn
# El modelo de la red neuronalclass RedNeuronal(nn.Module): def __init__(self): super().__init__() self.arquitectura = nn.Sequential( nn.Linear(4, 4), nn.Sigmoid(), nn.Linear(4, 8), nn.Softmax(dim=1) )
def forward(self, x): return self.arquitectura(x)
# Instanciamos el modelomodelo = RedNeuronal()loss_fn = nn.CrossEntropyLoss()optimizador = torch.optim.SGD(modelo.parameters(), lr=0.5, momentum=0.9, nesterov=True)
# Bucle de entrenamiento y pruebaepochs = 118for t in range(epochs): train_loop(X_entrena, y_entrena, modelo, loss_fn, optimizador) test_loop(t, X_prueba, y_prueba, modelo, loss_fn)
# Guardamos el modelo entrenadotorch.save(modelo, 'mod1.pth')Interfaz de Detección en Tiempo Real
La interfaz gráfica en Tkinter (detector_formas.py) se integra con OpenCV para capturar el video en vivo. Esta interfaz permite al usuario alternar entre el modelo cargado en PyTorch y el modelo de Scikit-Learn para comparar su desempeño en tiempo real al evaluar los momentos de Hu extraídos en cada fotograma.
import cv2import numpy as npimport tkinter as tk
# El script carga tanto el modelo de PyTorch como el de Sklearn# modelos_reg = { "PyTorch": ClasificadorPyTorch(...), "Scikit-Learn": ClasificadorSklearn(...) }
def actualizar_video(self): if not self.pausado and (ret := self.cap.read()[0]): self.f_actual = self.cap.read()[1]
frame = self.f_actual.copy()
# Preprocesamiento de la imagen para extraer contornos blur = cv2.GaussianBlur(cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY), (5, 5), 0) med = np.median(blur) bordes = cv2.dilate(cv2.Canny(blur, int(max(0, 0.5*med)), int(min(255, 1.5*med))), np.ones((3,3), np.uint8), iterations=2)
contornos, _ = cv2.findContours(bordes, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
# Obtiene el clasificador seleccionado actualmente en la UI mod = self.modelos_reg.get(self.var_mod.get())
for c in contornos: if no_es_valido(c): continue
# Extraemos los 4 momentos de Hu necesarios hu = extraer_hu_desde_mascara(c) if hu is None: continue
# Realizamos la predicción con el modelo en uso clase, conf = mod.predecir(hu) if conf < 0.4: continue
# Dibujamos los resultados (cajita y etiqueta) sobre el frame x, y, w, h = cv2.boundingRect(c) cv2.drawContours(frame, [c], -1, (0, 255, 0), 2) cv2.putText(frame, f"{clase} {conf:.0%}", (x, y-10), cv2.FONT_HERSHEY_SIMPLEX, 0.5, (0, 255, 0), 2)
# Actualiza el frame en la interfaz Tkinter mostrar_en_interfaz(frame)Demostraciónes en Video
Resultados y Conclusiones
Durante las pruebas prácticas, se realizaron las siguientes observaciones:
- Desempeño por forma: Las figuras como los círculos y los triángulos funcionan muy bien y son detectadas sin problemas. Sin embargo, las figuras en forma de “I” suelen tener un rendimiento muy errático a la hora de seleccionar la cajita delimitadora, como se observa en el video.
- PyTorch vs Scikit-Learn: Al modelo implementado en PyTorch suele dificultársele más la detección en comparación con el modelo elaborado en Scikit-Learn (sklearn), el cual se siente mucho más estable y robusto a la hora de detectar los objetos continuos. Por otro lado, la interfaz permite al usuario seleccionar qué modelo usar en tiempo real para poder comparar ambos.