enero 26, 2022 10:00 am

Jesús

En este artículo aprenderemos sobre otras de las muy útiles aplicaciones de los histogramas de color: histogram matching.

Anteriormente hablamos de ecualización de histograma, y cómo a través de esta herramienta podemos mejorar el contraste de una imagen.

Bueno, con histogram matching vamos un paso más allá, ya que dada una imagen de referencia, podemos hacer que una imagen objetivo tenga la misma distribución de color que la de referencia, al actualizar el histograma de la primera, hasta que coincida con el de la segunda.

¿Suena difícil? Quizás, si quisieras implementar dicha operación desde cero, pero por fortuna no tenemos que hacerlo, ya que scikit-image lo hace por nosotros.

Al final de este post sabrás:

  • Qué es histogram matching y cómo funciona.
  • Cómo aplicar histogram matching con scikit-image.

¿Qué es Histogram Matching?

En el fondo, con histogram matching, lo que queremos es ajustar los píxeles de una imagen objetivo para que su distribución coincida con la de la imagen de referencia. En otras palabras, queremos hacer que sus CDFs coincidan.

Aunque suene complicado, es una técnica tan sencilla como útil.

Como su nombre indica, lo que buscamos con esta herramienta es hacer coincidir (“match”) los histogramas de color de dos imágenes.

O, en otros términos, si tenemos la imagen A y B, donde B es la referencia, iremos actualizando los píxeles de A hasta que su distribución de color coincida con la de B.

Es importante mencionar que el contenido de A no cambia, pero sí su distribución de píxeles, lo que conduce a cambios en:
  • Iluminación.
  • Contraste.

Entre las aplicaciones más comunes de histogram matching destacan:

  • Efectos estéticos: Al aplicar la distribución cromática de una imagen a otra, de cierta forma también estamos aplicándole su estilo.
  • Mecanismo rudimentario de corrección de color: Si tenemos varias imágenes de un mismo objeto o escena, tomadas a diferentes horas del día, o en condiciones de luz cambiante, podemos usar una imagen de referencia para lograr un “baseline” o iluminación estándar mediante histogram matching

La mejor manera de entender histogram matching es llenándonos las manos de código, así que pasemos a la siguiente sección.

Creación del Entorno de Desarrollo con Anaconda

Como ya es usual, veamos la estructura del proyecto:

Podemos notar que nuestro proyecto se compone de un único programa, datasmarts/match.py, que implementa y demuestra la lógica de histogram matching con skimage.

En el formulario de abajo hallarás el código:

Estando en la raíz del proyecto, ejecuta este comando para crear el ambiente de Anaconda:

conda env create -f skimage-histogram-matching

Esta es la configuración del ambiente recién creado (skimage-histogram-matching):

Para activar el ambiente, ejecuta:

conda activate skimage-histogram-matching

Con los preparativos completos, podemos implementar la solución.

Histogram Matching con scikit-image

Abre el archivo datasmarts/match.py, e importa las dependencias del proyecto:

Como usaremos matplotlib para manipular las imágenes, abajo creamos la función show_image(), la cual nos facilitará la tarea de mostrar una imagen en pantalla:

Esta función auxiliar lo que hace es desplegar una imagen en una ventana titulada usando el paquete pyplot de matplotlib.

A continuación, cargamos las imágenes objetivo y de referencia:

Mostramos ambas imágenes usando nuestra conveniente función show_image():

Para llevar a cabo histogram matching, llamamos a la función match_histograms(), la cual habita en el paquete exposure de scikit-image.

Esta función recibe los siguientes parámetros:

  • image: La imagen fuente u objetivo, es decir, la que transformaremos.
  • reference: La imagen de referencia usada para transformar la imagen objetivo.
  • multichannel: Un booleano que indica si las imágenes son multicanal (a color) o no.

Finalizamos mostrando el resultado en pantalla; consiguientemente cerramos las ventanas creadas a lo largo de la ejecución del script:

¡ATENTO!

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

Estando en la raíz del proyecto, corre el siguiente comando en tu terminal para invocar el programa:

python datasmarts/match.py

La primera imagen que veremos es de la torre Eiffel en un día nublado; esta es nuestra imagen objetivo:

Después, aparecerá la imagen de referencia, que no es otra que la misma torre Eiffel, pero en un día soleado:

En tercer lugar observaremos el resultado de la operación de histogram matching:

Como notamos, el contenido de la imagen no cambia, ya que se trata de la misma torre Eiffel en un día nublado de la imagen sin alterar.

No obstante, lo que sí cambió de forma considerable es la distribución de color de la misma, ya que toda la escena adquirió un tono azulado, lo cual tiene lógica, considerando que en la imagen de referencia, donde aparece la torre Eiffel en un día soleado y despejado, buena parte de la foto está caracterizada por el azul del cielo y del río Sena.

Interesante, ¿no te parece?

Resumen

En este artículo hemos aprendido sobre la existencia, funcionamiento y utilidad de histogram matching usando scikit-image.

Este técnica nos facilita redistribuir los píxeles de una imagen con base a la distribución de una imagen de referencia.

El resultado no cambia de forma alguna el contenido de la imagen original, pero sí su representación cromática, puesto que los elementos asociados al color de la imagen de referencia se trasladan a la imagen objetivo como consecuencia de hacer coincidir la distribución de píxeles subyacente.

Con histogram matching podemos mejorar la estética de nuestras imágenes, e incluso alcanzar un nivel mínimo de normalización de color, disminuyendo así los indeseados y nocivos efectos de una mala iluminación.

Esto es lo que debes recordar:

  • Para aplicar histogram matching, necesitamos una imagen objetivo y una imagen de referencia.
  • En scikit-image, histogram matching se aplica con la función exposure.match_histograms().
  • Si trabajamos con imágenes a color, debemos pasarle el parámetro multichannel=True; en caso contrario, multichannel=False.

No olvides descargar el código para que continúes experimentando por tu cuenta:

¡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.