martes, 8 de abril de 2014

La función Gaussiana en visión artificial I



¿Cuanto se le debe a Johann Carl Friedrich Gauss?. Imposible de cuantificar la aportación del brillante matemático al mundo de la física , de las matemáticas o de la astronomía. Desde los fractales, pasando por el electromagnetismo y como no, la visión artificial son, entre otras muchas ramas de la ciencia, deudoras del ingenio del "príncipe de las matemáticas". La visión por computador es posible hoy en día por estar, en términos newtonianos, aupada a hombros de gigantes como Gauss. En esta entrada vamos a explicar en que consiste la función Gaussiana, y que importancia tiene en la visión por computador.

La función gaussiana tiene el siguiente aspecto en dos dimensiones:

$G(x,y;\sigma ) = \frac{1}{2\pi \sigma ^2}e^-\frac{x^2+y^2}{2\sigma ^2}$

Esta misma función, en una dimensión es considerada la función de densidad de una variable aleatoria cuando se entiende a $\sigma ^2$ como la varianza.  En el caso que nos ocupa el valor $\sigma$ representará la "escala interior", cuyo valor siempre será mayor que cero, esto es evidente si consideramos que no es posible realizar un observación a través de una apertura nula. Por otro lado la parte correspondiente a $\frac{1}{2\pi \sigma ^2}$ sirve  para normalizar la función - en la versión de 1 dimensión esto es muy fácil de ver- . Esto último es importante ya que el volumen que encierra la superficie tiene valor la unidad, independientemente del valor de sigma



Ahora expliquemos lo que es la convolución de dos funciones, y que se define de forma discreta como:

$g(m)*f(m)=\sum _ng(n)f(m-n)$

Y que cumple las siguientes propiedades:

- Conmutativa: $w*f = f*g$
- Asociativa: $w*(f*g) = (w*f)*g$
- Distributiva: $w*(f+g) =w*f+w*g$
- Teorema de la convolución $F(w*g) = F(w)*F(g)$, donde F es la transformada de  Fourier

Una propiedad importante es que la convolución de dos funciones gaussiana es también una función gaussiana, esto se denomina autosimilaridad.

$G_1(x,\sigma_1^2)*G_2(x,\sigma_2^2)=G(x,\sigma_1^2+\sigma_2^2)$

Para hacer esta última propiedad más explicita usamos el siguiente parámetro:


$\widetilde{x}=\frac{x}{\sigma\sqrt{2}}$

En ese caso nuestra función para una dimensión queda como:

$G(\widetilde{x},\sigma)=\frac{1}{\sigma\sqrt{2\pi }}e^-\widetilde{x}^2$

Una vez explicada brevemente el aspecto de la función gaussiana vamos a ver como puede emplearse en visión artificial. Para mejorar el aspecto de una imagen, eliminar ruido o destacar algunas características de la misma se pueden emplear distintos tipos de filtros. Un filtro en el dominio del espacio se realiza sobre todos y cada uno de los píxeles de una imagen, de tal forma que para modificar el pixel i,j se tienen en cuenta los valores de los vecinos. Los filtros en el dominio del espacio pueden ser de dos tipos, lo lineales y los no lineales.  Los filtros lineales usan un kernel o mascara $w(x,y)$ para realizar la siguiente operación que transforma cada píxel f(x,y):

$g(x,y)=\sum_{s=-i}^{i}\sum_{t=-j}^{j}w(i,j)f(x+i,y+j)$ 

Como puede comprobarse esta operación es una convolución.
 
Un ejemplo de filtro lineal es el que sustituye el valor del píxel por la suma ponderada de los píxeles vecinos. Para ello, se realiza una convolución donde la mascara o kernel es como el siguiente - en este caso hemos tomado una máscara de 2x2 -:

$\begin{pmatrix}
 1/2&1/2 \\
 1/2&1/2 
\end{pmatrix}$
 
Apliquemos un filtro de convolución como este usando OpenCV para Python:  

 
kernel = np.ones((3,3), dtype=np.float32)/9.0
cv2.filter2D(img,-1,kernel)

En este caso hemos aplicado una convolución tal que cada píxel es transformado en la media de los 9 vecinos, para ello se utiliza el kernel definido en la primera línea. El resultado de aplicar este filtro se muestra a continuación:



Como puede verse este filtro empaña o emborrona la imagen. Lo que puede lograrse mediante este filtro es suavizar la imagen, eliminado detalles dispersos y de pequeño tamaño. Como se deduce inmediatamente parte de su utilidad se encuentra en su capacidad para eliminar ruido.


El filtro de la media tiene algunas desventajas, ya que es muy sensible a cambios locales y puede crear nuevas intensidades que no aparecen en el original. Empleando un kernel más sofisticado pueden obtenerse resultados más óptimos. Para ello podemos recurrir a la función gaussiana:

$G(x,y;\sigma ) = \frac{1}{2\pi \sigma ^2}e^-\frac{x^2+y^2}{2\sigma ^2}$

El valor de $sigma$ determina la anchura de la campana. Hay que destacar que en virtud de las propiedades vistas anteriormente el filtro gaussiano es separable, es decir podemos aplicar un filtro 2D aplicando dos mascaras, una horizontal y otra vertical.

Si aplicamos un filtro gaussiano, empleando OpenCV:
cv2.GaussianBlur(img,(0,0),1)

Donde el valor (0,0) designa el tamaño del kernel o máscara y el valor 1 es el correspondiente a sigma. Si el valor del tamaño del kernel es cero - como en el caso que nos ocupa - la evaluación se realiza empleando el valor de sigma. También es posible dar distintos valores para la sigma de x y la sigma de y. El resultado es:



Uno de los usos más interesantes de este tipo de filtros es el que va encaminado a facilitar la detección de características. Los algoritmos para extraer esquinas como el propuesto por Harris son invariantes ante las rotaciones pero no lo son con respecto a los cambios de escala, es decir, no detectara esquinas y bordes que no estén el la misma escala. En estos casos se puede recurrir a un nuevo tratamiento, como por ejemplo el algoritmo SIFT - Scale-Invariant Feature Transform - que hace uso del filtrado con kernel gaussiano y que veremos en la siguiente entrada.        
 

No hay comentarios:

Publicar un comentario