Actualizado el

Lector de fichas DIAD: cómo una app empezó a convertir formularios físicos en datos


Lector de fichas DIAD: cómo una app empezó a convertir formularios físicos en datos

Los formularios son la base de la recolección de datos e información. Hoy se suelen hacer en línea, con las distintas herramientas disponibles. Sin embargo, todavía existen ocasiones en las que necesitamos formularios físicos para garantizar el llenado y la recolección de datos.

Sigue siendo una manera rápida y ágil de asegurar que se registró la información sin tener que consultar pantallas del sistema en ese momento. Claro, eso no garantiza que la información sea correcta. Tampoco evita el problema de leer después una escritura casi jeroglífica del registrante.

Esa necesidad impulsó la realización de la aplicación sobre la que va este post: Lector de fichas DIAD.

Hay otro punto que para mí es importante desde el inicio: no todo tiene que depender de modelos cerrados o servicios caros en la nube. La aplicación también permite trabajar con Ollama y modelos de pesos abiertos. Eso abre una ruta de procesamiento de bajo costo, e incluso local, cuando se cuenta con el equipo adecuado. Para instituciones que procesan muchas fichas, esa diferencia puede importar bastante.

El problema: pasar del papel a una tabla

La situación era fácil de entender. Había fichas físicas, llenadas a mano, que luego debían convertirse en datos útiles. Nombres, apellidos, documentos, teléfonos, correos, colegio, carreras de interés, casillas marcadas y firma.

Hacerlo a mano funciona cuando son pocas fichas. Pero cuando empiezan a acumularse, el trabajo se vuelve lento. Además, cada digitador puede interpretar la letra de una forma distinta. Un número puede parecer otro. Un correo puede quedar mal escrito. Una casilla marcada a medias puede generar duda.

La idea de la app fue sencilla de decir, pero no tan sencilla de resolver:

Tomar una ficha escaneada o fotografiada y convertirla en una fila de Excel, marcando qué datos parecen correctos y cuáles conviene revisar.

No se trataba de eliminar al humano. Se trataba de reducir la digitación repetitiva y dejar la revisión humana para los casos dudosos.

Primer paso: enseñar a la app dónde mirar

La primera versión del proyecto, según el historial del repositorio, ya nació con una estructura bastante completa. No empezó como una pantalla bonita. Empezó como una herramienta de línea de comandos capaz de procesar fichas escaneadas.

El primer problema era este: una computadora no sabe, por sí sola, dónde está el nombre, dónde está el DNI o dónde está la firma. Para una persona es obvio porque ve el formulario completo. Para un programa, la hoja es solo una imagen.

La solución fue usar una plantilla vacía de la ficha.

La app compara cada ficha escaneada contra esa plantilla. Si la hoja está un poco torcida, movida o con tamaño distinto, intenta alinearla. Es como poner una hoja encima de otra hasta que los bordes y secciones coincidan.

Luego entra el segundo elemento: un mapa de campos. En el proyecto se llama schema.yaml, pero podemos imaginarlo como una lista de rectángulos invisibles. Cada rectángulo dice: “aquí está el nombre”, “aquí está el teléfono”, “aquí está la casilla de egresado”, “aquí está la firma”.

Ese fue el primer aprendizaje importante: para leer bien un formulario físico, no basta con tener inteligencia artificial. También hay que decirle con claridad dónde debe mirar.

La calibración: mover rectángulos hasta que caigan bien

Al comienzo, definir esos rectángulos podía ser incómodo. Si una zona quedaba mal ubicada, la app podía leer la etiqueta impresa en vez de la respuesta manuscrita. O podía cortar una parte del texto. O podía revisar una casilla donde no correspondía.

Por eso apareció una herramienta visual de calibración. En lugar de editar números a ciegas, se podía abrir la plantilla en el navegador, mover recuadros y ajustar las zonas de lectura.

Esto cambió bastante el trabajo. Ya no era solo programar. Era mirar la ficha como la miraría una persona encargada de procesarla y preguntarse:

  • ¿Este recuadro cubre la zona escrita?
  • ¿Está tomando solo la respuesta o también el texto impreso?
  • ¿La casilla está bien centrada?
  • ¿La zona de firma sirve para saber si alguien firmó?

Ese tipo de ajustes parece pequeño, pero determina si la app ayuda o estorba.

El primer lector no era suficiente

Una vez que la app sabía dónde mirar, venía el siguiente problema: leer lo que las personas escribieron.

Aquí apareció una dificultad esperable. Los OCR tradicionales funcionan mejor con texto impreso. Pero las fichas tenían escritura manual. Algunas letras eran claras. Otras no tanto. Algunos correos estaban bien escritos. Otros mezclaban mayúsculas, puntos, guiones o trazos difíciles.

Por eso el proyecto empezó a incorporar modelos de visión y lenguaje. En vez de pedirle a un OCR clásico que reconociera letras sueltas, se podía mostrar una parte de la ficha a un modelo capaz de entender imágenes y texto.

En el historial aparecen integraciones con Gemini, Claude, Qwen, OpenAI y también alternativas locales como Ollama y PaddleOCR.

Para una persona no técnica, la idea sería esta: la app fue probando distintos “lectores”. Algunos viven en la nube y suelen leer mejor. Otros corren en la computadora o en una red local, lo que ayuda cuando los datos no deberían salir a internet.

Ahí entra con fuerza Ollama. Poder usar modelos de pesos abiertos permite procesar fichas sin pagar por cada llamada a un proveedor externo, o al menos reducir mucho ese costo. No siempre será la opción de mejor calidad, y depende de la memoria o GPU disponible, pero da una alternativa real para escenarios donde el presupuesto o la privacidad pesan más.

Leer campo por campo era caro y lento

Al inicio, una forma natural de resolver el problema era enviar cada campo por separado: primero nombres, luego apellido, luego documento, luego correo, y así sucesivamente.

Eso funciona, pero tiene un costo. Si una ficha tiene treinta campos, el sistema puede terminar haciendo muchas consultas por una sola hoja. Multiplica eso por cientos de fichas y el proceso se vuelve más lento y más caro.

Entonces apareció uno de los cambios más importantes: el modo de página completa.

En vez de preguntar campo por campo, la app le muestra la ficha completa al modelo y le pide que devuelva todos los datos de una vez. Es parecido a darle la hoja entera a una persona y pedirle que llene una tabla.

Ese cambio mejoró dos cosas:

  • redujo la cantidad de llamadas necesarias por ficha;
  • permitió que el modelo entendiera mejor el contexto completo del formulario.

Por eso el proyecto terminó usando gemini-full como opción por defecto: una llamada por ficha, con buen equilibrio entre velocidad, costo y calidad. Aun así, la ruta con Ollama quedó como una pieza importante porque permite explorar procesamiento local o de menor costo usando modelos abiertos.

Las casillas también tenían sus trampas

Leer texto manuscrito era solo una parte del problema. Las casillas marcadas también necesitaban cuidado.

Una casilla impresa ya tiene tinta. Si el sistema solo mide “hay tinta o no hay tinta”, puede confundirse y creer que una casilla vacía está marcada.

La solución fue comparar la ficha llenada con la plantilla vacía. Si la casilla tiene más tinta que la plantilla, probablemente alguien la marcó. Si se ve igual que en blanco, no debería contarse como marcada.

Esto fue especialmente útil para opciones como “Soy escolar” o “Soy egresado”. También obligó a ajustar pruebas, porque una marca demasiado pequeña no se comporta igual que una marca real hecha por una persona.

Ese detalle muestra algo importante: una app de este tipo no se construye solo escribiendo código. Se construye probando con fichas reales y viendo dónde se equivoca.

La firma: validar presencia sin guardar el trazo

Otra decisión interesante fue la firma. La app no necesitaba exportar la imagen de la firma al Excel. Eso podía ser innecesario e incluso delicado por privacidad.

Lo que sí necesitaba era saber si la ficha parecía firmada o no.

Entonces la firma se trató como una validación. La app revisa si en la zona de firma hay suficiente diferencia frente a la plantilla vacía. Si no encuentra firma, marca el registro para revisión.

El resultado es práctico: el Excel no se llena de imágenes sensibles, pero el equipo puede saber qué fichas requieren atención.

El sistema aprendió a decir “revisar”

Uno de los aciertos del proyecto es que no intenta fingir seguridad absoluta.

La salida no es solo una tabla con datos. También incluye un estado:

  • CORRECTO, cuando la alineación y los campos parecen confiables.
  • REVISAR, cuando hay baja confianza, firma ausente o alguna duda.
  • ERROR, cuando algo falló de forma más seria.

Esto es importante porque la app no debe inventar certeza. Si un correo no se lee bien, si falta una firma o si una ficha está mal alineada, lo correcto no es llenar cualquier cosa. Lo correcto es avisar.

En el historial también aparece una mejora específica para evitar datos inventados en fichas vacías. Ese problema es común con modelos de IA: si no se les controla bien, pueden completar algo aunque el campo esté vacío.

La app tuvo que aprender una regla básica: si no hay dato, no hay que inventarlo.

También hubo que separar lo local de lo que va a la nube

Otro aprendizaje fue la privacidad.

Si se procesan formularios con datos personales, importa mucho saber dónde se están leyendo esas imágenes. No es lo mismo usar un modelo en la nube que usar uno instalado localmente.

Por eso el proyecto terminó separando opciones como:

  • Gemini, Claude u OpenAI, cuando se acepta enviar la imagen a un proveedor externo.
  • Ollama local, cuando se quiere procesar en una computadora o servidor propio.
  • Ollama cloud, cuando se quiere usar un modelo alojado por Ollama.
  • PaddleOCR, como opción local más clásica.

La separación entre ollama-local y ollama-cloud fue una mejora de claridad. Antes, un nombre ambiguo podía confundir. Después quedó más claro si los datos se quedaban en el equipo o salían a una nube.

Para una organización, esa diferencia no es menor. A veces el mejor modelo no es el que lee mejor, sino el que cumple mejor con las reglas de privacidad del caso.

También hay una razón económica. Si el volumen de fichas crece, pagar por cada procesamiento puede volverse relevante. Con Ollama y modelos de pesos abiertos, existe la posibilidad de asumir más procesamiento propio y bajar el costo por ficha, siempre que la infraestructura alcance.

El comando doctor: revisar antes de procesar

Otra mejora útil fue el comando doctor.

La idea es parecida a una revisión médica rápida, pero para la instalación. Antes de procesar fichas, el sistema puede revisar si están las dependencias, si la plantilla existe, si los modelos están disponibles o si las claves de API fueron configuradas.

Esto ayuda porque muchos errores no aparecen por la ficha en sí, sino por el entorno:

  • falta una dependencia para convertir PDFs;
  • no se descargó un modelo;
  • no existe una clave de API;
  • la plantilla no está donde debería;
  • el servidor local de Ollama no está respondiendo.

Un diagnóstico previo evita perder tiempo buscando el problema en el lugar equivocado.

De la línea de comandos al navegador

El proyecto empezó como una herramienta de línea de comandos. Eso está bien para pruebas, automatización o usuarios técnicos. Pero si se quiere mostrar a más personas, o facilitar su uso, una pantalla ayuda.

En el historial del repositorio aparece un cambio reciente: una web app con Streamlit para procesar fichas desde el navegador.

Esto no cambia la idea de fondo. La app sigue alineando fichas, leyendo campos y entregando resultados. Pero la experiencia se vuelve más cercana para alguien que no quiere escribir comandos. Puede cargar archivos, elegir opciones y descargar resultados.

Ese paso suele ser importante en proyectos internos: primero se demuestra que la lógica funciona; después se mejora la forma de usarla.

Qué entrega finalmente la app

El resultado esperado es bastante concreto.

La app recibe imágenes o PDFs de fichas. Luego produce un archivo Excel o CSV con los datos extraídos. También agrega columnas de confianza, estado, motivo de revisión, archivo de origen y página.

Además, puede guardar imágenes de depuración: una ficha alineada y otra con los recuadros dibujados sobre los campos. Eso sirve para entender por qué leyó bien o mal una ficha.

Para mí, esa parte es clave. Una herramienta de IA que solo entrega un resultado sin explicación obliga a confiar a ciegas. En cambio, una herramienta que muestra qué zona leyó permite revisar, corregir y mejorar.

Lo que esta implementación deja como aprendizaje

La historia de esta app muestra algo que se repite mucho en proyectos de IA aplicados a problemas reales: la parte difícil no es solo “usar un modelo”.

La parte difícil es ordenar el proceso completo:

  • tener una plantilla confiable;
  • saber dónde están los campos;
  • calibrar con ejemplos reales;
  • distinguir texto, casillas y firma;
  • aceptar que algunos casos deben revisarse;
  • evitar que la IA invente datos;
  • decidir cuándo usar nube y cuándo usar procesamiento local;
  • aprovechar modelos abiertos cuando el costo o la privacidad lo justifican;
  • entregar un Excel que el equipo realmente pueda usar.

El Lector de fichas DIAD no nació como una solución perfecta. Fue creciendo a medida que aparecían problemas: fichas torcidas, casillas ambiguas, letra difícil, costos por llamadas, privacidad, campos vacíos, necesidad de auditoría y facilidad de uso.

Ese recorrido es lo más valioso. La aplicación no intenta reemplazar todo el proceso humano. Intenta quitar la parte más repetitiva y dejar señales claras sobre lo que necesita revisión.

Repositorio

El proyecto está en GitHub como DIAD-PUCP/lector-fichas-diad:

Por ahora el repositorio es privado, pero se puede solicitar acceso si alguien necesita revisarlo, probarlo o colaborar con el desarrollo.

Recursos

  • README del proyecto: README.md
  • Guía de demostración: demostracion-lector-fichas.md
  • Configuración de campos: config/schema.yaml
  • Guía de calibración: config/CALIBRACION.md