abril 8, 2022 10:00 am

Jesús

Si algo hemos aprendido en nuestro prolongado estudio de computer vision, y especialmente de OCR, es que las condiciones iniciales tienen un impacto enorme en la calidad de los resultados.

Por este motivo, hoy aprenderemos a resolver o, al menos, mitigar uno de los problemas más comunes en el procesamiento de imágenes: deformaciones.

Concretamente, deformaciones en términos de alineación y perspectiva.

Para ilustrar tanto la problemática como la efectividad de nuestra solución, nos centraremos en la alineación de documentos.

Al finalizar este post, sabrás:

  • Qué es la alineación y por qué es importante.
  • Cómo calcular y puntos clave y descriptores locales invariantes utilizando el algoritmo ORB.
  • Cómo alinear una imagen con base a una plantilla, utilizando una matriz de homografía.

Nos espera un proyecto bien interesante, ¿estás listo?

¡Comencemos!

¿Por Qué es Importante Alinear Imágenes y Documentos?

Los seres humanos somos absurdamente buenos detectando patrones visuales. 

No es casualidad que buena parte de nuestro cerebro esté dedicada enteramente a nuestro sentido de la vista.

Sin embargo, es por esta misma razón que nos cuesta entender por qué ciertas tareas, en apariencia triviales, como saber que el ángulo en el que vemos un objeto no afecta su identidad (es decir, si vemos una pelota desde arriba, desde abajo o de frente, sigue siendo la misma pelota), resultan tan complejas para una computadora.

Para disminuir las probabilidades de que el computador erróneamente clasifique o tome dos imágenes de un mismo objeto capturadas con ángulos ligeramente diferentes como fotos de objetos diferentes, llevamos a cabo ciertas transformaciones.

Una de tales transformaciones es la alineación, la cual consiste en:

  1. 1
    Aceptar dos imágenes que contienen el mismo objeto pero en ángulos distintos.
  2. 2
    De forma automática calcular la matriz de homografía usada para alinear las imágenes.
  3. 3
    Utilizar la matriz de homografía para transformar la perspectiva de una imagen con respecto a la otra.

Si todo esto suena un poco confuso, no te preocupes, ya que cuando lleguemos a la demostración los conceptos quedarán más claros.

Pasemos a la siguiente sección, donde configuraremos nuestro entorno de desarrollo.

Creación del Entorno de Desarrollo con Anaconda

En la siguiente imagen verás los archivos que componen nuestro proyecto de hoy:

Nuestra implementación vivirá en el archivo datasmarts/align_document.py

En la carpeta images tenemos tanto la plantilla como las imágenes que buscaremos alinear con nuestro algoritmo.

Puedes descargar el proyecto llenando el formulario de abajo:

Para crear el entorno de desarrollo con Anaconda, primero ubícate en la raíz del proyecto, y después ejecuta la siguiente instrucción en la consola:

conda env create -f opencv-document-alignment-registration

La configuración del ambiente (opencv-document-alignment-registration) es esta:

Para activar el ambiente, corre este comando:

conda activate opencv-document-alignment-registration

¡Listo! Prosigamos.

Alineación de Documentos con OpenCV

Comencemos la implementación abriendo el archivo datasmarts/align_document.py, e inserta estas líneas, las cuales importan las dependencias del programa:

Ahora, definimos la función auxiliar, align_images(), la cual contiene la lógica necesaria para alinear una imagen con respecto a una plantilla, siguiendo el procedimiento descrito al principio del artículo:

Comenzamos convirtiendo ambas imágenes a escala de grises:

Luego, instanciamos el detector ORB, y lo usamos para extraer los puntos clave y los descriptores de las dos imágenes:

Como vimos,  le pasamos el valor max_features a la función cv2.ORB_create(), lo que significa que, a lo sumo, el detector tomará en cuenta 500 (valor por defecto) puntos clave. Esto lo hacemos para filtrar puntos clave deficientes.

Emparejamos los descriptores de la imagen y la plantilla, ordenando las parejas por distancia (de menor a mayor, entendiendo que si la distancia de una pareja es pequeña, mayor es su similitud y, por tanto, dicha pareja nos ayudará más al momento de alinear):

Nos quedamos solo con el top 20% de las parejas:

Si el parámetro debug es True, visualizamos los keypoints, trazando una línea para unir cada punto clave en la imagen con su correspondiente en la plantilla:

Iteramos sobre los emparejamientos para mapear los puntos de una imagen con los de la otra:

Hallamos la homografía entre las dos colecciones de puntos. Dicha homografía es una matriz que nos permitirá alterar la perspectiva de la imagen original, para que coincida con la de la plantilla (o, en resumidas cuentas, alinear la imagen con la plantilla):

Por último, usamos la homografía para transformar la imagen de entrada, y la retornamos:

Finalizada la implementación de align_images(), procedemos a crear el menú del programa, compuesto por los parámetros -i/--image, y -t/--template, las rutas a la imagen y a la plantilla, respectivamente:

Cargamos las imágenes y las mostramos:

Alineamos la imagen con relación a la plantilla, usando la función auxiliar align_images():

Redimensionamos la imagen alineada y la plantilla:

Crearemos dos visualizaciones para inspeccionar visualmente el resultado de la alineación. La primera consiste de juntar la plantilla y la imagen alineada en un mismo arreglo, para mostrarlas una al lado de la otra:

Para la segunda visualización, superponemos la imagen alineada sobre la plantilla. Esto nos permitirá ver qué tan lejos está una imagen de la otra en términos de perspectiva:

Finalmente, mostramos ambas visualizaciones, y destruimos las ventanas creadas hasta los momentos:

¡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 sobre una de las imágenes de ejemplo, ejecuta esta instrucción en tu terminal:

python datasmarts/align_document.py -i images/scan_01.jpg -t images/form_w4.png

En principio veremos la imagen que buscamos alinear:

Así como la plantilla:

Acto seguido, veremos cómo los keypoints de una imagen se unen mediante líneas con los keypoints correspondientes en la otra imagen. Esto nos da una idea de cuales son los puntos de interés que nuestro programa usará para alinear la imagen con respecto a la plantilla:

Luego, veremos la imagen alineada versus la plantilla:

Como podemos notar, el resultado fue bastante exitoso, pero aún hay margen de mejora, como evidenciamos en la próxima visualización:

La imagen de arriba es el resultado de superponer la foto del formulario alineada sobre la plantilla. Si el resultado hubiese sido perfecto, no notaríamos diferencia alguna, pero la presencia de sombras y “visión doble” en algunas partes del formulario nos indica que podríamos refinar aún más nuestro programa.

Resumen

Hoy aprendimos sobre la importancia y utilidad de alinear nuestras imágenes antes de llevar a cabo determinadas acciones, como extraer texto de las mismas, ya que en la inmensa mayoría de los casos en computer vision, las condiciones iniciales tienen una enorme influencia en la calidad de los resultados.

En especial, nos centramos en la alineación de documentos como vehículo para entender el concepto de la alineación de imágenes a nivel particular.

La solución que desarrollamos consta de los siguientes tres pasos:

  1. 1
    Aceptar dos imágenes que contienen el mismo objeto pero en ángulos distintos.
  2. 2
    De forma automática calcular la matriz de homografía usada para alinear las imágenes.
  3. 3
    Utilizar la matriz de homografía para transformar la perspectiva de una imagen con respecto a la otra.

Una vez implementado y evaluado nuestro programa, nos dimos cuenta de que a pesar de su considerable efectividad, aún hay margen de mejora.

Así, pues, ¿por qué no te animas a descargarte el código y ver si puedes mejorar lo que hemos implementado en el post de hoy?

¡Hasta luego!

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.