A la hora de la implementación de los filtros lineales hay que tener en cuenta ciertos aspectos, los cuales, una vez comentados pueden parecer evidentes, pero que suelen ser errores frecuentes en las primeras implementaciones.
1. Dos buffers de imagen
Como es obvio, es necesario disponer de una copia de la imagen a filtrar, durante el proceso. La razón es que para cada pixel estamos considerando los valores de sus vecinos, si modificamos los pixels sobre la imagen original, estaremos modificando los vecinos de pixels que serán procesados posteriormente. Operar de esta forma hace que la convolución no sea válida, puesto que estamos convirtiendo nuestro sistema en variante con el tiempo y la operación convolución se define para sistemas lineales e invariantes en el tiempo.
Si no disponemos de dos buffers en ciertas ocasiones aparecen estructuras fractales (tipo triángulo de Sierpinski) sobre la imagen resultado, fruto de la mencionada realimentación.
Si nuestro sistema no dispone de memoria suficiente, podemos utilizar un algoritmo de tipo scanline, creando un buffer para almacenar la imagen original, para el scanline que se este procesando en ese momento. Si estamos barriendo la imagen de izquierda a derecha y de arriba a abajo, todos los vecinos de los pixels en la línea que estemos procesando estarán en esa línea, en la superior y en la inferior, con lo cual con un buffer de tres líneas podemos realizar el filtrado. El inconveniente de este método es que el tiempo de procesado aumenta, al ser necesario actualizar el buffer para cada línea procesada. Como siempre compromiso entre velocidad y memoria.
2. Condiciones de contorno
Tal y como se ha definido el proceso de convolución, los pixels más exteriores de la imagen, no disponen de todos los vecinos que se consideran en la fórmula. Así, el pixel (0,0), no tiene vecinos ni en la parte superior, ni en la parte izquierda (si consideramos el punto 0,0 en la esquina superior izquierda), el pixel (1,0) ya tiene vecinos a su izquierda -los pixels (0,0) y (0,1)- pero sigue sin tener vecinos encima.
Podemos seguir tres estrategias para tratar este problema:
3. Operaciones
La forma más sencilla e intuitiva de realizar las operaciones entre el filtro y la ventana de imagen de cada iteración, es utilizar aritmética de punto flotante, la desventaja de esta implementación es la velocidad, al ser mucho más lentas estas operaciones (recuérdese que si utilizamos números decimales podemos normalizar los coeficientes y eliminar el parámetro factor). La otra solución es utilizar aritmética entera, mucho más rápida (aquí es necesario considerar el parámetro factor, dependiendo del filtro), pero teniendo cuidado con los errores de redondeo.
4. El Color
Como ya se comento en una sección anterior, para procesar imagenes en color, se aplica el algoritmo sobre cada componente de color independientemente, como si tuviésemos 3 imagenes en escala de grises. Es en este tipo de operaciones en las que las nuevas extensiones MMX ofrecen ventajas en la implementación, al permitir realizar operaciones con bytes empaquetados. De esta forma un pixel de imagen sería un grupo de 4 bytes empaquetados (R,G,B y alpha), sobre el cual podemos operar como si se tratase de un solo bloque pero considerando cada byte por separado, es decir, en una sola operación actuamos sobre las tres componentes.
|
|
|