febrero 25, 2022 10:00 am

Jesús

En el artículo pasado hablamos largo y tendido sobre cómo, en muchas ocasiones, tenemos que procesar profundamente una imagen con OpenCV, para poder escanear exitosamente el texto presente en ella con la ayuda de Tesseract.

Sin embargo, estoy seguro de que convendrás conmigo en que el ejemplo en dicho artículo era demasiado abstracto.

Por tal razón, hoy nos abocaremos a crear una aplicación que fácilmente tendría gran acogida en el mundo real: ¡Un escáner de pasaportes!

Al final de este post sabrás:

  • Qué es la MRZ en un pasaporte y qué datos contiene.
  • Cómo usar técnicas de procesamiento de imágenes para localizar texto en una imagen, específicamente pasaportes.
  • Extraer el texto localizado usando Tesseract.

¿Estás listo? Comencemos, pues.

¿Qué es la MRZ en un Pasaporte?

Un pasaporte no es más que un documento de identidad parecido a un librito, que se usa principalmente en viajes internacionales.

Cuando vas a otro país, los oficiales de inmigración validan que los datos en tu pasaporte sean correctos y que, en efecto, tú seas quien dices ser.

Anteriormente esta validación era manual, lo que hacía el proceso de inmigración algo largo, cansón y tedioso. 

Afortunadamente, desde hace varios años, la mayoría de los pasaportes del mundo incluyen unas líneas especiales en la parte inferior, conocidas como Machine-Readable Zone o MRZ. Estas líneas almacenan de forma comprimida data como:
  • Nombre.
  • Número de pasaporte.
  • Nacionalidad.
  • Sexo.
  • Fecha de nacimiento o edad.
  • Fecha de expiración del documento.

En las próximas secciones nos centraremos en crear una solución capaz de detectar y extraer el código de la MRZ de un pasaporte.

Bastante cool, ¿no te parece? 😉

Creación del Entorno de Desarrollo con Anaconda

Esta es la estructura del proyecto que hoy nos ocupa:

El archivo más importante es datasmarts/read_passport.py, que como su nombre indica, contiene la implementación del escáner de pasaportes.

Para descargar el proyecto, simplemente llena el siguiente formulario con tus datos:

Lo siguiente que haremos es crear y configurar el entorno de Anaconda, para lo que primero deberemos ubicarnos en la raíz del proyecto. Desde ahí ejecuta este comando:

conda env create -f pytesseract-passport-reader

La configuración del ambiente (pytesseract-passport-reader) es esta:

Para activar el ambiente, ejecuta:

conda activate pytesseract-passport-reader

Continuemos.

Cómo Escanear Pasaportes con Tesseract y OpenCV

¿Estás preparado para comenzar a implementar? Si es así, abre el archivo datasmarts/read_passport.py, y coloca estas líneas, las cuales importan las dependencias del programa:

Después, definimos los argumentos del script, que en este caso es solo uno, -i, la ruta a la imagen de entrada:

Cargamos la imagen, la convertimos a escala de grises y la mostramos en pantalla:

Extraemos sus dimensiones:

Creamos dos kernels o filtros, el primero rectangular, y el segundo cuadrado, los cuales usaremos más adelante en varias operaciones con OpenCV:

Para eliminar detalles y ruido, pasamos un filtro Gaussiano de 3x3:

Aplicamos Black Hat, una operación que nos sirve para hallar las regiones oscuras sobre un fondo blanco, lo cual tiene sentido, ya que los caracteres en la MRZ suelen ser negros, mientras que el fondo del pasaporte tiende a ser más claro:

Calculamos el gradiente usando Scharr, lo que nos servirá para hallar bordes y otras regiones de interés. También aprovechamos para normalizar el resultado en el rango [0, 255]:

Llevamos a cabo una clausura para cerrar los espacios entre las letras, y así facilitar su reconocimiento más adelante. Para esto, usamos el kernel rectangular creado previamente:

Hacemos otro pase de clausura con el kernel cuadrado, el cual es más fino que el rectangular por ser más pequeño. Adicionalmente, rompemos componentes conectadas típicamente relacionadas con blobs de píxeles que son solo ruido mediante dos erosiones consecutivas:

Procedemos a encontrar todos los contornos. Luego los ordenamos de abajo hacia arriba.

¿Por qué hacemos esto? Pues porque de antemano sabemos que todos los pasaportes contienen su MRZ en la parte de abajo, así que definitivamente la zona de interés se encontrará en el fondo de la imagen:

Iteramos sobre los contornos para hallar la MRZ. Si entre ellos encontramos uno cuya anchura sea de al menos el 80% del ancho de la imagen, y su altura de por lo menos el 4% del alto de la imagen, asumimos que es la MRZ:

Si no encontramos un contorno que satisfaga esta condición, concluimos que no hay MRZ en la imagen, bien porque necesita más procesamiento, o simplemente porque no se corresponde a un pasaporte:

Para incrementar las chances de que Tesseract pueda leer el texto en la MRZ, añadimos “padding” o márgenes a los bordes de la región. Esto lo hacemos para que ningún caracter quede demasiado pegado al borde:

Extraemos la región donde se halla la MRZ de la imagen original:

Usamos Tesseract para extraer el texto de la MRZ, y lo imprimimos en la consola:

Mostramos la MRZ y destruimos todas las ventanas creadas durante la ejecución del programa:

¡ATENTO!

Antes de ejecutar el código, asegúrate de hallarte en la raíz del proyecto para que los comandos funcionen correctamente.

Para correr el programa, ejecuta esta instrucción en tu terminal:

python datasmarts/read_passport.py -i passport.jpg 

Veremos la imagen del pasaporte en escala de grises:

Después el resultado de aplicar Black Hat que, como vemos, realza los caracteres mientras que disminuye los detalles del fondo:

Luego observamos el resultado de hallar los gradientes usando Scharr:

Con la clausura rectangular, unimos todos los caracteres y demás elementos en componentes conectadas, las cuales se ven como grandes manchas o áreas blancas:

La clausura con el filtro cuadrado crea regiones aún más grandes. Lo interesante es que las dos líneas del fondo, ahora se unieron para formar un único rectángulo blanco:

Ahora vemos la MRZ que logramos extraer después de tanto procesamiento:

Y en la consola vemos lo que Tesseract logró leer:

MRZ: P<GBRUNITEDSKINGDOM<FIVE<<JODIEKPIPPAL<L<<L<<L
10718570326BR8501178F1601312<<<<<<<<<<<<<<02

Cerca, pero no es exactamente lo que dice el pasaporte. Algunos < se mezclaron con las letras, dando origen a caracteres que no existen en la imagen.

Un reto interesante sería que lograras mejorar la lectura de Tesseract, bien mediante más procesamiento con OpenCV, o ajustando las opciones de PyTesseract.

¿Te animas?

Resumen

Hoy aprendimos sobre las MRZ en los pasaportes, y cómo éstas se utilizan para codificar información vital sobre el titular, como su nombre, edad y sexo, a la vez de que ayudan a agilizar los trámites migratorios en aeropuertos, puertos y demás puestos fronterizos.

Posteriormente, implementamos un escáner o lector de pasaportes con la ayuda de OpenCV y Tesseract.

Como hemos aprendido en los últimos artículos, estas tecnologías forman un tándem de cuidado cuando se trata de crear pipelines complejos para la extracción de texto.

¿Qué te pareció el post de hoy? ¿Te animas a probar el código con una imagen de tu propio pasaporte? Si es así, no olvides descargarlo abajo:

¡Adiós!

Sobre el Autor

Jesús Martínez es el creador de DataSmarts, un lugar para los apasionados por computer vision y machine learning. Cuando no se encuentra bloggeando, jugando con algún algoritmo o trabajando en un proyecto (muy) cool, disfruta escuchar a The Beatles, leer o viajar por carretera.