Una sola operación para editar fotografías
Cuando editas una fotografía y la desenfocas, o haces que resalten sus contornos, estás aplicando un filtro: una operación que recorre toda la imagen y cambia cada píxel según lo que tiene alrededor.
Esos efectos parecen muy distintos entre sí, pero muchos son la misma operación. Lo único que cambia son unos cuantos números.
La ventana que se desliza
Una imagen es un tablero grande de casillas, cada una con un valor. Ahora imagina un cuadrado pequeño —de 3×3, o de 5×5— que va recorriendo ese tablero, píxel por píxel.
| ● | ||
| ● | ||||
En cada posición, ese cuadradito toma los valores que quedan debajo, multiplica cada uno por el número de su casilla, los suma, y el resultado reemplaza al píxel del centro (el punto ●).
Esa operación se llama convolución. El cuadradito con los números adentro se llama kernel, y es lo que decide qué filtro es. Cambias los números del kernel y cambias el efecto.
Primer relleno: el promedio (desenfoque)
Pon un noveno en cada una de las nueve casillas.
| 1/9 | 1/9 | 1/9 |
| 1/9 | 1/9 | 1/9 |
| 1/9 | 1/9 | 1/9 |
¿Por qué un noveno? Porque 3×3 son nueve números, y sumarlos todos y dividir entre nueve es exactamente lo mismo que multiplicar cada uno por un noveno. Es un promedio.
Entonces cada píxel se reemplaza por el promedio de sí mismo y de su vecindario.
El efecto es una imagen más suave. Tienes más información de lo que hay alrededor y menos de lo que hay exactamente en ese punto. El contraste se deteriora, sí, pero a cambio ganas información de color y de forma en vez de detalle.
Eso sirve estéticamente —desenfocar el fondo para que resalte el sujeto de un retrato, aplicándolo sólo en ciertas áreas— y sirve técnicamente, cuando lo que te interesa de una imagen son los patrones y las formas y los detalles finos sólo estorban.
(Éste es el desenfoque más simple. Hay otros, como el gaussiano, que usan fórmulas distintas para los mismos nueve espacios.)
Segundo relleno: unos y menos unos (bordes)
Ahora, misma ventana, mismo recorrido, otros números: unos de un lado y menos unos del otro (y ceros en medio).
Si los acomodas en disposición vertical —positivos a la izquierda, negativos a la derecha— la cuenta da cerca de cero en las zonas parejas, y da un valor grande justo donde hay un cambio brusco de un lado a otro. Es decir: detecta bordes verticales.
| 1 | 0 | −1 |
| 1 | 0 | −1 |
| 1 | 0 | −1 |
Si pones los unos arriba y los menos unos abajo, detecta bordes horizontales.
| 1 | 1 | 1 |
| 0 | 0 | 0 |
| −1 | −1 | −1 |
Y si combinas los dos resultados, encuentras idealmente todos los bordes de la imagen. Cuando tienes, por ejemplo, una pelota sobre un fondo blanco, obtienes las líneas de su contorno.
Se pueden hacer giros para encontrar bordes a 45 grados, pero eso ya requiere otras operaciones.
Una operación, muchos filtros
El desenfoque y la detección de bordes se sienten como cosas opuestas —uno borra detalle, el otro lo extrae— y son exactamente el mismo programa.
El código que recorre la imagen es idéntico. La única diferencia son nueve números en una tabla.
Es de los mejores ejemplos que conozco de una idea que aparece por todas partes: cuando encuentras la operación correcta, muchísimas funciones que parecían distintas se vuelven configuraciones de la misma cosa. Y ahí, de pronto, agregar un filtro nuevo deja de ser programar y pasa a ser sólo elegir números.
Este texto sale del episodio 007 del Podcast Algoritmos, sobre imágenes digitales.