Cuando hablamos de datos la mayoría de las personas piensa en datos estructurados: e.g., bases de datos relacionales, archivos CSV, Excel, etc.. Pero existe un mundo de datos no estructurados que abarca entre el 80% y 90% de toda la información disponible (fuente). Esta data no estructurada ha ido acumulando gran interés los últimos 10 años y ha sido el motor que ha impulsado el estudio y desarrollo de nuevos modelos que se están aplicando en varias industrias. Por ejemplo, vehículos autónomos, traducción de audio en videos, evaluación en la calidad de plantaciones agrícolas, detección de fake news en redes sociales, y muchos más.
Hoy nos enfocaremos en el mundo de las imágenes. Las imágenes se guardan en nuestros computadores como un tensor de 3 dimensiones que representan el Ancho, Alto, y por último el Número de canales (el más común RGB) que nos indican la combinación de colores que está en ella. Por ejemplo, una imagen a colores tiene un número de canales igual a 3, mientras que una imagen en blanco y negro, un número de canales igual a 1. Cuando se quiere trabajar con ellas, lo primero que hay que hacer es encontrar una representación vectorial (descriptor o feature) que no sea el tensor inicial y que capture las características que nos interesan para poder posteriormente entrenar un modelo y resolver el problema que estemos atacando, ya sea de clasificación, segmentación, detección de objetos, detección de acciones, seguimiento de objetos u otros.
Actualmente existen dos formas para transformar imágenes a uno o más vectores que capturen su esencia: la primera es utilizar o crear algún algoritmo diseñado específicamente para extraer features de una imagen (handcrafted-features), y la segunda es dejar que un modelo de machine learning (en general de la subarea del Deep-Learning) aprenda la mejor forma de representar las características de la imagen solo mirando los datos mientras entrena para realizar una tarea secundaria (learned-features).
En este blog conoceremos dos algoritmos clásicos para extraer features de una imagen. Pero, ¿por qué revisitar estos algoritmos antiguos siendo que el estado del arte utiliza redes neuronales para lograrlo? Si bien las redes neuronales son muy poderosas, también requieren de millones de datos para ser entrenadas y usan muchos más recursos computacionales que los algoritmos de procesamiento de imágenes más clásicos, por lo que nunca está demás conocer herramientas que nos permitan atacar problemas que involucren imágenes cuando estamos limitados ya sea por datos o recursos.
Los filtros de Gabor son filtros (o kernels) que al ser aplicados a una imagen son capaces de detectar los bordes y las texturas dentro de ella. Estos son combinaciones de una distribución gaussiana y sinusoides con parámetros que permiten variar el filtro en distintos aspectos, por lo que en general se usan varios en conjunto ya que no todos capturan lo mismo. La Figura 1 muestra los tipos de variaciones que pueden aplicarse a estos filtros, y en la Figura 2 podemos ver una representación de estos con variaciones en cuanto a su orientación y tamaño controladas por distintos parámetros que regulan cada una de las características que muestra la Figura 1, con excepción de la forma (shape) que es una extensión a los filtros originales.
Figura 1: Filtros de Gabor con variaciones en cuanto a distancia, escala, orientación, número ubicación y forma. (Fuente)
Figura 2: filtros con variaciones en el tamaño y orientación.
Pero ¿cómo se pueden utilizar estos filtros para trabajar con imágenes? Tal como se ve en la Figura 3, las imágenes resultantes dependen de la orientación y tamaño del filtro que se aplique y capturarán información diferente de ésta. Los ejemplos de la derecha logran capturar bien la textura del mar y la roca, mientras que la arena pareciera no verse afectada por el filtro. La ‘activación’ o imagen resultante luego de aplicar el filtro puede utilizarse como una feature que podría servir posteriormente para segmentar la imagen, clasificarla, o simplemente se pueden combinar a modo de preprocesamiento antes de aplicar alguna otra transformación sobre la imagen. En caso de utilizar las activaciones como features de entrada para otra imagen, es recomendable utilizar el filtro sobre una imagen más pequeña. Esto con el fin de evitar el uso excesivo de memoria y reducir los tiempos de procesamiento. Otra alternativa es sumar todos los valores de la imagen resultante, con lo que se obtendría un valor por cada filtro de Gabor aplicado, si es alto, el filtro se activa en varias partes de la imagen y nos entrega información valiosa del contenido.
Figura 3: Imagen original junto a activación de 4 filtros de Gabor diferentes
Otro uso de estos filtros es simplemente utilizarlos como un paso de preprocesamiento antes de aplicar un algoritmo de detección de bordes. A modo de ejemplo, en la Figura 4 se puede ver cómo cambian los resultados al preprocesar una imagen aplicando filtros de Gabor antes de realizar detección de bordes. Los resultados con los filtros de Gabor logran detectar mejor los bordes de la imagen sin introducir ruido de fondo.
Figura 4: Comparación de resultados entre imagen con 16 filtros de Gabor y sin Gabor antes de aplicar un algoritmo de detección de bordes (Canny filter [1] ).
Este es un método que permite extraer características de la textura de una imagen o dentro de una imagen, en base a la suposición de que tono y textura siempre van de la mano y en el cálculo de 14 métricas sobre la probabilidad de co-ocurrencia de los valores de pixeles adyacentes en una dirección predeterminada. Es decir, el cálculo de una matriz que nos indica la probabilidad de que una cierta combinación de pixeles ocurra en una dirección para todas las posibles combinaciones de valores. Por ejemplo, la probabilidad de que un pixel negro esté justo al lado derecho de uno blanco (pasar de 0 a 255) o viceversa en una misma dirección.
Como se ve en la Figura 5, hay 4 orientaciones en las que se calculan las matrices de co-ocurrencia, y una vez calculadas, se recomienda promediar las 14 métricas propuestas por Haralick además de calcular el rango (max – min) de éstas. El resultado es un vector con 28 valores que en teoría capturan la esencia de texturas en una imagen o parte de ella.
Figura 5: Direcciones en que se calcula la co-ocurrencia de pixeles dentro de una imagen. 1 y 5 es horizontal con 0°, 7 y 3 vertical con 90°, 6 y 2 con 135° y finalmente 4 y 8 con 45° (Fuente).
Por ejemplo, podría interesarnos analizar la textura en distintas partes de la imagen A de la Figura 6.
Figura 6: Imagen a ser analizada con las texturas de Haralick
A) Imagen original
B) Imagen en blanco y negro obtenida a partir del promedio de todos los canales (RGB)
C) Cuadrantes de la imagen a ase analizados con texturas de Haralick
Las texturas de Haralick están pensadas para funcionar solo en un canal de la imagen, por lo que se genera una versión en blanco y negro (Figura 6 B), que luego se subdivide en 100 cuadrantes de los cuales se extraen las texturas de Haralick. Como se puede ver en la Figura 7, cada cuadrante tiene distintos valores en el promedio de las 14 métricas que se calculan sobre la matriz de co-ocurrencia y pueden utilizarse como features para clasificar las texturas dentro de la imagen o la imagen misma.
Figura 7: Imagen Vs Histograma de métricas de Haralick.
A) Imagen original en escala de grises subdividida en 100 cuadrantes.
B) Histograma del promedio de las 14 métricas escaladas en cada cuadrante
Algunas áreas en las que se han utilizado las texturas de Haralick son en imagenología en el área médica, segmentación en mapas, entre otras.
Como vimos en este post, existen algoritmos sencillos capaces de extraer features de imágenes e incluso servir a modo de preprocesamiento. Por lo que, si por algún motivo no es posible utilizar redes neuronales, ya conocemos dos métodos que nos permiten extraer features desde una imagen.
Cada método tiene sus ventajas y desventajas, Haralick básicamente no requiere configurar ningún parámetro y es rápido de calcular. Y en segundo lugar los Filtros de Gabor, requieren una elección de parámetros cuidadosa y/o el uso de un gran banco de filtros que podría hacerlo la extracción de features inecesariamente lenta.
Los métodos que vimos se usan mucho en la detección de texturas. Ambos métodos pueden utilizarse de distintas formas dependiendo del objetivo que tengamos, podemos decidir extraer features de partes de una imagen o la imagen completa, hacer agregaciones y/o transformaciones de las activaciones o dejarlas tal cual dependiendo de lo que necesitemos.
En este blog se dieron intuiciones de como funcionan estos algoritmos y casos de uso muy particulares, lo importante es tener en mente que existen estos métodos más tradicionales y que los podemos utilizar para generar features que posteriormente se pueden usar para entrenar modelos de machine-learning y resolver problemas relacionados a imágenes.
[1] Algoritmos de detección de bordes que está fuera del scope de este post, solo se utiliza para ejemplificar una de las aplicaciones de los filtros de Gabor.