Teoría de la Información Y
Métodos de Codificación
Image Compressor
The process effected was as follows:
- Get an image .jpg what is asked the user.
- Convert this image a gray scale.
- It loads in an array one of variables rgb (As in each rgb the elements are equal, you take only one).
- Decomposes the array using the library wavedec2 of pywt, the result gives us three variables, the first 2 are used only to rebuild the array. The last is applied one process (this is the coefficient variable).
- Make new array of coefficient using the variable coefficient, sweep every element of the array and compares with the threshol, if data success the condition the value of the array is 0. All data (success the condition or not) save in the array.
- Add in the new list the 2 variable and the array and aplied the method waverec2 and get one array, this array can change to integer for continue. This array is used to create the new image.
- Sweep the array get every pixel of the image with your rgb (every element x 3) and create the new image.
- Compare the weight of the image in gray scale with the compress for obtain the compress percentage.
Code Used
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import Image | |
import os | |
import sys | |
import numpy | |
import pywt | |
import random | |
#Convierte la imagen original a escala de grises y regresa la variable Image de la imagen a escala de grises | |
def grises(im, name, ext): | |
x, y = im.size | |
pixeles = im.load() | |
for i in range(x): | |
for j in range(y): | |
(r,g,b) = pixeles[i,j] #Obtengo el rgb del pixel[i, j] de la imagen | |
suma = r + g + b #Sumo las variables | |
promedio = int(suma/3) #Obtengo el promedio de la suma | |
#Sustituyo el promedio para cada variable | |
r = promedio | |
g = promedio | |
b = promedio | |
pixeles[i,j] = (r,g,b) #Se substituye en el pixel[i, j] el nuevo valor rgb | |
ImGrises = name+"-Grises"+ext | |
im.save(ImGrises) #Se crea la nueva imagen | |
return ImGrises | |
#Metodo en el cual se obtienen los rgb de cada pixel de la imagen a escala de grises y se agrega el elemento r (de los rgb) a una lista, por ultimo esa lista se convierte a un arreglo de numpy para trabajarlo de la mejor manera | |
def matriz(ImGrises): | |
im2 = Image.open(ImGrises) | |
x, y = im2.size | |
pixeles = im2.load() | |
lista1 = list() | |
for i in range(x): | |
lista2 = list() | |
for j in range(y): | |
lista2.append(pixeles[i,j][0]) #Agrego a la lista el primer elemento del arreglo, como son iguales puedo poner o el segundo o el tercero | |
lista1.append(lista2) | |
arreglo = numpy.array(lista1) #Convierto la lista a arreglo de numpy para poderlo utilizar | |
return arreglo | |
#En este metodo se obtiene el arreglo, el cual sera utilizado para crear la imagen comprimida | |
def pequeno(arreglo, umbral): | |
j = pywt.Wavelet('haar') #Se define el wavelet a usar | |
var = pywt.wavedec2(arreglo, j, level=2) #Se descompone el arreglo | |
a, b, coeficientes = var #Se guarda en tres variables la descomposicion del arreglo | |
lista = list() #Lista provisional que tendra el resultado de la transformada de cada elemento de la fila de coeficientes comparada con el umbral | |
for i in coeficientes: | |
c = numpy.where(((i > umbral)), i, 0) #Se busca en todo el arreglo i si alguno cumple la condicion si lo cumple valor se cambia por 0 | |
lista.append(c) | |
#Lista que tendra los nuevos coeficientes | |
lisfi = list() | |
lisfi.append(a) | |
lisfi.append(b) | |
lisfi.append(tuple(lista)) | |
arrfi = pywt.waverec2(lisfi, j) #Arreglo que almacena los valores de la lista final aplicados la transformada de wavelet | |
arrint = arrfi.astype(int) #Convertimos todo el arreglo a integer | |
return arrint | |
#Se crea la imagen comprimida en base al arreglo generado de la transformada inversa, se barre en x y despues en y, en cada pixel[x][y] se agrega su rgb correspondiente | |
def crearImagen(x, y, nuearreglo, name, extension, umbral): | |
nimagen = Image.new('RGB', (x, y)) #Variable del tipo image de un tamano x, y de formato RGB | |
lista = list() | |
for i in nuearreglo: | |
lista2 = list() #Lista provisional que almacenara los rgb para cada fila i | |
for j in i: | |
lista2.append((int(j), int(j), int(j))) #Se agrega a la lista el elemento i, j | |
lista.append(lista2) #Se agrega a la lista final los rgb de la fila i | |
#Se barre la lista final para agregarlo a la imagen a crear | |
for i in range(x): | |
for j in range(y): | |
nimagen.putpixel((i, j), lista[i][j]) #Se agrega el pixel i, j el elemento RGB correspondiente de la lista | |
nimagen.save(str(name)+"-Compress con "+str(umbral)+" de Umbral"+str(extension)) #Se crea la imagen | |
nombre = name+"-Compress con "+str(umbral)+' de Umbral'+extension+"" | |
return nombre | |
def detumbral(x, y): | |
umbral = int((x+y)/2) | |
if umbral > 255: | |
#if umbral > x: | |
while True: | |
umbral = umbral / 2 | |
if umbral <= 255: | |
#if umbral <= x: | |
break | |
elif umbral < 0: | |
umbral = 1 | |
return umbral | |
def comparar(ncompre, ngris, x, y): | |
imcompre = Image.open(ncompre) | |
infogri = Image.open(ngris) | |
infogri = os.stat(ngris) | |
infocompre = os.stat(ncompre) | |
tamgri = int(infogri.st_size) | |
tamcompre = int(infocompre.st_size) | |
print "Tamano imagen en escala de grises: ",tamgri, "bytes" | |
print "Tamano imagen comprimida: ",tamcompre, "bytes" | |
porcompress = (float(tamcompre)*100.0) / float(tamgri) | |
porcompress = 100.0 - porcompress | |
print "Porcentaje de Compresion: "+str(porcompress)+"%" | |
def main(): | |
Archivo = str(sys.argv[1]) | |
extension = Archivo[-4:] | |
nombre = Archivo[:-4] | |
info = os.stat(Archivo) | |
im = Image.open(Archivo) | |
x, y = im.size | |
print "Ancho Imagen: ", x | |
print "Alto Imagen: ", y | |
#Se determinal el umbral, si es dado por el usuario con que este dentro del rango no hay problema si se pasa se genera aleatoriamente; si no se da el umbral se aplica el metodo para determinar el umbral | |
try: | |
umbral = int(sys.argv[2]) #Umbral dado por el usuario, debe de ser entre 1 y 255 | |
if umbral > 255 or umbral <= 0: #Si no se cumple la condicion el umbral se da de forma aleatoria | |
umbral = random.randint(1, 255) | |
print "Umbral dado no esta en el rango por lo que se genera aleatoriamente: ", umbral | |
else: | |
print "Voy por el umbral que diste: ", umbral | |
except: | |
umbral = detumbral(x, y) | |
print "Voy por el umbral del metodo: ", umbral | |
ImGrises = grises(im, nombre, extension) #Se crea la imagen a escala de grises | |
Arreglo = matriz(ImGrises) #Guarda en un arreglo | |
narreglo = pequeno(Arreglo, umbral) | |
imfinal = crearImagen(x, y, narreglo, nombre, extension, umbral) | |
print "Tamano imagen original: ",info.st_size, "bytes" | |
comparar(imfinal, ImGrises, x, y) | |
main() |
Make Test
We have the image:
Size 308 x 328
Aplied the Code
Image to gray scale:
Compress the image with threshold of 230.
Threshold 10
Threshold 159
As see in the images, while the threshold is high the quality of the image decreases so the compression become greater.
This can be rectify in the picture of below, which shows the result of the execution:
References
http://www.pybytes.com/pywavelets/ref/2d-dwt-and-idwt.html
Mala ortografía. Hubiera sido bueno medir los tiempos de ejecución. El reporte es además algo breve. 4 pts por el reporte.
ResponderEliminarEl método no es muy original; el simplemente llamadas a librerías y código ejemplo. Por mínimo tiene algo de comentarios... 6 pts por ello. Te veo en segundas.