Curso de Integración Módulos Nativos iOS/Android para Flutter

Parseo de montos desde texto OCR con regex

Curso de Integración Módulos Nativos iOS/Android para Flutter

Contenido del curso

Acceso a sensores y cámara

Parseo de montos desde texto OCR con regex

Resumen

Extraer el total de un recibo desde una imagen es uno de esos retos donde la magia no está en el OCR, sino en lo que haces después con ese texto. Acá vas a aprender a procesar la salida del reconocimiento óptico, aplicar expresiones regulares y devolver un valor numérico limpio listo para usar en tu app.

Esta guía es para desarrolladores que ya tienen la extracción de texto resuelta y necesitan transformar ese texto crudo en un double confiable.

Cómo extraer el total desde el texto reconocido

La función parte del texto que ya devolvió el OCR y se construye como un método privado que recibe ese string como parámetro. La idea es clara: tomar todo lo que vino de la imagen y aislar solo los montos.

Para lograrlo, declaras una variable con la expresión regular que detecta números con formato monetario (incluyendo separadores de miles y decimales). Esa regex es la que hace el trabajo pesado de identificar qué fragmentos del texto son candidatos a ser un total.

Luego creas otra variable que guarda los matches, es decir, todas las coincidencias que la regex encontró dentro del texto. Aquí ya tienes una lista de posibles montos, pero todavía son cadenas, no números.

¿Qué hace una expresión regular en este caso? Busca patrones de texto que parecen números monetarios y los separa del resto del contenido del recibo, como fechas, nombres o descripciones.

Cómo mapear y limpiar los montos detectados

Una vez tienes los matches, viene el paso de convertirlos en valores numéricos reales. Aquí entra una función que retorna un double y aplica un .map sobre las coincidencias.

Dentro del map trabajas elemento por elemento. Para cada match haces lo siguiente:

  • Tomas el primer grupo con match.group(1) para acceder al valor capturado.
  • Validas si ese valor es nulo y, si lo es, retornas 0.0 para evitar que el parseo explote.
  • Reemplazas las comas por puntos usando replaceAll, porque el parser de double espera el punto como separador decimal.
  • Aplicas double.tryParse sobre la cadena ya limpia.

El detalle clave: la validación de nulo debe ir antes del replaceAll, porque esa función no acepta valores nulos. Si te saltas ese chequeo, vas a tener una excepción en tiempo de ejecución.

Como el resultado del map sigue siendo un iterable, lo conviertes en lista con .toList() para poder trabajarlo en el siguiente paso.

¿Por qué reemplazar comas por puntos? Porque en muchos formatos latinos la coma actúa como separador decimal, pero double.parse en Dart solo entiende el punto. Sin esa conversión, el parseo falla.

Cómo retornar el total final del recibo

Ya tienes una lista de doubles con todos los montos detectados. La pregunta es: ¿cuál es el total? La estrategia aquí es asumir que el total suele aparecer al final del recibo, así que se devuelve el último elemento de la lista.

La lógica final usa un operador ternario:

  • Si la lista no está vacía, retorna el último valor con .last.
  • Si la lista está vacía, retorna 0.0 como valor por defecto.

Eso te da una función robusta que nunca rompe la app, incluso cuando la imagen no contiene montos legibles.

¿Qué pasa si el recibo tiene varios montos? La función los captura todos en la lista y devuelve el último, que en la mayoría de recibos corresponde al total después de impuestos.

Conceptos clave que aparecen en la implementación

Para que todo esto tenga sentido, vale la pena reconocer las piezas técnicas que se conectan entre sí.

  • Expresión regular (regex): patrón que filtra los montos dentro del texto crudo del OCR.
  • Match.group: método que extrae el contenido capturado por la regex en una posición específica.
  • replaceAll: función que sustituye todas las apariciones de un carácter por otro, usada para normalizar separadores decimales.
  • double.tryParse: convierte una cadena en double y retorna null si la conversión falla, lo que la hace más segura que parse.
  • Validación de nulos: paso obligatorio antes de aplicar transformaciones de string para evitar excepciones.
  • toList: convierte el resultado de un map iterable en una lista manipulable.

Cada una de estas piezas resuelve un problema específico del flujo: detectar, capturar, limpiar, convertir y entregar.

En la próxima clase vas a montar la parte visual y de UI sobre esta lógica. ¿Qué otros casos de parseo de recibos te gustaría resolver con regex? Déjalo en los comentarios.