Un modelo que detecta fallas de impresión no aprende "cómo se ve un spaghetti". Aprende cómo se ve tu impresora cuando todo va bien, y levanta la mano cuando la escena deja de parecerse a eso. Esa diferencia. detección de anomalías en lugar de clasificación. es la que te permite entrenar con puras fotos de impresiones correctas, sin tener que arruinar veinte piezas a propósito para juntar ejemplos de error.

Este capítulo toma las ~2.600 imágenes que la cámara del Arduino UNO Q juntó sola durante una semana de impresiones normales y las convierte en el cerebro del vigilante: un modelo FOMO AD entrenado en Edge Impulse, exportado como archivo .eim para correr offline sobre la placa. Al terminar vas a saber armar el impulse completo, esquivar las dos trampas que hacen perder una tarde, interpretar los números del test (spoiler: el primero da malísimo y no significa lo que crees) y elegir un umbral de alarma con criterio en vez de a ojo.

Studio de Edge Impulse con el impulse terminado: bloque de imagen y bloque Visual Anomaly Detection

Qué es FOMO AD y por qué no necesitas fotos de fallas

Vale la pena entender el mecanismo antes de hacer clics, porque explica casi todas las decisiones que vienen después.

Un clasificador clásico necesita ejemplos de cada clase: 500 fotos de "bien" y 500 de "mal". FOMO AD (Faster Objects, More Objects, Anomaly Detection) funciona al revés. Corta cada imagen en una grilla de parches, aprende cómo se ven los parches de tu escena normal y guarda esa distribución. En inferencia compara cada parche contra lo aprendido y entrega un solo número: el score de anomalía, que es la distancia a esa normalidad.

Tres consecuencias prácticas que conviene tener claras desde ya:

  • Entrenas solo con ejemplos buenos. Las imágenes con fallas no se usan para entrenar; sirven únicamente para el test y para calibrar el umbral.
  • La cámara y la luz son parte del modelo. Si mueves la cámara o cambias la iluminación, cambias la "normalidad" y el modelo empieza a desconfiar de todo. Esto no es un defecto, es la definición del método.
  • El score no es una probabilidad. No hay un 0,5 mágico. El umbral se decide mirando cómo se distribuyen tus propios datos, y es un parámetro tuyo, no del entrenamiento.

La plataforma: Edge Impulse en dos minutos

Edge Impulse es una plataforma en la nube especializada en modelos para dispositivos chicos: microcontroladores, computadores de placa única, celulares. Lo atractivo para quien hace proyectos en casa es que todo el flujo vive en el navegador. gestión de datos, armado de la pipeline, entrenamiento, test y exportación. y el entrenamiento corre en sus servidores. No necesitas GPU propia ni ambiente de Python. Tu equipo vuelve a aparecer recién al final, cuando el modelo terminado se instala en él y desde ahí funciona completamente offline.

Para este proyecto alcanza el plan Developer gratuito (crea la cuenta en studio.edgeimpulse.com), y el UNO Q figura como target oficialmente soportado, así que la exportación sale sin parches raros.

Después de entrar, crea un proyecto vacío con Create new project. De ahí vas a necesitar dos cosas casi de inmediato:

  • El API key, en Dashboard → Keys, para subir las imágenes.
  • La página Data acquisition, donde todo lo subido aparece como miniatura con su etiqueta.

Subir las imágenes desde la propia placa

Las fotos ya están en el UNO Q, en ~/dataset/no-anomaly/, dejadas ahí por el servicio recolector del capítulo anterior. No hay que pasarlas por el PC: se suben por SSH directo desde la placa a la nube.

Edge Impulse ofrece su propia herramienta de línea de comandos, pero exige Node.js, y en una placa con menos de 10 GB de almacenamiento gastar varios cientos de megabytes en eso es caro. La alternativa liviana es la Ingestion API, que recibe imágenes por HTTP simple, y curl ya viene instalado.

Bash
wget https://raw.githubusercontent.com/raspberry-tips/arduino-uno-q-projects/main/kamera-setup/ei_upload.sh
nano ei_upload.sh   # EI_API_KEY eintragen
sh ei_upload.sh

El script sube la carpeta completa del dataset en paquetes de 20 y, gracias a la protección contra duplicados, se salta todo lo que ya está en el Studio. Eso significa que puedes volver a correrlo después de cada impresión sin pensarlo.

Las imágenes con fallas se suben por el mismo camino, con dos diferencias: etiqueta anomaly y endpoint testing en vez de training. El porqué está en la sección siguiente.

Trampa 1: "Poor training/test split ratio" no pide fotos de fallas

Apenas terminan de subir las imágenes aparece una advertencia: "The 'no anomaly' class has a poor training/test split ratio". La reacción natural es pensar que hace falta juntar un 20% de imágenes de error. o sea, arruinar cientos de impresiones a propósito.

No es eso. La advertencia habla exclusivamente del reparto de las imágenes normales entre datos de entrenamiento y datos de test.

El fondo del asunto sí importa: el set de test necesita imágenes normales que el modelo nunca vio durante el entrenamiento, porque solo así se puede medir cuántas veces se equivoca en operación normal. "¿Detecta el spaghetti?" y "¿molesta durante una impresión buena?" son dos preguntas distintas, y el umbral de alarma sale recién de las dos juntas.

La corrección es un clic: Dashboard → Danger zone → Perform train/test split. Edge Impulse mueve solo alrededor del 20% de las imágenes normales al set de test. En el proyecto de referencia quedó así: 2.082 imágenes para entrenar, 525 para testear, de las cuales 20 son fallas reales de stringing.

Armar el impulse: 96×96 y FOMO AD

La pipeline de procesamiento. en Edge Impulse se llama impulse. se arma en cinco minutos. Las imágenes se comprimen a 96×96 píxeles, un bloque Image las normaliza, y detrás va el bloque de aprendizaje Visual Anomaly Detection (FOMO AD). La salida es un único valor: el score de anomalía.

Paso a paso:

  1. En el menú de la izquierda, abre Impulse design → Create impulse.
  2. El primer recuadro, Image data, ya está listo: ancho y alto en 96 cada uno, Resize mode en Squash.
  3. Add a processing block → Image (la primera opción). Se encarga de la normalización y del tratamiento de color.
  4. Add a learning block → acá está la trampa 2, que viene a continuación. Necesitas Visual Anomaly Detection (FOMO AD), que según la vista aparece escondido tras Show all blocks.
  5. Save impulse. A la derecha la salida debe decir 1 (Anomaly score).
  6. En el nuevo ítem de menú Image: deja Color depth en RGB → Save parametersGenerate features. Eso prepara todas las imágenes para el entrenamiento y, de paso, dibuja el Feature Explorer.

Un detalle que suele generar desconfianza: 96×96 píxeles parecen poquísimos para ver un enredo de filamento. Alcanza porque FOMO AD no necesita reconocer un objeto, sino notar que la textura de una zona de la imagen dejó de parecerse a lo aprendido. Un ovillo de spaghetti cambia la textura de varios parches de la grilla completa, y eso sobrevive perfectamente a la reducción de resolución. Además, la resolución baja es justamente lo que hace que la inferencia dure milisegundos en vez de segundos.

Trampa 2: hay DOS bloques llamados "Anomaly Detection"

En el diálogo de bloques de aprendizaje también existe uno que se llama simplemente Anomaly Detection. Ese es un autoencoder para series de tiempo de sensores (aceleración, temperatura y similares), no para imágenes. El bloque visual se esconde según la vista tras el enlace Show all blocks y su nombre completo es Visual Anomaly Detection (FOMO AD).

Si eliges el equivocado, el entrenamiento se cae con este error exacto:

Text
ValueError: total size of new array must be unchanged,
input_shape = [96, 96, 3], output_shape = [96, 1]

Traducido: el bloque está tratando de aplastar una imagen a color en una serie de mediciones unidimensional. Si ves ese mensaje, ya sabes que el problema no es tu dataset ni tu configuración: elegiste el bloque incorrecto.

Entrenamiento: cinco minutos aburridos

El entrenamiento propiamente tal es decepcionantemente tranquilo: deja todos los parámetros en sus valores por defecto, aprieta Start training y espera unos cinco minutos.

Antes de eso vale la pena mirar el Feature Explorer, porque muestra bien qué está por aprender el modelo: las imágenes normales forman varias nubes de puntos separadas, una por impresión y por situación de luz. Esas "islas de normalidad" son exactamente lo que FOMO AD memoriza.

Feature Explorer del Studio de Edge Impulse con las nubes de puntos de las imágenes de entrenamiento

Que aparezcan varias nubes en vez de una sola mancha compacta es buena señal: significa que el dataset cubre condiciones distintas. Si todas tus imágenes fueran de una sola impresión con una sola luz, tendrías una nube apretada y un modelo que se asusta con cualquier atardecer.

El susto: F1 de 0,23 (y por qué casi no significa nada)

Llega el momento de la verdad: Model testing pasa las 525 imágenes de test por el modelo recién entrenado. Resultado: accuracy 74,67%, F1-score para la clase anomalía un desalentador 0,23.

Acá es donde mucha gente da el proyecto por fracasado. No lo hagas: ese número dice muy poco sobre el modelo. Dice que el umbral por defecto no calza con tus datos.

Los datos crudos cuentan otra historia completamente distinta:

  • Las 20 imágenes de stringing fueron detectadas: el 100%.
  • Las imágenes normales tienen mediana de score 26 y el 99% queda bajo 33.
  • Las imágenes con falla parten en 44 y tienen mediana 63.

O sea, entre 33 y 44 hay un corredor limpio, sin nadie adentro. El problema era el umbral por defecto de 27,3, sentado justo en medio de la distribución normal, que declaraba anomalías a 133 imágenes inofensivas.

Con el umbral movido a 40 (en Model testing, en el ícono de filtro junto a Classify all) y una reclasificación, el 0,23 se transforma en F1 = 1,00: todas las anomalías detectadas, cero falsas alarmas.

Model testing del Studio de Edge Impulse mostrando 100% de accuracy y F1-score 1,00

Cómo elegir un umbral honesto

Que el 40 haya funcionado no fue suerte, y conviene entender la receta porque vas a tener que repetirla con tus propios datos.

El F1-score se calcula después de aplicar un umbral: convierte un score continuo en una decisión sí/no, y recién ahí cuenta aciertos y errores. Por eso un modelo perfecto con un umbral malo mide horrible, y por eso mirar la métrica antes de calibrar es engañarse.

El procedimiento razonable es este:

  1. Exporta o anota los scores de todas las imágenes normales del set de test y busca el percentil 99. Ese número es tu piso: por debajo de él vas a tener falsas alarmas seguidas.
  2. Busca el mínimo score entre las imágenes con falla. Ese es tu techo: por encima de él empiezas a perder detecciones.
  3. Si hay corredor entre ambos (acá: 33 y 44), pon el umbral cerca del medio, quizás un poco más arriba si te molestan más las falsas alarmas que una detección tardía. 40 sobre un corredor 33 a 44 deja margen para ambos lados.
  4. Si no hay corredor. el techo quedó bajo el piso. ningún umbral te va a salvar y el problema es de datos: falta variedad en las imágenes normales, o hay fallas mal etiquetadas.

Guarda esos números. Cuando cambies la iluminación o muevas la cámara vas a tener que rehacer este ejercicio, y tener el corredor anterior anotado te dice de inmediato cuánto se corrió tu normalidad.

La sorpresa: el modelo encontró un error humano

Un detalle quedó dando vueltas durante la calibración: una única imagen "normal" marcaba tercamente 62,8, en pleno territorio de anomalía. ¿Falsa alarma? Para nada.

Imagen de cámara con un hilo de filamento cruzado sobre la cama de impresión

En la foto se ve un hilo fino de filamento cruzando la cama hasta la boquilla: stringing real, que simplemente se pasó por alto al ordenar las imágenes de entrenamiento. El modelo encontró un error de etiquetado en sus propios datos de test.

Después de re etiquetar, el set de test queda con 21 anomalías, todas detectadas. Difícil pedir una confirmación mejor de que la detección no anduvo de pura suerte.

Vale la pena quedarse con la técnica, no solo con la anécdota: cuando un ejemplo etiquetado como normal puntúa alto de forma consistente, ábrelo y míralo antes de culpar al modelo. En detección de anomalías, los outliers persistentes del set "bueno" son el mejor detector de etiquetas equivocadas que vas a tener.

¿Aguanta la placa? 41 milisegundos

Queda por resolver si el UNO Q puede con el modelo. La página de Deployment lo calcula para la versión cuantizada (int8): 41 milisegundos por imagen y un archivo de 3,9 MB sobre el chip Qualcomm.

Para dimensionar: el vigilante va a revisar una imagen cada 15 segundos. Eso ocupa aproximadamente el 0,3% del tiempo de cómputo disponible. Hay muchísimo aire, tanto que si más adelante quieres bajar el intervalo a un par de segundos no vas a chocar con la placa.

Página de deployment del Studio de Edge Impulse con Arduino UNO Q como target y 41 ms de latencia

La exportación es un clic: en la página Deployment, elige el target Linux (AARCH64) y el build entrega el archivo .eim. La instalación en la placa queda para el capítulo siguiente.

Un apunte sobre la cuantización int8: convierte los pesos del modelo de coma flotante a enteros de 8 bits, lo que reduce tamaño y latencia de forma dramática a cambio de una pérdida de precisión numérica mínima. Para detección de anomalías esa pérdida es irrelevante en la práctica, pero sí desplaza levemente los scores. Si calibraste el umbral con el modelo flotante en el Studio y después corres el .eim cuantizado en la placa, revisa el corredor de nuevo antes de dar por buena la calibración.

Errores comunes y depuración

  • El entrenamiento se cae con ValueError: total size of new array must be unchanged: elegiste el bloque de anomalía de series de tiempo. Bórralo y agrega Visual Anomaly Detection (FOMO AD) desde Show all blocks.
  • El F1-score es pésimo pero la accuracy no tanto: casi siempre es umbral, no modelo. Anda a los scores crudos antes de tocar nada más.
  • Las imágenes no aparecen en Data acquisition: revisa que el API key en el script sea el del proyecto correcto; una cuenta con varios proyectos tiene una key distinta por proyecto.
  • Todas las imágenes de test puntúan alto: revisa que se hayan generado con la misma pipeline de cámara que las de entrenamiento. Cualquier diferencia de balance de blancos, rotación o recorte corre la distribución completa.
  • El Feature Explorer muestra una sola nube muy apretada: tu dataset es demasiado homogéneo. Junta imágenes de más impresiones, colores de filamento y horas del día antes de confiar en el umbral.

Variantes y mejoras

  • Recolección continua para reentrenar: en lugar de dejar el dataset congelado, haz que el sistema guarde en rotación las imágenes que quedan bajo el umbral durante la operación. Cuando cambies la luz, la posición de la cámara o el color de filamento, ya vas a tener material fresco para un reentrenamiento en vez de partir de cero. Es clave filtrar por umbral: si guardas todo, las fotos de una impresión fallida entran como "normales" y envenenan el modelo siguiente.
  • Replicar el concepto con una ESP32-CAM: si no tienes un UNO Q, el mismo flujo de Edge Impulse funciona con una ESP32-CAM, exportando como librería Arduino en vez de .eim. Vas a tener que bajar la resolución y aceptar una latencia bastante mayor, y la memoria del ESP32 obliga a un modelo más chico, pero para un intervalo de 15 segundos sobra. La calibración del umbral se hace igual: recolecta scores en operación normal y busca el percentil 99.
  • Correr el modelo en un mini PC o Raspberry Pi 5: el mismo proyecto exporta a Linux (x86_64) y Linux (AARCH64). Si ya tienes un servidor casero con Home Assistant, puedes dejar la cámara en la impresora y la inferencia en el servidor, lo que te libera la placa para otra cosa.
  • Registrar los scores en el tiempo: manda cada score a InfluxDB o a los propios recorders de Home Assistant y grafícalo. Ver la curva de scores de una impresión completa enseña muchísimo más sobre el umbral correcto que cualquier métrica agregada, y deja en evidencia si el score sube lentamente durante la impresión (señal de que la escena cambia de forma legítima).

Personalización para Chile

Este capítulo es casi todo software y no suma costo: el plan Developer de Edge Impulse es gratis y cubre entrenamiento, test y exportación para el UNO Q. Lo que sí necesitas es el equipo armado en los capítulos anteriores:

  • Placa principal Arduino UNO Q. es la placa del proyecto original; corre el modelo .eim compilado para Linux AARCH64.
  • Media Carrier para Arduino UNO Q. expone el conector CSI de la cámara.
  • Cámara IMX219 (Raspberry Pi Camera v2). el sensor usado para armar el dataset.
  • Cable plano FFC de 15 pines para cámara CSI. el largo importa según dónde montes la cámara.
  • Impresora 3D FDM con firmware Klipper. el equipo a vigilar; también fabrica el soporte de la cámara.
  • Iluminación constante (tira LED con su fuente). no es un accesorio opcional: la luz es parte de lo que el modelo aprende como normal.

En MechatronicStore encuentras localmente el grueso de estos componentes. cámaras compatibles con el conector CSI, cables FFC, tiras LED con fuente y placas de desarrollo. , sin importar ni esperar semanas de envío. Si no consigues el UNO Q, la ruta equivalente más accesible es una Raspberry Pi 5 con la misma cámara IMX219: el flujo de Edge Impulse es idéntico y el export para Linux (AARCH64) sirve para las dos.

Nota de esta versión: los enlaces directos a producto con precio y SKU no pudieron generarse en esta corrida porque el catálogo no estaba disponible al momento de escribir. Busca los componentes por su nombre en la tienda; las equivalencias descritas arriba se mantienen.

Recursos

Versión chilena inspirada en el trabajo original, con componentes en stock local en MechatronicStore.