Etiquetas

miércoles, 29 de mayo de 2013

Image Compression - Wavelets

For this post, show you how to work on image compression.

Waveletes
To accomplish this task using what are wavelets, which are a type of Fourier transform. The wavelet transform is to compare the signal with certain wavelet functions, which are obtained from the mother wavelet. The comparison allows to obtain the coefficients are interpretable and further manipulation.

PyWavelets
To carry out the compression used pywavelets which is a wave abirto code and serves to transform python. It is necessary to use this module you need to install pywt. To do this we can just download it from the terminal with the following line:

sudo apt-get install python-pywt

Process


To do this work with the Discrete Wavelet Transform, with which we obtain a new representation of the image to be treated.

Within this process the TWD provides a matrix of coefficients, which are the four wavelet coefficients:
  1. approximations
  2. horizontal coefficients
  3. vertical coefficients
  4. diagonal coefficients
In the following image shows how the coefficients are obtained:

Haar transform used to treat 2-dimensional images, which we use to get our 4 coefficients.

The process is performed as follows:
  1.  Enter imgagen you want to compress
  2.  After you get the size in bytes of the image from the original image
  3.  We estimate each of the coefficients (approximations, horizontal, vertical and diagonal)

    def coeficientes(matrix):#Obtener los coefficientes 2D
    coeffs=pywt.dwt2(matrix,'haar')
    cA,(cH,cV,cD)=coeffs#cA=approximacion,cH=Detalle horizontal,cV=Detalle vertical,cD=Detalle diagonal
    return (cA,cH,cV,cD),coeffs
    view raw coeficientes.py hosted with ❤ by GitHub
  4. After obtaining the coefficients, we apply them within a binary filter for so the new images.

    def binario(mat):
    ancho = len(mat)
    alto = len(mat[0])
    nuevo = 0
    foto = Image.new('RGBA',(ancho, alto)) #nueva imagen
    pixeles = foto.load()
    for i in range(ancho):
    for j in range(alto):
    if mat[i,j]<0:
    nuevo = 0
    elif mat[i,j]>255:
    nuevo = 255
    else:
    nuevo = int(mat[i,j])
    pixeles[i,j] = (nuevo,nuevo,nuevo)
    return foto
    view raw filtro_bin.py hosted with ❤ by GitHub
  5. Also after that calculate the inverse image to apply the compression process.

    def inversa(coeffis,escala):
    inv = pywt.idwt2(coefficientes,'haar')
    pixeles = escala.load()
    ancho,alto = escala.size
    for i in range(ancho):
    for j in range(alto):
    nuevo = int (inv[i,j])
    pixeles[i,j] = (nuevo,nuevo,nuevo)
    return escala
    view raw inversa.py hosted with ❤ by GitHub

Below will show some of the tests performed with different images.

Test 1:

Approximation coefficient   


Horizontal coefficient


Vertical Coefficient


Diagonal Coefficient


Finally this is the compressed image below shows the change that was from one image to another. (reverse image)


Here attached another test that you make with a different image which contained a little more color, and is slightly heavier than the first.

Test 2:

Approximation coefficient   


Horizontal coefficient


Vertical Coefficient


Diagonal Coefficient


And the reverse image


Conclusions

According to the tests you make think it depends on the weight of the image, so that when compressing it look as similar to the original, another thing I noticed is that it also depends on how well defined this image, because for example in the first test can fully appreciate the detail between one figure and another, while in the second test is different.

Another thing you can do is check if the compression works with images that contain a lot of noise and not lost many details of the original image. Below I made a small test this:

Test 3:


Approximation coefficient   


Horizontal coefficient


Vertical Coefficient


Diagonal Coefficient


And the reverse image:


And we see in this image with more noise, reduced compression almost the weight of the picture and not get upset too.

Here attached the code you use.

import pywt
from PIL import Image
import numpy
import os
import Gnuplot
from time import *
def matriz(foto):
ancho,alto=foto.size
pixeles=foto.load()
matrix=numpy.empty((ancho,alto))
for i in range(ancho):
for j in range(alto):
(r,g,b)=foto.getpixel((i,j))
matrix[i,j]=r
return matrix
def coeficientes(matrix):#Obtener los coefficientes
coeffs=pywt.dwt2(matrix,'haar')
cA,(cH,cV,cD)=coeffs
return (cA,cH,cV,cD),coeffs
def binario(mat,c,to,ti):
ancho=len(mat)
alto=len(mat[0])
nuevo=0
foto=Image.new('RGB',(ancho,alto))
pixeles=foto.load()
for i in range(ancho):
for j in range(alto):
if mat[i,j]<0:
nuevo=0
elif mat[i,j]>255:
nuevo=255
else:
nuevo=int(mat[i,j])
pixeles[i,j]=(nuevo,nuevo,nuevo)
foto.save('coefficiente'+str(c)+'.jpg')
def inversa(coefficientes,escala):
inv=pywt.idwt2(coefficientes,'haar')
pixeles=escala.load()
ancho,alto=escala.size
for i in range(ancho):
for j in range(alto):
nuevo=int(inv[i,j])
pixeles[i,j]=(nuevo,nuevo,nuevo)
return escala
def main():
img=str(raw_input('Nombre de imagen: '))#cargar imagen
foto=Image.open(img)
ancho,alto=foto.size
f=os.stat(img)
print f
ti=time()
tamano_original=f.st_size
matrix=matriz(foto)
coe,coeff=coeficientes(matrix)
nueva_imagen(coe,tamano_original)
foto=inversa(coeff,foto)
foto.save('Inversa.jpg')
f=os.stat('Inversa.jpg')
tamano=f.st_size
porcentaje=(tamano*100)/float(tamano_original)
print "Resultado de imagen"
print "Tamano Imagen original:"+str(tamano_original)+"bytes"
print "Tamano con compression:"+str(tamano)+"bytes"
print "Porcentaje de compression:"+str(100-porcentaje)+"%"
print "Tiempo de compression: "+str(tt)+"segundos"
print "-------------------------------------------"
main()
view raw wavelets.py hosted with ❤ by GitHub
References




1 comentario:

  1. Aquí las reversas y los detalles no en realidad son de interés, sino la comparación entre original y comprimida. Hubiera sido bueno discutir los tiempos de ejecución. Las referencias carecen formato. 5 pts por el reporte.

    El código ocuparía comentarios (por mínimo tienes explicación por pedazos) y alguna contribución tuya. Pero pues, que sean 6 pts. Te veré en segundas ;)

    ResponderEliminar