Arrancamos este artículo presentando la importancia de los filtros en el Procesamiento de Imágenes frente a su uso en las Redes Neuronales Convolucionales.

Los filtros constituyen una etapa importante en el procesado de imágenes como ser: suavizado y realcé de la imagen, eliminación de ruido, detección de bordes, y más. Desde un punto de vista matemático, el aplicar un filtro representa la convolución entre un kernel y la imagen (un arreglo de 3 capas que hacen referencia a los colores RGB).

Filtros conocidos y sus aplicaciones

- Filtro Gaussiano: Sirve para difuminar y eliminar ruido en las imágenes. Para que te formes la idea, se usa para difuminar las placas de los autos en los Reality Shows, tapar la cara de los niños en reportajes de Guerra, y muchas aplicaciones industriales.

Se aprecia como al variar el parámetro de Sigma, se va difuminando más la imagen original.

- Filtro Sobel: Permite resaltar los bordes del objeto en la imagen. Muy utilizado junto al filtro Gaussiano Blur.

Al aplicar el filtro Gauss y Sobel se obtuvieron los siguientes resultados.
También se pueden aplicar los filtros en distintas direcciones (por ejemplo en dirección vertical, horizontal, cruzado, etc.)

- Filtro Perona Malik: También llamado Difusión Anisotrópica. Busca eliminar el ruido de las imágenes sin necesidad de retirar las piezas importantes del contenido. Muy difundido en el reconocimientos de objetos metálicos en la Industria.

La Difusión Anisotrópica se implementa normalmente por medio de una aproximación de la ecuación de difusión generalizada: cada nueva imagen en la familia se calcula mediante la aplicación de esta ecuación a la imagen anterior, hasta que se obtiene un grado suficiente de suavizado.

- Filtro Laplace, Median, Frangi, Prewitt y muchos más: Hay una extensa variedad de filtros, cada uno con sus respectivas características y kernel propio.

Se aprecia las variantes que sufre la imagen original respecto a la aplicación de los distintos filtros.

¿Porqué al ser una etapa tan importante, muchas veces no es considerado en las implementaciones de Redes Neuronales Convolucionales?

LegosFondo-1

En muchas ocasiones lo que hacen las convoluciones es aprender cuales son los mejores filtros automáticamente. Con el fin de detectar bordes; eliminar ruido; etc. Muchas veces le pasamos todo nuestro dataset de imágenes a la Red, y que el algoritmo de entrenamiento haga su trabajo, sin que nosotros tengamos que pensar demasiado en cómo resolver el problema.

Aunque no lo crean, si uno se toma el tiempo de analizar qué hacen las Redes Convolucionales, muchas veces se va a encontrar en las primeras capas con algunos Kernels sospechosamente parecidos a los filtros "conocidos" como mencionamos anteriormente (es decir, las Redes Convolucionales a veces terminan aprendiendo, en base a los datos: un kernel Gaussiano, Sobel, etc).

Image Super-Resolution Using Deep Convolutional Networks

LegoPaper-2

Por ejemplo, hay un paper de hace unos años que mencionan estos filtros implicitos en las Redes Neuronales, el de SR-CNN (una Convnet de Super-Resolución, de antes de la época de las GANs) donde encontraron y destacan el hecho que las Redes Neuronales que entrenaban, terminaban "re-descubriendo" algunos kernels clásicos.

Sí se desea entrar en más detalle, adjunto link de Bibliografía de SR-CNN. En la página 6, sección 4.2 se cita Learned Filters for Super-Resolution y en la siguiente página 7, figura 5 se aprecian con mayor detalle. Se resalta en el análisis que los filtros aprendidos en la primer capa, y destacan algunos de ellos son similares a filtros de Laplace/Gauss, mientras que otros son similares a filtros detectores de bordes.


Conclusión

Por más que no definamos una etapa de Filtración, está aparecerá implicitamente al usar Redes Neuronales Convolucionales.

LosSimpson


Código

Acá dejo los códigos en Python de los distintos filtros que abordamos en este artículo.

import numpy as np
import cv2
from skimage import io,filters, color, img_as_float, img_as_ubyte
from matplotlib import pyplot as plt
plt.rcParams['image.cmap'] = 'gray'

#Imagen a analizar
#Las fotos de entrada estan en formato png o jpeg
imagenDatosVivos = './Logo.png'

## FILTRO GAUSSIANO
imagenLogo = io.imread(imagenDatosVivos)

#Redimensionamiento de la imagen de entrada
fixed_size = tuple((500, 400))
imagenLogo = cv2.resize(imagenLogo, fixed_size) 

#Gauss
bs0 = filters.gaussian(imagenLogo, sigma=1, multichannel=False)
bs1 = filters.gaussian(imagenLogo, sigma=3, multichannel=False)
bs2 = filters.gaussian(imagenLogo, sigma=5, multichannel=False)
bs3 = filters.gaussian(imagenLogo, sigma=15, multichannel=False)

f, (ax0, ax1, ax2, ax3) = plt.subplots(1, 4, figsize=(16, 5))
ax0.imshow(bs0)
ax0.set_title('$\sigma=1$')
ax1.imshow(bs1)
ax1.set_title('$\sigma=3$')
ax2.imshow(bs2)
ax2.set_title('$\sigma=5$')
ax3.imshow(bs3)
ax3.set_title('$\sigma=15$')
plt.show()

## FILTRO SOBEL Y ROBERTS
imageBlancoNegro = color.rgb2gray(imagenLogo)

edgeRoberts = filters.roberts(imageBlancoNegro)
edgeSobel = filters.sobel(imageBlancoNegro)

sobelV=filters.sobel_v(imageBlancoNegro)
sobelH=filters.sobel_h(imageBlancoNegro)

f, (ax0, ax1, ax2, ax3) = plt.subplots(1, 4, figsize=(16, 5))
ax0.imshow(edgeRoberts)
ax0.set_title('Operador cruzado de Robert')
ax1.imshow(edgeSobel)
ax1.set_title('Operador de Sobel')
ax2.imshow(sobelV)
ax2.set_title('Operador de Sobel vertical')
ax3.imshow(sobelH)
ax3.set_title('Operador de Sobel horizontal')
plt.show()

## FILTRO GAUSSIANO + SOBEL
imagenLogo = cv2.cvtColor(imagenLogo, cv2.COLOR_BGR2GRAY)

bg = cv2.GaussianBlur(imagenLogo, (15, 15), 10)
bc = filters.sobel(imagenLogo)

fig, (ax0, ax1, ax2) = plt.subplots(1, 3, figsize=(15, 15))
ax0.imshow(imagenLogo)
ax0.set_title('Original')
ax1.imshow(bg)
ax1.set_title('Filtro Gauss')
ax2.imshow(-bc)
ax2.set_title("Filtros Gauss+Sobel")
plt.show()

## FILTRO LAPLACE, MEDIAN, FRANGI Y PREWITT
laplace = filters.laplace(imageBlancoNegro)
median = filters.median(imageBlancoNegro)
frangi = filters.frangi(imageBlancoNegro)
prewitt = filters.prewitt(imageBlancoNegro)
 
f, (ax0, ax1,ax2, ax3, ax4) = plt.subplots(1, 5, figsize=(16, 5))
ax0.imshow(imagenLogo)
ax0.set_title('Original')
ax1.imshow(frangi)
ax1.set_title('Filtro Frangi')
ax2.imshow(prewitt)
ax2.set_title('Filtro Prewitt')
ax3.imshow(laplace)
ax3.set_title('Filtro Laplace')

ax4.imshow(median)
ax4.set_title('Filtro Median')
plt.show()


Escrito por Carlos Bustillo.

Publicado originalmente en escueladedatosvivos.ai

¿Qué pensas del artículo? Compartí con tus colegas y deja tu comentario👇