Un filtro suaviza el ruido de una imagen
Un filtro de imagen cambia cada píxel usando los píxeles de su alrededor. El desenfoque es el filtro más usado para quitar ruido. Sin él, una foto escaneada con motas da umbrales y bordes falsos.
Hoy calculas a mano un filtro de 3 por 3 y ves cuánto baja el ruido en una página escaneada.
Al final de esta lección
Nota
Puedo suavizar el ruido de una imagen con un filtro.
Palabras clave
| Palabra | Qué significa | Ejemplo |
|---|---|---|
| Ruido | píxeles con valores erróneos, como motas | |
| Filtro | una regla que cambia cada píxel según sus vecinos | |
| Núcleo | la cuadrícula de pesos del filtro (kernel en inglés) | 3 × 3 |
| Convolución | deslizar el núcleo y sumar productos en cada punto | |
| Desenfoque | un filtro que promedia los vecinos | |
| Mediana | el valor del medio de una lista ordenada |
Las celdas que rellenan los estudiantes quedan en blanco en esta vista previa.
Un píxel suelto se corrige con sus vecinos
Una página escaneada tiene motas: puntos negros o blancos que no están en el papel. Eso es ruido.
Un vecino sabe cómo debería ser un píxel. Si sustituyes cada píxel por la media de su trozo de 3 por 3, una mota se reparte entre nueve puntos y casi desaparece. Eso es un desenfoque.
Ejemplo resuelto: una mota entre nueve píxeles
| Paso | Cálculo | Resultado |
|---|---|---|
| El trozo de 3 × 3 | Ocho píxeles de 10 y una mota de 90 | Mota en el centro |
| Suma de los nueve | 8 × 10 + 90 | 170 |
| Media entera | 170 // 9 | 18 |
| Píxel nuevo | El centro pasa de 90 a 18 | La mota casi no se nota |
Las celdas que rellenan los estudiantes quedan en blanco en esta vista previa.
Un núcleo dice cuánto pesa cada vecino
Un núcleo es una cuadrícula pequeña de pesos. Se coloca sobre un trozo de la imagen, se multiplica cada píxel por su peso y se suman los productos. Eso es una convolución.
Un núcleo de nueve unos suma el trozo entero. Dividido entre 9 da la media. Otros pesos dan otros filtros.
Un núcleo sobre un trozo
# Un filtro 3 por 3 en UNA posición: multiplica cada vecino por su peso y suma.
patch = [
[1, 2, 3],
[4, 5, 6],
[7, 8, 9],
]
kernel = [
[1, 1, 1],
[1, 1, 1],
[1, 1, 1],
]
total = 0
for row in range(3):
for column in range(3):
total = total + patch[row][column] * kernel[row][column]
print("suma de productos:", total)
print("desenfoque:", total // 9)
# Cambia el núcleo: un 9 en el centro y ceros en los demás. ¿Qué devuelve el filtro?
Ejemplo resuelto: tres núcleos sobre el mismo trozo
| Núcleo | Qué pesos tiene | Resultado sobre 1 a 9 |
|---|---|---|
| Nueve unos | Todos 1 | 45, y 5 al dividir entre 9 |
| Solo el centro | Un 1 en el centro y ceros | 5, la imagen no cambia |
| En cruz | Unos arriba, abajo, izquierda y derecha | 20 |
Las celdas que rellenan los estudiantes quedan en blanco en esta vista previa.
La suma del núcleo de unos
docker exec jupyter python3 -c "print(1 + 2 + 3 + 4 + 5 + 6 + 7 + 8 + 9, 45 // 9)"Se muestra aquí y no se ejecuta. Crea una cuenta gratuita para pulsar Ejecutar y escribirlo en el terminal de tu propio laboratorio.
Un error muy común
Advertencia
Mucha gente cree que basta con escribir cada resultado en la misma imagen. Pero el píxel siguiente necesita los valores viejos de sus vecinos. Escribe el resultado en una imagen nueva y deja la original sin tocar. Además, la nueva sale 2 filas y 2 columnas más pequeña, porque en el borde el núcleo no cabe.
La mediana ignora las motas
La media se deja arrastrar por una mota. La mediana no: se ordenan los nueve valores y se toma el del medio.
Con ocho píxeles de 10 y una mota de 255, la media entera da 32 y la mediana da 10. Por eso el filtro de mediana limpia bien las motas de tinta y de papel.
La media y la mediana de una mota
docker exec jupyter python3 -c "v = [10, 10, 10, 10, 255, 10, 10, 10, 10]; print(sum(v) // 9, sorted(v)[4])"Se muestra aquí y no se ejecuta. Crea una cuenta gratuita para pulsar Ejecutar y escribirlo en el terminal de tu propio laboratorio.
Qué cuenta el script del desenfoque
El script blur.py desenfoca scan.png con un desenfoque gaussiano, que da más peso a los vecinos cercanos. Mide cuánto varían los píxeles de un trozo vacío de la página.
Imprime en inglés: before es antes y after es después. La dispersión baja de 25,3 a 4,9 niveles de gris.
Desenfoca la página escaneada
docker exec jupyter python3 steps/blur.pySe muestra aquí y no se ejecuta. Crea una cuenta gratuita para pulsar Ejecutar y escribirlo en el terminal de tu propio laboratorio.
Para ir más lejos: más desenfoque
En el código de arriba, cambia el trozo para que tenga una mota de 90 en el centro y ocho píxeles de 10. Comprueba que el desenfoque da 18.
Después abre scan_blurred.png en JupyterLab y compárala con scan.png. ¿Qué pasa con las letras?