septiembre 1, 2021 10:00 am

Jesús

Inpainting es una técnica de computer vision ideada para recuperar imágenes que se hayan visto alteradas por daños, desgaste o información faltante. 

Si bien este es un tema que ya tocamos cuando hablamos sobre cómo llevar a cabo inapinting con OpenCV, me pareció una buena oportunidad para revisitar esta técnica, esta vez usando scikit-image, otra de las herramientas por excelencia en computer vision.

Al final de este post sabrás:

  • Cómo funciona en líneas generales un algoritmo de inpainting.
  • Cómo llevar a cabo inpainting en scikit-image.

¿Preparado? Genial, pongámonos manos a la obra.

¿Cómo Funciona el Inpainting?

Como bien mencionamos en el este artículo sobre inpainting en OpenCV, no existe un único mecanismo o un método universal de restauración de imágenes.

No obstante, en general, todos los algoritmos llevan a cabo variaciones de estos pasos:

  1. 1
    Las secciones dañadas se rellean usando información de los píxeles que las rodean.
  2. 2
    La estructura de color que rodea una zona afectada se extiende para ocupar el borde de la región faltante haciéndola, en efecto, más pequeña (imagina que las regiones dañadas se “rellenan” con el color de los píxeles vecinos).
  3. 3
    Se pintan los pequeños detalles en aras de preservar la uniformidad.

En scikit-image contamos únicamente con un método basado en ecuaciones biarmónicas, pero por fortuna, no necesitamos matricularnos en cálculo avanzado para poder hacer uso del mismo ?.

Sin nada más que agregar en lo que a teoría respecta, procedamos a implementar nuestra solución.

Creación del Entorno de Desarrollo con Anaconda

Echémosle un vistazo rápido a la estructura del proyecto:

Como notarás, el único archivo de interés es datasmarts/inpaint.py, pues allí vive nuestra implementación.

Las imágenes de prueba que usaremos para evaluar nuestra solución se encuentran en la carpeta resources.

Para crear el ambiente de Anaconda, corre este comando en tu terminal:

conda env create -f env.yml

Esta instrucción creará un ambiente llamado skimage-inpainting, correspondiente al siguiente archivo de configuración:

Lo que resta es activar el ambiente de la siguiente manera:

conda activate skimage-inpainting

Excelente, podemos continuar.

Cómo Restaurar Imágenes con Inpainting en scikit-image

Abre el archivo datasmarts/inpaint.py, e inserta las siguientes líneas para importar las dependencias:

Nuestro script es bastante ligero en lo que a dependencias se refiere, ya que únicamente nos valremos en OpenCV y scikit-image, aparte de ArgumentParser para, como de costumbre, definir el menú del programa.

El módulo inpaint ubicado en skimage.restoration contiene la función que implementa el método de inpainting biarmónico que veremos en breve.

En el siguiente extracto configuramos los argumentos de entrada de nuestro script:

  • -i/--image: Define la ruta a la imagen de entrada a ser restaurada.
  • -m/--mask: Define la ruta a la imagen usada como máscara para la restauración.

Cargamos la imagen a reparar:

Y la máscara que nos servirá para ubicar las regiones de la imagen dañada a restaurar:

Nota que la máscara tuvimos que pasarla a escala de grises.

También vale mencionar que aunque usaremos scikit-image para aplicar el inpainting per se, nos valemos de OpenCV para cargar y mostrar las imágenes.

¿Por qué, te preguntas? Pues, honestamente, me parece más fácil trabajar con OpenCV en lo que a I/O de imágenes respecta, aunque bien podrías usar únicamente scikit-image de principio a fin si así lo prefieres.

Para llevar a cabo la restauración de la imagen como tal, llamamos a la función inpaint.inpaint_biharmonic(), teniendo especial cuidado de pasarle multichannel=True, puesto que estamos trabajando con imágenes a color:

Transformamos el resultado a un formato entendible por OpenCV (esto es, un arreglo multidimensional de enteros sin signo) mediante la función img_as_byte():

Por último, mostramos la imagen dañada, la máscara, y el resultado del inpainting:

Podemos correr el programa como sigue:

python ./datasmarts/inpaint.py -i ./resources/damaged.jpg -m ./resources/mask.jpg

Al cabo de unos pocos segundos veremos varias imágenes en pantalla. La primera es la foto que deseamos restaurar:

imagen-a-restaurar

Imagen dañada

A mano derecha observamos varios trazos en blanco que claramente no tienen nada que ver con el paisaje de la foto.

Luego, nos toparemos con la máscara:

Máscara

Máscara

No es más que una imagen binaria en la que las zonas en blanco indican los píxeles en la imagen original que queremos recuperar.

Si te preguntas cómo obtuve esta máscara, simplemente usé Paint. Es un proceso bien tedioso, la verdad. 

También se podría hacer de forma programática, aunque lo más probable es que me hubiera consumido más tiempo.

La última imagen que veremos es el resultado de aplicar inpainting:
Resultado

Resultado

Si bien se taparon en su mayoría los trazos blancos que hice adrede, un vistazo más cercano revela que el resultado podría mejorar.

Para empezar, aún se nota un manchón blanco en la derecha. Este puede deberse a una limitación del algoritmo de inpainting, o a una mala máscara (en cuyo caso puedes echarme la culpa ?).

Luego, en el cielo y en las olas vemos que a pesar de haberse rellenado los daños con colores similares a los de los píxeles vecinos, no se alcanzó un resultado uniforme, homogéneo.

La conclusión es que el inpainting, al menos basado en algoritmos más artesanales como este, es una herramienta útil, aunque limitada.

Necesitamos más poder, ¿pero cómo?

¡Deep learning, por supuesto! Aunque eso ya es tema para otro artículo.

Resumen

El día de hoy aprendimos a aplicar inpainting o, en español, restauración de imágenes, usando scikit-image.

Siempre que queramos aplicar inpainting necesitaremos dos ingredientes:
  1. 1
    Una imagen dañada que queramos restaurar.
  2. 2
    Una máscara binaria que indica las regiones de la imagen que se deben reparar.

Luego es cuestión de escoger entre los diversos métodos a nuestra disposición para llevar a cabo la tarea. No obstante, cabe mencionar que, al momento de escribir este artículo, scikit-image solo implementa inpainting basado en ecuaciones biarmónicas.

Si quieres más opciones, te recomiendo leer este artículo sobre inpainting en OpenCV, puesto que éste ofrece dos alternativas aparte de las ecuaciones biarmónicas.

Si deseas descargar el código del proyecto, puedes hacerlo en el formulario de abajo:

¡Hasta pronto!

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.

Paso 2/2: Celebra tu NUEVO EMPLEO en Machine Learning ?

A %d blogueros les gusta esto: