Portafolio profesional

Paractica Vocales: Cuando la IA se encuentra con la fonética

Construí una aplicación en Python que usa visión por computadora para enseñar a reconocer vocales en tiempo real, uniendo lingüística y machine learning.

Artículo

# Cuando la IA se encuentra con las vocales: un proyecto educativo en Python ## El problema Como desarrollador, a veces te encontrás con problemas que parecen simples pero que tienen un impacto real. En este caso, la motivación fue educativa: ¿cómo podés hacer que aprender las vocales sea más interactivo y atractivo, especialmente para niños o personas que están comenzando? La práctica tradicional suele ser repetitiva: ver una imagen, decir el sonido. No hay retroalimentación inmediata, no hay adaptación al ritmo del usuario. Quería construir algo que combinara la tecnología actual con un objetivo de aprendizaje claro, creando un puente entre la pantalla y la acción física del usuario. ## Por qué Python y TensorFlow/Keras Podría haber optado por una aplicación web simple con botones, pero eso no resolvería el problema de la interacción física y la retroalimentación visual. Necesitaba que el sistema "viera" lo que el usuario hacía. Python, con su ecosistema para ciencia de datos y aprendizaje automático, era la opción obvia. Librerías como OpenCV (`cv2`) para la captura y procesamiento de imágenes en tiempo real, y TensorFlow/Keras para construir y entrenar un modelo de red neuronal convolucional (CNN) ligero, permitieron crear un prototipo funcional rápidamente sin una infraestructura compleja. Comparado con desarrollar una aplicación nativa para móviles o usar un framework web pesado, esta stack me dio la agilidad para iterar sobre el modelo de machine learning, que era el núcleo del proyecto. ## Arquitectura El sistema sigue un flujo de pipeline bastante directo, dividido en tres etapas principales de preparación de datos, entrenamiento y despliegue/inferencia. ```mermaid flowchart LR Captura["captura_imagenes.py Captura webcam, procesa ROI"] -- Guarda imágenes etiquetadas --> Datos["Directorio de imágenes Dataset para entrenamiento"] Datos -- Carga y aumenta --> Entrenamiento["entrenar_modelo.py Construye y entrena CNN"] Entrenamiento -- Serializa pesos --> Modelo["modelo_vocales.h5 Modelo Keras entrenado"] Modelo -- Carga para inferencia --> Inferencia["reconocer_en_tiempo_real.py Captura webcam, predice, muestra"] Inferencia -- Usa --> OpenCV["OpenCV (cv2) Procesamiento de video"] NOTE["Evidence gap: No se especifica el formato de los datos de entrada al modelo."] Entrenamiento -.-> NOTE ``` Como ves en el diagrama, la arquitectura es un pipeline lineal. Primero, `captura_imagenes.py` se encarga de crear el dataset. Usa OpenCV para acceder a la webcam, aísla una región de interés (ROI) donde el usuario muestra la seña de la vocal (probablemente con la mano), y guarda frames etiquetados. Estos datos crudos pasan a `entrenar_modelo.py`, que se encarga del ciclo completo de ML: carga las imágenes, aplica aumentos de datos (para mejorar la generalización), construye la arquitectura de la CNN, la entrena y finalmente guarda el modelo entrenado en un archivo `.h5`. La última etapa, `reconocer_en_tiempo_real.py`, es la aplicación final. Carga el modelo guardado, inicia un bucle de captura de video, y para cada frame realiza el mismo preprocesamiento que durante el entrenamiento (recortar la ROI) para luego pasar esa imagen al modelo y obtener una predicción, la cual se muestra superpuesta en la pantalla en tiempo real. **Decisión 1: Pipeline separado en scripts.** En lugar de un monolitico, dividí la funcionalidad en scripts independientes (`captura`, `entrenar`, `reconocer`). Esto permite iterar y probar cada etapa por separado. Por ejemplo, podés recolectar nuevos datos sin tocar el código de entrenamiento. **Decisión 2: Modelo guardado en archivo `.h5`.** Keras permite guardar el modelo completo (arquitectura y pesos) en un solo archivo. Esto simplifica enormemente el despliegue en la etapa de reconocimiento, ya que `reconocer_en_tiempo_real.py` solo necesita una línea para cargar el modelo y listo. **Decisión 3: Procesamiento en tiempo real con OpenCV.** Usar OpenCV para la captura de video y el dibujo de la interfaz (texto, rectángulo de la ROI) en el mismo script de reconocimiento mantiene la aplicación ligera y responsiva, sin necesidad de un framework de UI más complejo. ## El trade-off que nadie te cuenta El gran trade-off está en la **generalización del modelo vs. la simplicidad del dataset**. Para que la aplicación funcione bien para cualquier usuario, en cualquier entorno de iluminación y con cualquier webcam, necesitarías un dataset enorme y diverso. En la práctica, para un prototipo o un uso controlado, el dataset suele ser pequeño y capturado por una sola persona (a veces, por vos mismo como desarrollador). Esto significa que el modelo puede aprender muy bien a reconocer *tus* gestos en *tu* escritorio, pero fallará miserablemente si otra persona lo usa o si cambia la luz. La solución temporal fue implementar aumentos de datos (rotaciones, cambios de brillo) durante el entrenamiento para simular algo de variabilidad. Pero la solución real, y el trabajo más arduo, es la recolección de un dataset más robusto y representativo, lo cual es un proceso manual y lento. ## Resultado * **Aplicación funcional de extremo a extremo:** Se logró un pipeline completo, desde la generación de datos hasta una aplicación interactiva que responde en tiempo real (con latencias de unos pocos milisegundos por frame). * **Interfaz de usuario mínima pero efectiva:** La ventana de OpenCV muestra claramente la región de interés y la vocal predicha, dando una retroalimentación inmediata al usuario. * **Base para experimentación:** El código está estructurado de manera que es fácil modificar la arquitectura de la red, los parámetros de entrenamiento o la lógica de preprocesamiento para probar diferentes enfoques. * **Documentación implícita en el código:** La separación en scripts y el uso de nombres de variables claros hace que el flujo del proyecto sea fácil de entender y replicar. ## Lo que haría diferente Invertiría más tiempo en la etapa de **ingeniería de características** o preprocesamiento de las imágenes antes de alimentar la red. En este proyecto, el preprocesamiento se limita básicamente a recortar la ROI. Probaría convertir las imágenes a escala de grises, aplicar umbralización o detectar bordes (con Canny, por ejemplo) para entregarle al modelo una representación más abstracta y menos dependiente del color y la textura de la piel o el fondo. Esto podría mejorar la robustez y reducir la necesidad de un dataset tan grande. También, para hacerlo más "productivo", encapsularía la lógica principal en funciones o una clase para facilitar las pruebas unitarias. ¿Querés profundizar en algún componente? Contactame o revisá el código en https://github.com/Albarracin-sg/paractica-vocales.