PRÁCTICAS TXÓN.

DATOS MULTIMEDIA

COMPRESORES BASADOS EN LA TRANSFORMADA WAVELET

1. Introducción
En esta práctica estudiaremos tanto la Transformada Discreta Wavelet (DWT) como los principales compresores basados en esta transformada, entre los que se encuentra JPEG 2000, la siguiente versión del famoso estándar para compresión de imágenes de tono continuo. En la primera parte de la práctica presentaremos e implementaremos la transformada Wavelet orientada a imagen (es decir, bi-dimensional). Para este estudio e implementación nuevamente se proporciona un código fuente incompleto escrito en ANSI C++, que se deberá analizar y completar. En la segunda parte de la práctica introduciremos los compresores basados en Wavelet: JPEG 2000 y LTW, y a partir de unos ejecutables que implementan estos algoritmos, realizaremos una comparación de ambos en términos de eficiencia en compresión y en tiempo de ejecución.

2. La Transformada Wavelet
La Transformada Wavelet, más conocida por su nombre en inglés, Discrete Wavelet Transform (DWT), es una herramienta matemática de reciente desarrollo que permite descomponer una señal no sólo en componentes frecuenciales sino también espaciales. Si la comparamos con la DCT (que está basada en las conocidas teorías de Fourier), observamos que los coeficientes resultantes de aplicar la DCT a un conjunto de muestras nos indican qué componentes frecuenciales componen esa señal, pero no tienen ningún tipo de información sobre su situación en la señal original, sino que se refiere al global de las muestras. Por el contrario, los coeficientes de la DWT nos sitúan distintos componentes frecuenciales en posiciones espaciales, mediante un análisis por subbandas. En general, los más modernos compresores de imagen han decidido sustituir la DCT por la DWT para la fase de la transformada por diversas ventajas, entre ellas: (1) La DWT es capaz de compactar la energía en menos coeficientes que la DCT. Uno de los objetivos de aplicar una transformada matemática a los píxels antes de su almacenamiento/transmisión es ser capaz de concentrar gran parte de la información sobre la representación de la imagen en unos cuantos componentes, de manera que el resto de componentes sean cero, o prácticamente cero. Después de aplicar la DCT a un bloque de 8x8, la mayor parte de la energía (valores más altos) está en la componente de continua (DC) y los coeficientes que la rodean. En la DWT esta concentración de energía será aun más pronunciada, quedando la mayor parte de la energía en las subbandas de menor frecuencia.

1

(3) Una cualidad interesante de la DWT es que permite un análisis en multiresolución de las imágenes. En concreto. Como sabemos. lo que se conoce como proceso de síntesis. porque se aplica a toda la imagen. degradando mucho la calidad perceptual de la imagen. ya que su aplicación a la imagen completa sería excesivamente costosa. basándose en un banco de filtros de análisis paso-bajo {hk } y paso-alto {g k } que descomponen una señal unidimensional en dos bandas. de manera que nos quedaremos con la mitad de las muestras obtenidas al aplicar cada filtro.(2) No es necesario dividir en bloques la imagen para aplicar la DWT. en la DCT. sí es necesario aplicar la DCT en pequeños bloques de 8x8. { } 2 . Como ya hemos comentado. que se escalan y se desplazan respecto a una función prototipo. esta aplicación de la DCT y posterior cuantización de la imagen en bloques puede dar lugar al típico efecto de bloque. Sin embargo.1 La transformada Wavelet 1D (1D-DWT) La teoría matemática que subyace a la DWT puede resultar ciertamente compleja. Cuando el índice de compresión aplicado es alto. con propiedades oscilantes. Posteriormente haremos un downsampling de los coeficientes resultantes. en el que los bloques resultan perfectamente visibles (ver figura). una de baja frecuencia y otra de alta frecuencia. sin embargo. 2. su implementación es bastante sencilla. con una base para el espacio Wavelet más compleja que los cosenos a distintas frecuencias que forman la base de la DCT. en la DWT este efecto no sucede. se puede usar sobre la imagen completa. la DWT usa como base funciones de soporte finito. bastará con hacer un upsampling de los coeficientes (poniendo “0’s” en las muestras que se eliminaron en el downsampling) y aplicar los ~ ~ }. Para obtener las muestras originales aplicando la transformada inversa (IDWT). Esto permitirá incluir fácilmente escalabilidad espacial en un compresor de imagen. En la siguiente figura se esquematiza filtros de síntesis paso-bajo hk y paso-alto {g k este proceso para un primer nivel de descomposición.

11.11. pero la que se propone es usar extensión simétrica (es decir. y su reconstrucción obteniendo la señal original.38 -0.41 17. esta solución también se puede adoptar en el extremo final del vector).0 con tres proyectos distintos: 1DDWT.12.64. en el que el material necesario es simplemente un par de ficheros: “DWT.33. En “DWT. en concreto float Muestras[32]= {33.34.33.35.27} 3 . Para la parte de la práctica en al que implementaremos la DWT.64.39 -5. mostrando el resultado de cada una de estas operaciones.21. En particular. el resultado de la transformada directa una vez implementada correctamente debe ser el siguiente vector: {29.65 41.02 38.57 -39.h asociado).54 30. Para poder aplicar el filtro en estos casos hay distintas alternativas.64 32. el fichero “1DDWT.43.34.cpp” (y el DWT.33.22.58 1.33.67 41. vamos a realizar una implementación de esta transformada.12. Ejercicio 1 Para entender mejor el proceso de transformada Wavelet aplicada a una señal unidimensional (esto es. 33.72 39.65 41.69 63.cpp” simplemente contiene un sencillo programa que define un vector constante de 32 elementos. En este primer ejercicio vamos a trabajar con el proyecto 1DDWT.87 -4.08 42.97 35.74 -18.cpp” y “1DDWT.44.34.58 1.55 -10.22. si el vector inicial de muestras es “abcde…”.43}. un vector). uno por cada ejercicio.42 14.44. se ha definido un Workspace de Visual C++6.37 -12.66.55. Por otro lado. con el filtro que usaremos en prácticas.34.Análisis Paso-bajo 2↓ 2↑ Síntesis {hk } S ~ {h } k S Paso-alto {g k } 2↓ 2↑ ~ } {g k Figura: Un nivel de descomposición wavelet de una señal.21. en los que no se dispone de suficientes muestras para aplicar al filtro (por ejemplo.cpp” se tendrán que implementar las distintas versiones de la transformada Wavelet que haremos en esta práctica.55.55 -10.03 30.72 39.66. Un problema a resolver en la transformada es cómo operar con los valores próximos a los bordes.42 14.17 17.64.57 -37. replicamos el borde simétricamente con las muestras del propio vector de la siguiente forma: “edcbabcde…”. para aplicar un filtro a la primera muestra de la fila no disponemos de valores a la izquierda de las muestras). y llama a las funciones de transformada directa e inversa.00 -18. 2DDWT y 2DDWTn.97 35.69 63.35.64.02 38.

026748757410810 Síntesis paso bajo.057543526228500 + 0.091271763114250 k 0 ±1 ±2 ±3 Análisis paso alto. el resultado del paso alto). • La aplicación de un filtro digital sobre un vector consiste en. lógicamente debe ser el vector original.591271763114250 − 0.026748757410810 En el módulo DWT. En concreto. Por ejemplo. la 2 con la -2. mientras que las 16 últimas muestras forman la banda de alta frecuencia (banda H.016864118442875 + 0. el filtro {g k } aplicado sobre una posición x de un vector {vi }. también denominados coeficientes wavelet.016864118442875 + 0. los filtros de análisis se encuentran definidos en los vectores B97_AnalisisPasoBajo[] y B97_AnalisisPasoAlto[]. los filtros de B9/7 de análisis y síntesis son los siguientes. daría como resultado: {v x−3 g −3 + v x−2 g −2 + v x −1 g −1 + v x g 0 + v x +1 g1 + v x + 2 g 2 + v x +3 g 3 } Esta operación está ya implementada por la función float PasoDeFiltrado7(float *coef. y los de síntesis en B97_SintesisPasoBajo[] y B97_SintesisPasoAlto[]. de manera que otros filtros definirían otras DWT.078223266528990 + 0. {hk } + 0. etc.mientras que el de la transformada inversa.int pos. con lo que la posición 1 se corresponde también con la -1.591271763114250 − 0. vamos a usar los filtros que corresponden a la transformada Wavelet bi-ortogonal 9/7 (B9/7).cpp: • Para la transformada directa (DWT). (por eso en los vectores tan sólo definimos cinco elementos para los filtros de longitud nueve.115087052457000 − 0.091271763114250 ~ k 0 ±1 ±2 ±3 ±4 ~ } Síntesis paso alto.266864118442875 − 0.266864118442875 − 0.057543526228500 − 0.115087052457000 + 0. En principio podemos destacar los siguientes elementos del fichero DWT. {g k } + 1.cpp. multiplicar los taps (coeficientes del filtro) por los distintos componentes del vector y sumar el resultado.602949018236360 + 0.602949018236360 − 0. Observa que las primeras 16 muestras de este vector corresponden a la banda de baja frecuencia (banda L. {g k + 0. { hk } + 1. y cuatro para los de longitud siete).078223266528990 − 0. float *tap) 4 . por cada componente de este vector. es el resultado de aplicar el filtro paso bajo). Observa que estamos usando filtros simétricos. k 0 ±1 ±2 ±3 ±4 k 0 ±1 ±2 ±3 Análisis paso bajo.

Para aplicar el filtrado. y el filtro (de longitud siete) a usar (existe una función equivalente para los filtros de longitud nueve). 2. dejando los coeficientes de baja frecuencia en la parte baja del vector de entrada. etc. 4. simplemente tendremos que utilizar esta función sobre cada una de las posiciones que compongan el vector a filtrar. respectivamente. etc. 5 . (5) Por último se debe dejar el resultado sobre el vector de entrada. int tam) (1) Reserva la memoria necesaria para los distintos vectores auxiliares. (4) A continuación debes implementar la aplicación del downsampling de las muestras. y hay que completarlas. y otra de las tareas a realizar es extender los extremos simétricamente (para ello hemos usado un pequeño truco. que se encuentran parcialmente implementadas. la función void Calcula1D_DWT(float *Vector. (2) Como el resultado de la transformada se debe dejar sobre el propio vector de entrada. mientras que para los de alta frecuencia hay que eliminar las muestras impares (posiciones 1. y poner un vector a cero. 5. es necesario aplicar una extensión simétrica de la señal. Esta parte también está implementada. • Como ya hemos visto anteriormente. que lógicamente sirven para copiar un vector sobre otro. (3) A continuación hay que aplicar los filtros de síntesis paso alto y paso bajo a “VectorAux”. en esta misma unidad nos encontramos con las funciones para el cálculo de la DWT 1D directo e inverso. Esta parte se ofrece ya implementada.que recibe como parámetros el vector con el que operar (“coef”). dejando el resultado en “ResultadoPasoBajoDownsampled[]” y “ResultadoPasoAltoDownsampled[]”. El vector que contiene la copia es “VectorAux”.float *fin). y los de alta frecuencia en la parte alta del vector de entrada. y es que hemos definido este vector sobre otro más grande. Además. una de las primeras cosas a hacer es copiarlo sobre un vector distinto (para no perder los datos de entrada a medida que se van calculando los nuevos datos). En cuanto a la función void Calcula1D_IWT(float *Vector. para poder operar alrededor de las posiciones del vector próximas a los extremos. int tam) (1) Reserva la memoria necesaria para los distintos vectores auxiliares. Esta parte está implementada. (2) Separamos el vector de entrada en dos vectores. dejando el resultado en los vectores “ResultadoPasoBajo[]” y “ResultadoPasoAlto[]”. Otras funciones auxiliares interesantes son CopiaVector(…) y PonVectorACero(…). que contendrán los coeficientes de baja frecuencia (vector “CoeficientesPasoBajoDownsampled[]”) y los coeficientes de alta frecuencia (vector “CoeficientesPasoAltoDownsampled[]”) que se calcularon en la transformada directa. Observa que para los coeficientes de baja frecuencia debemos eliminar las muestras de las posiciones pares (0. llamado “VectorAux_Extendido”).). la posición que filtrar. En concreto. Esta parte hay que implementarla. Esta operación se encuentra ya implementada en la función void ExtensionSimetrica(float *ini. 3.).

tras aplicar esta transformada: 6 . la banda LL se obtiene a partir del filtro paso bajo tanto por filas como por columnas. e ir sumando posteriormente el resultado de aplicar el otro filtro. mientras que por último. La banda HH es la resultante de aplicar el filtro paso alto por filas y columnas. Partiendo de la transformada wavelet 1D. y dejando el resultado de este upsampling en los vectores “CoeficientesPasoBajo[]” y “CoeficientesPasoAlto[]”. Para hacer esta operación. sin necesidad de más vectores auxiliares. retornándolos a sus dimensiones originales. al ser una transformada separable). Esta parte hay que implementarla. y luego tendremos que realizar la asignación inversa a la que hicimos en el punto (4) de la DWT. Simplemente se debe aplicar la transformada 1D. dejando el resultado de la suma en el propio vector de entrada. en primer lugar deberemos poner estos vectores a cero (para que las posiciones no completadas sean “0’s”). y sumar el resultado de la aplicación de ambos filtros. 2. (5) En último lugar hay que aplicar los filtros de síntesis a los vectores que acabamos de construir. HL. (4) A continuación se realiza una extensión simétrica de los bordes de los vectores que se acaban de crear (esta parte se da hecha). y por tanto que su uso final será la aplicación sobre señales bidimensionales. su aplicación sobre imágenes es sumamente sencilla.2 La transformada Wavelet 2D (2D-DWT) No debemos olvidar que nuestro objetivo final es usar esta nueva transformada para compresión de imagen. En la siguiente figura se observa un ejemplo de la imagen estándar “Lena”. En la banda HL se encuentra el resultado de aplicar el filtro paso alto a las filas. Para hacer esto de manera sencilla.(3) A continuación tenemos que hacer un upsampling de ambos vectores. y paso bajo a las columnas. La aplicación de esta 2D-DWT a una imagen dará lugar a cuatro bandas de frecuencias denominadas LL. y después a cada una de las columnas (el orden también podría ser el contrario. puedes asignar a “Vector” el resultado de aplicar un filtro. LH y HH. primero a cada una de las filas que forman la imagen. mientras que en la LH tenemos el caso contrario.

En el nuevo proyecto se ha incorporado el módulo “ImagenES.cpp. que contiene el programa principal. En este caso usaremos el proyecto 2DDWT de nuestro Workspace y la imagen de prueba “lena512. seguidamente guarda el resultado de esta transformada en el fichero “lenaDWT. Para obtener la imagen original.raw”. y que está codificada con 8 BPP (escala de grises). • La función void Calcula2D_DWT(float **Imagen. y puede ser vista con algún visor de imágenes como IrfanView (http://www.cpp” para realizar la carga y escritura de imágenes desde disco. para a continuación calcular la 2D-IWT. a partir de estas cuatro subbandas. int ancho.cpp”. En la primera variable se recibe la imagen a transformar. Ejercicio 2 En este segundo ejercicio vamos a implementar la 2D-DWT a partir de la transformada 1D desarrollada durante el primer ejercicio. finalmente guardando el resultado de esta transformada inversa en el fichero “lenaRec. llama a la función para el cálculo de la 2D-DWT sobre esta imagen. y el fichero “2DDWT.raw”. El resultado de la transformada se debe dejar en esta misma imagen. que se encuentran en el fichero DWT.com/). Esta imagen está almacenada en formato crudo. y muestra una versión reescalada de la imagen. Observa que a la fila “i” de la imagen de entrada se puede acceder como el vector 7 . indicando al abrirla que las dimensiones de la imagen son de 512x512.LL HL LH HH Fíjate como la subbanda LL es la que concentra más energía.raw”. En este ejercicio simplemente debemos implementar las funciones para el cálculo de la 2D-DWT directa e inversa.irfanview. por filas y por columnas. int alto) debe implementar la transformada directa. que realiza en primer lugar una carga de la imagen de Lena. simplemente bastaría con aplicar la transformada wavelet inversa unidimensional (1D-IWT). cuyas dimensiones vienen dadas en las dos siguientes variables.

y) de la imagen es accesible como “Imagen[y][x]”. qué columna se quiere copia (NCol) y sobre qué vector se quiere copiar (además hay que pasar el alto de la imagen). 2.raw” después de implementar correctamente esta transformada debe ser similar a la siguiente figura: • En void Calcula2D_IWT(float **Imagen. el fichero “lenaRec. Una vez se implementen correctamente estas dos funciones. del vector a las columnas. mientras que un píxel (x. 8 . y posteriormente de las columnas. en primer lugar calcularemos la 1D DWT de todas las filas. y realizar la copia inversa. Debido a la organización por filas de las imágenes en memoria. en las que se indican por parámetro cuál es la imagen. cambiando la llamada a las funciones unidimensionales DWT por las equivalentes IWT. la de baja frecuencia (LL).raw” deberá tener una versión de “Lena” visualmente idéntica a la original. En esta función.“Imagen[i]”. y su implementación es exactamente igual. Para hacer estas copias se proporcionan las rutinas auxiliares “void PasaColumnaAVector(…)” y “void PasaVectorAColumna(…)”.3 La transformada Wavelet 2D multinivel (2D-DWTn) Podemos observar en el punto anterior que después de calcular la 2D-DWT sobre una imagen la mayor parte de la energía se encuentra centrada en una única subbanda. después del cálculo. int alto) implementaremos la transformada inversa. Los parámetros son exactamente los mismos que en la función directa. pero para el cálculo de las columnas es necesario antes realizar una copia de cada columna sobre un vector auxiliar (“Vector”. int ancho. Esto se debe a que las imágenes naturales se encuentran formadas sobre todo por información de baja frecuencia. el cálculo de la 1D-DWT sobre filas se puede hacer directo. ya creado en la propia función). El resultado de la imagen en “lenaDWT.

LH1 y LH2. el número de veces que vamos a aplicar la 2DDWT). que contiene un programa principal similar al del ejercicio 2. A los parámetros de la 2DDWT anterior le hemos añadido un último parámetro indicando el nivel de descomposición deseado (esto es. Ejercicio 3 En este ejercicio vamos a implementar la 2D-DWT multinivel a partir de la transformada 2D desarrollada en el anterior ejercicio. en el que hemos añadido “2DDWTn. int ancho. nivel) 9 . HH1 y HH2). dando lugar a coeficientes wavelet de dos niveles distintos (HL1 y HL2. centrándonos ahora exclusivamente en esta subbanda LL. podemos repetir exactamente el mismo proceso de transformada 2D. con lo que podríamos repetir el proceso de transformada 2D centrándonos en las distintas subbandas de baja frecuencia hasta que consideremos que hemos concentrado suficientemente la energía en una única banda de dimensiones reducidas. pero que en este caso llama a las funciones de transformada multinivel del módulo “DWT. facilitando esto el posterior proceso de compresión. y un único nivel de subbanda de baja frecuencia (LL2). a medida que vamos calculando más niveles de transformada. esta banda contiene la mayor parte de la energía.cpp: • En void Calcula2D_DWT_Multinivel(float **Imagen. Ahora usaremos el proyecto 2DDWTn de nuestro Workspace. Además. Podemos ver como en la banda de baja frecuencia de la figura tenemos nuevamente una versión reducida de la imagen original. De manera que un segundo nivel de transformada daría el siguiente resultado: LL2 HL2 LH2 HH2 HL1 LH1 HH1 En este caso. Nuevamente implementaremos las funciones directa e inversa sobre DWT.Para concentrar aun más la energía. int vamos a implementar la transformada directa. Decimos que la DWT facilita la multiresolución de manera natural porque vamos teniendo distintas versiones de la imagen original.cpp”.cpp” (usando un nivel de descomposición por defecto de 3). hemos aplicado la 2D-DWT con dos niveles de transformada. int alto. a distintos tamaños.

debemos ir calculando la transformada 2D inversa y duplicando el ancho y el alto. Nuevamente podremos comprobar la corrección de los procesos directos e inversos observando la calidad de la imagen resultante “lenaRec. se parte de la imagen transformada. La estructura básica del nuevo estándar es similar a la de JPEG y el resto de codificadores basados en transformada. 10 . El resultado de la imagen después de tres niveles de descomposición (el valor usado por defecto) deberá ser similar a la siguiente figura: • La transformada inversa multinivel se debe implementar en void Calcula2D_IWT_Multinivel(float **Imagen. 3. int ancho.raw”. y simplemente debemos calcular la transformada bidimensional un número de veces igual a nivel. y para las crominancias (diferencias de colores respecto a la luminancia) se realiza un downsampling a la mitad. en primer lugar se hace una conversión del espacio de colores de la imagen sin comprimir (normalmente RGB) a un espacio YCbCr 4:2:0.La implementación de esta función a partir de la del ejercicio 2 es muy sencilla. Es decir. reduciendo las dimensiones de la imagen (variables “ancho” y “alto”) a la mitad en cada uno de los niveles. y a partir de unas dimensiones de (ancho/2nivel−1) y (alto/2nivel−1). utiliza la DWT en vez de la DCT. pero en camino inverso.1 JPEG 2000 Una de las razones por la que la transformada Wavelet cobra tanto interés en compresión de imagen es que el nuevo estándar que sustituye a JPEG. llamado JPEG 2000. En este caso hay que seguir el mismo recorrido que en la función directa. int nivel). en el que la luminancia se codifica completa. int alto. tantas veces como nivel de transformada se aplicó en la directa. Compresores de imagen basados en la transformada Wavelet 3. Esta estructura es la siguiente: (1) Si la imagen a comprimir es en color.

(4) Se divide la imagen en bloques de un tamaño considerable. 3. ya que la transformada y la cuantización se han aplicado a toda la imagen. de forma que si queremos escalabilidad espacial. es decir. en primer lugar elimina la codificación por planos de bit que se realiza en JPEG 2000. en su versión bi-ortogonal 9/7 (la implementada en el ejercicio 1). en el caso de imágenes a color. JPEG 2000 realiza un rate control tan preciso que se le puede indicar un tamaño de fichero y es capaz de comprimir la imagen en ese mismo tamaño. Por otro lado. sin conocer “a priori” cual sería el tamaño final al que el compresor comprimiría la imagen. julio de 2000. Ya no se realiza una división por bloques de cada uno de los planos a comprimir. si se quiere una escalabilidad en calidad (o SNR). Este codificador realiza una compresión del bloque por planos de bit. sino que la transformada se aplica a la imagen entera (o. Cada plano de bits lo codifica en tres pasadas. de manera que intenta identificar de forma eficiente cuando un coeficiente tiene el primer bit significativo distinto de cero. del plano más significativo al menos significativo. Fíjate que aunque en esta fase volvemos a realizar una compresión por bloques. simplemente tendremos que codificar en primer lugar la subbanda LL (que es una versión reducida de la imagen). tendremos que almacenar la imagen por planos de bit.(2) Posteriormente se aplica la transformada matemática. Esta ultima etapa es importante porque nos permite obtener el tipo de escalabilidad deseado. por la que se pasa de coeficientes flotantes a coeficientes enteros. Sin embargo estas características adicionales lo convierten en un compresor bastante costoso computacionalmente. Esta característica no la tenía JPEG. con un coste computacional sensiblemente menor. Esto lo realiza con un algoritmo de optimización basado en los multiplicadores de Lagrange. luego continúa por el siguiente bit. de mayor a menor nivel. y luego el resto de subbandas wavelet. etc. Para esto. normalmente 64x64. a cada uno de los planos de luminancia y crominancia que la componen) (3) Se hace una cuantización del resultado de calcular la DWT. Volumen 9. número 7.2 Lower Tree Wavelet (LTW) encoder. en el que tan sólo se le podía indicar un nivel de compresión. sin divisiones previas. Para más información sobre JPEG 2000 y el codificador EBCOT se puede consultar el artículo “High performance scalable image compression with EBCOT” de la revista IEEE Transactions on Image Processing. En esta fase se construye el bitstream final según el tamaño que se desea que tenga el fichero comprimido. De hecho. (5) La última etapa de JPEG 2000 es una reorganización de los distintos bitstream obtenidos de codificar cada uno de los bloques con EBCOT. ya que permite indicar el tipo de escalabilidad deseada y el tamaño exacto del fichero final. hasta llegar al plano de bits menos significativo. en este caso la DWT. El LTW es un compresor basado en la transformada Wavelet que intenta mantener la eficiencia en compresión de JPEG 2000. el efecto de bloque típico de JPEG no aparecerá.. JPEG 2000 es un compresor muy versátil. y cada uno de estos bloques se codifica separadamente usando el algoritmo EBCOT. evitando así las múltiples iteraciones necesarias para codificar cada 11 . empieza comprimiendo el bit más significativo de todos los coeficientes.

se codifica como cero aislado. como otros compresores basados en Wavelets (por ejemplo. con lo que se pierde la posibilidad de indicar un tamaño exacto de fichero. Aprovechando esta estructura de árboles. y sus bits por debajo del más significativo distinto de cero). Es importante destacar que este compresor es eficiente por el hecho de que si un coeficiente es distinto de cero en un determinado nivel.coeficiente Wavelet. El compresor LTW. codificamos el valor del coeficiente (para ello se codifica el número de bits que tiene dicho coeficiente. Este símbolo ya representa todo el árbol. podemos definir la estructura de árboles que se muestra en la parte derecha de la figura. El nivel de compresión se varía por medio de un parámetro de cuantización. pero tiene algún descendiente distinto de cero. y 16 coeficientes del primer nivel. con lo que sus descendientes de las siguientes subbandas ya no se codificarán. Además. Por ejemplo. es bastante probable que sus descendientes también lo sean. codificamos un símbolo “L” (con un codificador aritmético). este compresor es escalable en resolución (se codifican antes los coeficientes de las subbandas de menor nivel). tal y como se muestra en la siguiente figura. el codificador LTW comprime los coeficientes wavelet. parte izquierda: HL2 HL3 LH2 HH2 HL1 HL2 HL1 LH1 HH1 De esta forma. usando el símbolo “I” (4) Si por el contrario el coeficiente no es cero. Además no usa ningún tipo de algoritmo de optimización de Lagrange. (3) Si el coeficiente es cero. se corresponde espacialmente con 4 coeficientes del segundo nivel. es fácil observar que un coeficiente en una subbanda de un tercer nivel. EZW y SPIHT). de la siguiente forma: (1) Se recorren las subbandas desde las de mayor nivel hasta las de primer nivel (2) Por cada coeficiente que sea cero (después de cuantización) y todos sus descendientes en el árbol también sean cero. pero no lo es en calidad. se propone la lectura del artículo “Lowcomplexity multiresolution image compression using wavelet lower trees” de la revista 12 . Para más información sobre este codificador. ordena los coeficientes en árboles.

como índice de distorsión usaremos el PSNR (que realmente indica calidad.jp2 -F lena512.0625.pgm -m psnr siendo el PSNR el último de los números que aparece como resultado de esta ejecución. en términos de índice de compresión (curva “tasa de bits/distorsión”) y en coste computacional (curva “tasa de bits/tiempo de ejecución”). En concreto vamos a emplear la implementación estándar de JPEG 2000 denominada JASPER (software de referencia incluido en la parte 5 del estándar) y el LTW implementado por los autores de la propuesta.125. 0.IEEE Transactions on Circuits and Systems for Video Technology. 0. Ejercicio 4 En este último ejercicio vamos a comparar dos implementaciones de JPEG 2000 y LTW.pgm --output lena. mejor calidad presenta la imagen). esta relación se puede calcular fácilmente como el resultado de dividir el número de bits del fichero comprimido entre el número de pixels de la imagen.25 Con esta orden podrás comprimir la imagen Lena sobre el fichero “lena.015625} 13 . Para comparar el nivel de compresión de ambos codificadores vamos a dibujar la gráfica “tasa de bits/distorsión” usando la imagen estándar “Lena”. Utiliza el siguiente conjunto de parámetros y construye ambas gráficas para JPEG 2000: rate={0. número 11.03125. necesitamos comparar la imagen comprimida con la original. Esto se puede hacer simplemente tecleando imgcmp -f lena. Volumen 16. 0. Como la imagen es de dimensiones 512x512.jp2 -O mode=real -O rate=0. así que cuanto mayor es el índice. En concreto. para obtener un punto de la gráfica que relaciona PSNR y bits por píxel.jp2”. usaremos los “bits por píxel” del fichero resultante. Respecto al nivel de compresión. noviembre de 2006. Para obtener el resto de puntos que nos sirva para completar ambas gráficas tendremos que modificar el parámetro “rate” en la compresión. esto es: “Bits por píxel =(Tamaño del fichero*8)/(512*512)” Para realizar la compresión con JPEG 2000 basta con teclear jasper --input lena512. y obtendrás directamente el número de millones de ciclos de CPU que se han empleado para la codificación. A partir de este valor y el tamaño del fichero resultante puedes obtener un punto de la gráfica que relaciona tiempo de ejecución y bits por píxel. A su vez.

75 1 1.75 1 1.25 0.75 2 Bits por pixel PSNR (dB) 45 40 35 30 0.25 1.25 1.Millones de ciclo de CPU 250 200 150 100 50 0 0.5 1.75 2 Bits por pixel 14 .5 1.5 0.5 0.25 0.

y aplicar la transformada en el tiempo. editable con IrfanView). En este esquema. Posibles extensiones de la práctica Como extensiones de la práctica. y comparando con el origina.9. simplemente deberás llevar a cabo las mismas modificaciones que hiciste cuando pasaste de una transformada 1D DWT a 2D DWT. En la predicción. 7. 4. en la que la tercera dimensión sería el tiempo. y se suceden pasos de predicción y actualización. Finalmente se aplica una etapa de 15 . No te olvides de implementar la transformada inversa 2) Implementar una transformada wavelet 1D siguiendo el esquema lifting. Así. 3.2} También puedes observar las distintas versiones de la imagen que se van obteniendo (fichero lenaRec. Esta implementación estaría orientada a una secuencia de vídeo. y su correspondencia con el índice PSNR.ltw –q 0.A continuación vamos a rellenar las mismas gráficas para el compresor LTW. en primer lugar las muestras se dividen entre muestras pares e impares.pgm –o lena. Para ello es conveniente que uses un bolígrafo de otro color para realizar los trazos que formen las nuevas gráficas. de la siguiente forma: LTWdecod –i lena. con distintas escalabilidades.ltw –o lenaRec. el conjunto de muestras pares se intenta predecir a partir de las impares. Para realizar esta ampliación. ten en cuenta que JPEG 2000 permite la creación de un bitstream más flexible.45 –t y anotaremos el tiempo de ejecución del codificador y los bits por píxel resultantes.6. deberás cargar un grupo de imágenes en memoria (que formen el vídeo). Una vez construida la gráfica. se propone 1) Realizar una implementación de la transformada wavelet 3D. mientras que en la actualización se realiza un ajuste de las impares a partir de las pares.pgm.8. El esquema lifting es una forma de calcular la transformada Wavelet totalmente distinta a la aplicación de filtros. 1. ¿Qué compresor consideras mejor según estos parámetros? Independientemente de los resultados obtenidos. Para llevar a cabo la compresión teclearemos LTWcod –i lena512. El PSNR lo podremos calcular usando el descompresor.pgm –c lena512. y que además es un compresor estándar.pgm Utiliza el siguiente conjunto de parámetros de cuantización para construir la gráfica: –q={0. ya podrás comparar ambos compresores en eficiencia de compresión y coste computacional.

A new. M. K. W. 3) Implementar un compresor basado en la transformada Wavelet Aparte del LTW y EBCOT. vol. Pearlman. Una vez implementada la transformada Wavelet en esta práctica. Rabbani. no3. pp. el siguiente paso sería usar esta transformada para realizar la implementación de uno de estos compresores. Speech. A. 14. R. Ejemplos de estos compresores son el SFQ. 3. 17. R. [RAB02] M. An overview of the JPEG2000 still image compression standard. Low complexity resolution progressive image coding algorithm: PROGRES (Progressive Resolution Decompression). 2002. vol. obteniendo los mismos resultados que al usar los filtros. Space-frequency quantization for wavelet image coding. 2035-2038. 677-693. [SWE96] W. Para implementar este esquema. Rabbani. IEEE Transactions on circuits and systems for video technology. A. and efficient image codec based on set partitioning in hierarchical trees. 46. IEEE International Conference on Image Processing. Islam. varios codificadores basados en la transformada Wavelet han sido publicados en distintas revistas. IEEE International Conference on Acoustics. vol. pp. Pearlman. 1219-1235. [CHY00] C. A. PROGRES. Xiong. A. Efficient. podéis usar las siguientes referencias: [RAB02] M. SPECK y SBPH. vol. A. pp. 2002. 17. Chrysafis. September 2005. Pearlman. pp. A. 1996. Said. W. and Signal Processing. Vol. Said. Nagaraj. May 1997. Orchard. June 1996. Signal Processing: Image Communication.A low complexity wavelet coder. Signal Processing: Image Communication. IEEE Transactions on Image Processing. Ramchandran. The lifting scheme: a custom-design construction of biorthogonal wavelets. 16 . Said. low-complexity image coding with a set-partitioning embedded block coder. Journal of Applied Computational and Harmonic Analysis. A. Pearlman. [XIO97] Z. A. A. November 2004. Said. Islam. Joshi. 2000. N.normalización. SPIHT. IEEE Transactions on Circuits and Systems for Video technology. [PEA04] W. 186-200. Joshi. An overview of the JPEG2000 still image compression standard. Puedes usar las siguientes referencias para obtener más información: [CHO05] Yushin Cho. 6. vol. Sweldens. En esta extensión tendréis que implementar la transformada 1D según este esquema. fast. Drukarev. A. SBHP. [SAI96] A.

Sign up to vote on this title
UsefulNot useful