Advertisement
  1. Code
  2. Python

Filtrado de Imagen en Python

Scroll to top
Read Time: 9 min

() translation by (you can also view the original English article)

¿Alguna vez que has encontrado con una imagen ruidosa? Me refiero a una imagen que no era tan clara cuando la veías. Creo que nos topamos con dichas imágenes muy frecuentemente, especialmente cuando muchas imágenes hoy en día son tomadas por cámaras de teléfonos móviles o cámaras digitales de baja resolución.

Si solo tuvieras esa imagen ruidosa que significa algo para ti, pero el problema es que no puede ser vista apropiadamente, ¿hay una solución para recuperar de tal ruido?

Aquí es donde el filtrado de imagen entra en juego, y esto es lo que estaré describiendo en este tutorial. ¡Comencemos!

Filtrado de Imagen

El filtrado de imagen es una herramienta popular usado en procesamiento de imagen. Al final del día, usamos el filtrado de imagen para remover ruido y cualquier característica no deseada de una imagen, creando una versión mejorada de esa imagen. Existen dos tipos de filtro: lineal y no-lineal. Ejemplos de filtros lineales son filtros medio y Laplaciano. Los filtros no lineales constituyen filtros como mediano, mínimo y máximo, y filtros Sobel.

Cada uno de estos filtros tiene un propósito específico, y es diseñado para remover ruido o mejorar algunos aspectos de la imagen. ¿Pero cómo se lleva a cabo el filtro? Esto es lo que veremos en la siguiente sección.

¿Cómo Llevamos a Cabo Filtrado de Imagen?

Para poder llevar a cabo un proceso de filtrado de imagen, necesitamos un filtro, también llamado máscara. El filtro es usualmente una ventana cuadrada de dos dimensiones, esa es una ventana con dimensiones iguales (alto y ancho).

El filtro incluirá números. Esos números son llamados coeficientes, y son los que realmente determinan el efecto del filtro y cómo lucirá la imagen de salida. La figura de abajo muestra un ejemplo de un filtro 3x3, teniendo nueve valores (coeficientes).

An example 3x3-filterAn example 3x3-filterAn example 3x3-filter

Para aplicar el filtro, la ventana de 3x3 es deslizada sobre la imagen. Este proceso de deslizar una ventana de filtro sobre una imagen es llamado circunvolución en el dominio espacial. La ventana será colocada sobre cada pixel (ej. piensa en ella como una celda en una matriz) en la imagen, en donde el centro del filtro debería superponer ese pixel.

Una vez que este encimado sucede, los pixeles de la sub-imagen sobre la que está el filtro serán multiplicados con los coeficientes correspondientes del filtro. En este caso, tendremos una nueva matriz con nuevos valores similar al tamaño del filtro (ej. 3x3). Finalmente, el valor de pixel central será reemplazado con un nuevo valor usando una ecuación matemática específica dependiendo del tipo de filtro usado (ej. fltro medio).

Sé que el párrafo de arriba es un poco apalabrado. Tomemos un ejemplo para mostrar cómo un filtro de imagen es aplicado en acción. Supón que tenemos la siguiente sub-imagen en donde nuestro filtro se superpuso (i y j se refieren a la ubicación del pixel en la sub-imagen, e I se refiere a la imagen):

An example sub-imageAn example sub-imageAn example sub-image

La circunvolución de nuestro filtro mostrado en la primera figura con la sub-imagen de arriba lucirá como se muestra abajo, en donde I_new(i,j) representa el resultado en la ubicación (i, j).

1
I_new(i,j) = v1 x I(i-1,j-1) + v2 x I(i-1,j) + v3 x I(i-1,j+1) + 
2
v4 x I(i,j-1) + v5 x I(i,j) + v6 x I(i,j+1) + v7 x I(i+1,j-1) + 
3
v8 x I(i+1,j) + v9 x I(i+1,j+1)
4

El proceso es repetido para cada pixel en la imagen, incluyendo los pixeles en los límites de la imagen. Pero, como puedes adivinar, parte del filtro residirá fuera de la imagen cuando se coloque el filtro en los pixeles fronterizos. En este caso, estamos realizando relleno.

Este proceso simplemente significa que insertamos nuevos valores de pixel en la sub-imagen bajo la parte del filtro que viene dentro de la imagen antes del proceso de circunvolución, ya que esa parte aparentemente no contiene ningún valor de pixel. ¡Está fuera de la imagen! Esos pixeles rellenos podrían ser ceros o un valor constante. Hay otros métodos para establecer los valores de relleno, pero estos están fuera del alcance de este tutorial.

¡Creo que esa es suficiente teoría por ahora, así que continuemos y ensuciemos nuestras manos con código! En este tutorial, estaré explicando el filtro medio (ej. no lineal) y el filtro medio (ej. lineal) y cómo podemos implementarlos en Python.

Filtro Medio

En el filtro medio, elegimos deslizar una ventana que se moverá a través de todos los pixeles de la imagen. Lo que hacemos aquí es recolectar los valores de pixel que vienen bajo el filtro y tomamos la media de esos valores. El resultado será asignado al pixel central.

Digamos que nuestro filtro 3x3 tenía los siguientes valores después de colocarlo en una sub-imagen:

An example median-filterAn example median-filterAn example median-filter

Veamos cómo calcular la media. La media, en esencia, es el número medio de una lista ordenada de números. Así pues, para encontrar la media para el filtro de arriba, simplemente ordenamos los números de menor a mayor, y el medio de esos números será nuestro valor medio. Acomodar los valores en nuestra ventana 3x3 nos dará lo siguiente:

1
17 29 43 57 59 63 65 84 98

Para encontrar el número medio (media) simplemente contamos el número de valores que tenemos, agregamos 1 a ese número, y lo dividimos entre 2. Esto nos dará la ubicación del valor medio en la ventana, el cuál es nuestro valor medio. Así que el valor medio estará en la ubicación 9+1/2 = 5, que es 59. Este valor será el nuevo valor del pixel bajo el centro de nuestra ventana 3x3.

Este tipo de filtro es usado para remover ruido, y funciona mejor con imágenes sufriendo del ruido de sal y pimienta. La imagen de abajo muestra un ejemplo de una imagen sufriendo de tal ruido:

An example of salt-and-pepper noiseAn example of salt-and-pepper noiseAn example of salt-and-pepper noise

Ahora, escribamos un código Python que aplicará el filtro de media a la imagen de arriba. Para este ejemplo, estaremos usando la librería OpenCV. Revisa Instalar OpenCV-Python en Windows e Instalar OpenCV 3.0 y Python 2.7+ en Ubuntu para instalar OpenCV.

Para aplicar el filtro de media, simplemente usamos la función cv2.medianBlur() de OpenCV. Nuestro código lucirá como sigue:

1
import cv2
2
import argparse
3
4
# create the argument parser and parse the arguments

5
ap = argparse.ArgumentParser()
6
ap.add_argument('-i', '--image', required = True, help = 'Path to the input image')
7
args = vars(ap.parse_args())
8
9
# read the image

10
image = cv2.imread(args['image'])
11
# apply the 3x3 median filter on the image

12
processed_image = cv2.medianBlur(image, 3)
13
# display image

14
cv2.imshow('Median Filter Processing', processed_image)
15
# save image to disk

16
cv2.imwrite('processed_image.png', processed_image)
17
# pause the execution of the script until a key on the keyboard is pressed

18
cv2.waitKey(0)

Nota que he usado argparse, ya que es una buena práctica para ser flexible aquí, y usar la linea de comando para pasar la imagen sobre la que queremos aplicar el filtro de media como un argumento a nuestro programa.

Después de pasar nuestra imagen como un argumento de línea de comando, leemos esa imagen usando la función cv2.imread(). Después aplicamos el filtro de media usando la función medianBlur(), pasando nuestra imagen y tamaño de filtro como parámetros. La imagen es mostrada usando la función cv2.imshow(), y es guardada al disco usando cv2.imwrite().

El resultado del código de arriba es como sigue:

The result of the processed imageThe result of the processed imageThe result of the processed image

Bueno, ¿qué opinas? Muy hermoso---una imagen bonita y limpia sin ruido.

Puedes descargar el código de arriba desde mi repositorio median-filter en GitHub.

Filtro Medio

El filtro medio es un ejemplo de un filtro lineal. Este reemplaza básicamente cada pixel en la imagen de salida con el valor medio (promedio) del vecindario. Esto tiene el efecto de suavizar la imagen (reduciendo la cantidad de variaciones de intensidad entre un pixel y el siguiente), remover ruido de imagen, y abrillantar la imagen.

Así pues, en filtrado medio, cada pixel de la imagen será reemplazado con el valor medio de sus vecinos, incluyendo el mismo pixel. El núcleo de 3x3 usado para filtrado medio es mostrado en la figura de abajo, aunque otros tamaños de kernel podrían ser usados (ej. 5x5).

An example of the Mean FilterAn example of the Mean FilterAn example of the Mean Filter

Lo que el kernel de arriba está de hecho tratando de decirnos es que sumamos todos los elementos bajo el kernel y tomamos el medio (promedio) del total.

Un punto importante para mencionar aquí es que todos los elementos del kernel medio deberían:

  • sumar a 1
  • ser el mismo

Tomemos un ejemplo para hacer las cosas más claras. Digamos que tenemos la siguiente sub-imagen:

An example of the sub-image mean filterAn example of the sub-image mean filterAn example of the sub-image mean filter

Cuando aplicamos el filtro medio, haríamos lo siguiente:

1
(7+9+23+76+91+7+64+90+32)/9 = 44

El resultado exacto es 44.3, pero redondeé el resultado a 44. Así que el nuevo valor para el pixel central es 44 en vez de 91.

Ahora para la parte de código. Digamos que tenemos la siguiente imagen ruidosa:

Another noisy imageAnother noisy imageAnother noisy image

Lo que queremos hacer en este punto es aplicar el filtro medio en la imagen de arriba y ver los efectos de aplicar tal filtro.

El código para hacer esta operación es como sigue:

1
import cv2
2
import numpy as np
3
import argparse
4
5
# create the argument parser and parse the arguments

6
ap = argparse.ArgumentParser()
7
ap.add_argument('-i', '--image', required = True, help = 'Path to the input image')
8
args = vars(ap.parse_args())
9
10
# read the image

11
image = cv2.imread(args['image'])
12
# apply the 3x3 mean filter on the image

13
kernel = np.ones((3,3),np.float32)/9
14
processed_image = cv2.filter2D(image,-1,kernel)
15
# display image

16
cv2.imshow('Mean Filter Processing', processed_image)
17
# save image to disk

18
cv2.imwrite('processed_image.png', processed_image)
19
# pause the execution of the script until a key on the keyboard is pressed

20
cv2.waitKey(0)

Nota del código que hemos usado un kernel de 3x3 para nuestro filtro medio. También hemos usado la función filter2D() para aplicar el filtro medio. El primer parámetro de esta función es nuestra imagen de entrada, el segundo es la profundidad deseada de la imagen de salida ddepth, y el tercer parámetro es nuestro kernel. Asignar -1 para el parámetro ddepth significa que la imagen de salida tendrá la misma profundidad que la imagen de entrada.

Después de ejecutar el código en nuestra imagen ruidosa, este fue el resultado que obtuve:

A result of the noisy image after a filterA result of the noisy image after a filterA result of the noisy image after a filter

Si observas la imagen de salida, podemos ver que es más suave que la imagen ruidosa. ¡Misión completada!

Puedes descargar el código de arriba desde mi repositorio de filtro medio en GitHub.

Conclusión

Como vimos en este tutorial, Python nos permite llevar a cabo tareas avanzadas como filtrado de imagen, especialmente a través de su librería OpenCV, en una manera simple.

De manera adicional, no dudes en ver lo que tenemos disponible a la venta y para estudio en el marketplace, y no dudes en hacer cualquier pregunta y proporcionar tu valiosa retroalimentación usando la sección de abajo.

Advertisement
Did you find this post useful?
Want a weekly email summary?
Subscribe below and we’ll send you a weekly email summary of all new Code tutorials. Never miss out on learning about the next big thing.
Advertisement
Looking for something to help kick start your next project?
Envato Market has a range of items for sale to help get you started.