├── README.md ├── __pycache__ ├── app.cpython-37.pyc ├── get_coeff.cpython-37.pyc ├── idwt.cpython-37.pyc ├── image.cpython-37.pyc ├── output.cpython-37.pyc └── test.cpython-37.pyc ├── app.py ├── get_coeff.py ├── output.py ├── startscreen.png └── utils ├── __init__.py └── __pycache__ └── __init__.cpython-37.pyc /README.md: -------------------------------------------------------------------------------- 1 | # Image Compression using discrete wavelet transform 2 | 3 | With the advent of powerful image sensors that provide very high-quality images, image  compression has become a necessity. Images have to be transferred over large distances  viz space telescopes, rendered on mobile phones having weaker internet connection and  be used in various other applications. Our project aims to address some of these issues  by using Discrete Wavelet Transform based image compression in python. 4 | 5 | ### Prerequisites 6 | 7 | What things you need to install the software and how to install them 8 | 9 | ``` 10 | numpy : pip3 install numpy 11 | PILLOW : pip3 install Pillow 12 | PyWavelet : pip3 install PyWavelets 13 | ``` 14 | 15 | ## Authors 16 | 17 | * [**Namit Shah**](https://github.com/NamitS27) 18 | * [**Martand Javia**](https://github.com/MRJ35) 19 | * [**Harvish Jariwala**](https://github.com/harvishj) 20 | 21 | See also the list of [contributors](https://github.com/NamitS27/Image-Compression-DWT/graphs/contributors) who participated in this project. 22 | 23 | -------------------------------------------------------------------------------- /__pycache__/app.cpython-37.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/NamitS27/Image-Compression-DWT/616f72cecd893ddd266f5fa32e1e91536231a0cb/__pycache__/app.cpython-37.pyc -------------------------------------------------------------------------------- /__pycache__/get_coeff.cpython-37.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/NamitS27/Image-Compression-DWT/616f72cecd893ddd266f5fa32e1e91536231a0cb/__pycache__/get_coeff.cpython-37.pyc -------------------------------------------------------------------------------- /__pycache__/idwt.cpython-37.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/NamitS27/Image-Compression-DWT/616f72cecd893ddd266f5fa32e1e91536231a0cb/__pycache__/idwt.cpython-37.pyc -------------------------------------------------------------------------------- /__pycache__/image.cpython-37.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/NamitS27/Image-Compression-DWT/616f72cecd893ddd266f5fa32e1e91536231a0cb/__pycache__/image.cpython-37.pyc -------------------------------------------------------------------------------- /__pycache__/output.cpython-37.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/NamitS27/Image-Compression-DWT/616f72cecd893ddd266f5fa32e1e91536231a0cb/__pycache__/output.cpython-37.pyc -------------------------------------------------------------------------------- /__pycache__/test.cpython-37.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/NamitS27/Image-Compression-DWT/616f72cecd893ddd266f5fa32e1e91536231a0cb/__pycache__/test.cpython-37.pyc -------------------------------------------------------------------------------- /app.py: -------------------------------------------------------------------------------- 1 | import os 2 | import get_coeff as comp 3 | import utils as util 4 | import numpy as np 5 | from PIL import Image, ImageEnhance,ImageTk 6 | import pywt 7 | import tkinter as tk 8 | import tkinter.filedialog as tf 9 | import math 10 | import output as getit 11 | 12 | 13 | def running(file, file_comp, file_ext): 14 | img = util.load_img(file) # Loads the image selected 15 | coef = comp.extract_rgb_coeff(img) # Extracts the RBG Coefficients from the image 16 | image = comp.img_from_dwt_coeff(coef) # Forms the new image using the dwt coeeficients 17 | comp_file = "compress"+file_ext 18 | image.save(comp_file) # Saves the image 19 | 20 | ''' 21 | Below lines of the code are to resize and enhance the images 22 | ''' 23 | enhancer = ImageEnhance.Brightness(image) 24 | image = enhancer.enhance(2) 25 | 26 | file_enh = "enhanced"+file_ext 27 | image.save(file_enh) 28 | im = Image.open(file_enh) 29 | size = get_image_dimensions(file) 30 | im_resized = im.resize(size, Image. 31 | ANTIALIAS) 32 | im_resized.save(file_comp) 33 | 34 | os.remove(comp_file) 35 | os.remove(file_enh) 36 | return os.path.getsize(file)/os.path.getsize(file_comp) 37 | 38 | 39 | def get_image_dimensions(imagefile): # Function to get the dimensions of the image 40 | with Image.open(imagefile) as img: 41 | width, height = img.size 42 | return int(width), int(height) # returns the width and height of the image in terms of pixels 43 | 44 | 45 | def create_folder(): 46 | path = "Compressed_Images" # Creates the folder and in order to save the image in this folder 47 | os.rmdir(path) 48 | os.mkdir(path) 49 | 50 | 51 | def run(): 52 | ''' 53 | Main Function to run the compression 54 | ''' 55 | root = tk.Tk() # Window for choosing the images 56 | load = Image.open("startscreen.png") 57 | render = ImageTk.PhotoImage(load) 58 | 59 | img = tk.Label(image=render) 60 | img.pack(side = "bottom", fill = "both", expand = "yes") 61 | root.geometry("700x700") 62 | center(root) 63 | 64 | file = tf.askopenfilenames(title="Choose Images", filetypes=( 65 | ("jpeg files", "*.jpg"), ("png files", "*.png"))) # Select two type of iamges : jpg and png 66 | files = list(file) 67 | # create_folder() 68 | ans = 0 69 | mini = math.inf 70 | maxi = -math.inf 71 | for i in range(len(file)): 72 | x = list(file[i]) 73 | ind = 0 74 | for j in range(len(x)): 75 | if x[j] == '/': 76 | ind = j 77 | ext = str(file[i][len(x)-4:len(x)]) 78 | file2 = "Compressed_Images/"+file[i][ind+1:len(x)-4]+"_compressed"+ext # create the path inorder to save the compressed image in the created folder 79 | ans1 = running(file[i], file2, ext) # The function to compress the image which returns the compression ratio 80 | 81 | ''' 82 | Finds the maximum compression and minimum compression ratio when multiple images are selected 83 | ''' 84 | mini = min(mini, ans1) 85 | maxi = max(maxi, ans1) 86 | ans += ans1 87 | 88 | print("\nCompression Ratio : %.2f" % (ans/len(file))) 89 | print("\nMax : "+str(maxi) + "\nMin : " + str(mini)) 90 | root.destroy() 91 | getit.run(files) 92 | 93 | def center(win): 94 | """ 95 | centers a tkinter window 96 | :param win: the root or Toplevel window to center 97 | """ 98 | win.update_idletasks() 99 | width = win.winfo_width() 100 | frm_width = win.winfo_rootx() - win.winfo_x() 101 | win_width = width + 2 * frm_width 102 | height = win.winfo_height() 103 | titlebar_height = win.winfo_rooty() - win.winfo_y() 104 | win_height = height + titlebar_height + frm_width 105 | x = win.winfo_screenwidth() // 2 - win_width // 2 106 | y = win.winfo_screenheight() // 2 - win_height // 2 107 | win.geometry('{}x{}+{}+{}'.format(width, height, x, y)) 108 | win.deiconify() 109 | 110 | 111 | if __name__ == "__main__": 112 | run() 113 | -------------------------------------------------------------------------------- /get_coeff.py: -------------------------------------------------------------------------------- 1 | # pylint: disable=C0103,E0401,W0631 2 | 'Compression methods' 3 | import pywt 4 | import numpy 5 | from PIL import Image 6 | import utils as util 7 | 8 | 9 | def extract_rgb_coeff(img): 10 | """ 11 | Returns RGB dwt applied coefficients tuple 12 | Parameters 13 | ---------- 14 | img: PIL Image 15 | Returns 16 | ------- 17 | (coeffs_r, coeffs_g, coeffs_b): 18 | RGB coefficients with Discrete Wavelet Transform Applied 19 | """ 20 | (width, height) = img.size 21 | img = img.copy() 22 | 23 | mat_r = numpy.empty((width, height)) 24 | mat_g = numpy.empty((width, height)) 25 | mat_b = numpy.empty((width, height)) 26 | 27 | for i in range(width): 28 | for j in range(height): 29 | (r, g, b) = img.getpixel((i, j)) 30 | mat_r[i, j] = r 31 | mat_g[i, j] = g 32 | mat_b[i, j] = b 33 | 34 | coeffs_r = pywt.dwt2(mat_r, 'haar') 35 | 36 | coeffs_g = pywt.dwt2(mat_g, 'haar') 37 | 38 | coeffs_b = pywt.dwt2(mat_b, 'haar') 39 | 40 | return (coeffs_r, coeffs_g, coeffs_b) 41 | 42 | 43 | def img_from_dwt_coeff(coeff_dwt): 44 | """ 45 | Returns Image recreated from dwt coefficients 46 | Parameters 47 | ---------- 48 | (coeffs_r, coeffs_g, coeffs_b): 49 | RGB coefficients with Discrete Wavelet Transform Applied 50 | Returns 51 | ------- 52 | Image from dwt coefficients 53 | """ 54 | # Channel Red 55 | (coeffs_r, coeffs_g, coeffs_b) = coeff_dwt 56 | 57 | cc = numpy.array((coeffs_r, coeffs_g, coeffs_b)) 58 | 59 | (width, height) = (len(coeffs_r[0]), len(coeffs_r[0][0])) 60 | 61 | cARed = numpy.array(coeffs_r[0]) 62 | cHRed = numpy.array(coeffs_r[1][0]) 63 | cVRed = numpy.array(coeffs_r[1][1]) 64 | cDRed = numpy.array(coeffs_r[1][2]) 65 | # Channel Green 66 | cAGreen = numpy.array(coeffs_g[0]) 67 | cHGreen = numpy.array(coeffs_g[1][0]) 68 | cVGreen = numpy.array(coeffs_g[1][1]) 69 | cDGreen = numpy.array(coeffs_g[1][2]) 70 | # Channel Blue 71 | cABlue = numpy.array(coeffs_b[0]) 72 | cHBlue = numpy.array(coeffs_b[1][0]) 73 | cVBlue = numpy.array(coeffs_b[1][1]) 74 | cDBlue = numpy.array(coeffs_b[1][2]) 75 | 76 | # maxValue per channel par matrix 77 | cAMaxRed = util.max_ndarray(cARed) 78 | cAMaxGreen = util.max_ndarray(cAGreen) 79 | cAMaxBlue = util.max_ndarray(cABlue) 80 | 81 | cHMaxRed = util.max_ndarray(cHRed) 82 | cHMaxGreen = util.max_ndarray(cHGreen) 83 | cHMaxBlue = util.max_ndarray(cHBlue) 84 | 85 | cVMaxRed = util.max_ndarray(cVRed) 86 | cVMaxGreen = util.max_ndarray(cVGreen) 87 | cVMaxBlue = util.max_ndarray(cVBlue) 88 | 89 | cDMaxRed = util.max_ndarray(cDRed) 90 | cDMaxGreen = util.max_ndarray(cDGreen) 91 | cDMaxBlue = util.max_ndarray(cDBlue) 92 | 93 | # Image object init 94 | dwt_img = Image.new('RGB', (width, height), (0, 0, 20)) 95 | # cA reconstruction 96 | 97 | ''' 98 | The image formed from the low frequnecy of the images which contains the main content of the image 99 | ''' 100 | for i in range(width): 101 | for j in range(height): 102 | R = cARed[i][j] 103 | R = (R/cAMaxRed)*100.0 104 | G = cAGreen[i][j] 105 | G = (G/cAMaxGreen)*100.0 106 | B = cABlue[i][j] 107 | B = (B/cAMaxBlue)*100.0 108 | new_value = (int(R), int(G), int(B)) 109 | dwt_img.putpixel((i, j), new_value) 110 | 111 | return dwt_img -------------------------------------------------------------------------------- /output.py: -------------------------------------------------------------------------------- 1 | from tkinter import * 2 | from PIL import Image 3 | import ntpath 4 | import os 5 | import math 6 | import app as appy 7 | 8 | def hspace(col,root): 9 | ''' 10 | Adding horizontal space 11 | ''' 12 | space = Label(root,text = " ",bg = '#3ed8ea') 13 | space.grid(row=2,column=col) 14 | 15 | def vspace(row,root): 16 | ''' 17 | Adding Vertical Space 18 | ''' 19 | space = Label(root,text = " ",bg = '#3ed8ea') 20 | space.grid(row=row) 21 | 22 | def leftClick(event,x): 23 | ''' 24 | Left Click event to open image 25 | ''' 26 | im = Image.open(x) 27 | im.show() 28 | 29 | def run(fileList): 30 | ''' 31 | Creates the window 32 | ''' 33 | root = Tk() 34 | root.title("Image Compression") 35 | root.geometry('1070x400') 36 | root.configure(background='#3ed8ea') 37 | root.resizable(True,False) 38 | appy.center(root) 39 | vspace(0,root) 40 | 41 | image_name = Label(root,text="Image Name",borderwidth=2, relief="solid",bg = '#3ed8ea',fg='#1c1c6c',height=2,width=25,font='Verdana 12') 42 | image_name.grid(row=2,column = 0) 43 | vspace(3,root) 44 | hspace(1,root) 45 | oi = Label(root,text="Original Image Size",borderwidth=2, relief="solid",bg = '#3ed8ea',fg='#1c1c6c',height=2,width=25,font='Verdana 12') 46 | oi.grid(row=2,column=2) 47 | hspace(3,root) 48 | ci = Label(root,text="Compressed Image Size",borderwidth=2, relief="solid",bg = '#3ed8ea',fg='#1c1c6c',height=2,width=25,font='Verdana 12') 49 | ci.grid(row=2,column=4) 50 | hspace(5,root) 51 | cr = Label(root,text="Compression Ratio",borderwidth=2, relief="solid",bg = '#3ed8ea',fg='#1c1c6c',height=2,width=25,font='Verdana 12') 52 | cr.grid(row=2,column=6) 53 | 54 | rows = 4 55 | ''' 56 | Adding the files in the list along with the size of original image and compressed image and also compression ratio 57 | ''' 58 | for i in range(len(fileList)): 59 | name = ntpath.basename(fileList[i]) 60 | compressed_file_name = "Compressed_Images/"+name[:len(name)-4]+"_compressed"+name[len(name)-4:] 61 | create_table(root,name,fileList[i],compressed_file_name,rows) 62 | rows = rows+1 63 | mainloop() 64 | 65 | def extract_ratio(str1,str2): 66 | ''' 67 | Finds the compression ratio 68 | ''' 69 | s1 = int(str1[:len(str1)-3]) 70 | s2 = int(str2[:len(str2)-3]) 71 | return "%.2f"%(s1/s2) 72 | 73 | def create_table(root,name,file,file2,row): 74 | ''' 75 | This is used for adding multiple images in the list. 76 | On clicking the original image, it opens the original image 77 | On clicking the compressed image, it opens the compressed image 78 | ''' 79 | image = Label(root,text=name,bg = '#3ed8ea',fg='#1c1c6c',font='Verdana 12') 80 | image.grid(row=row,column = 0) 81 | image1 = Label(root,text = meta_data(file),bg = '#3ed8ea',fg='#1c1c6c',font='Verdana 12') 82 | image1.grid(row=row,column = 2) 83 | image1.bind("",lambda event:leftClick(event,file)) 84 | image1 = Label(root,text = meta_data(file2),bg = '#3ed8ea',fg='#1c1c6c',font='Verdana 12') 85 | image1.grid(row=row,column = 4) 86 | image1.bind("",lambda event:leftClick(event,file2)) 87 | image1 = Label(root,text = extract_ratio(meta_data(file),meta_data(file2)),bg = '#3ed8ea',fg='#1c1c6c',font='Verdana 12') 88 | image1.grid(row=row,column = 6) 89 | 90 | def meta_data(filen): 91 | ''' 92 | Gives the file size of the selected file in Kb 93 | ''' 94 | return str(math.ceil(int(os.path.getsize(filen))/1024)) + " Kb" 95 | -------------------------------------------------------------------------------- /startscreen.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/NamitS27/Image-Compression-DWT/616f72cecd893ddd266f5fa32e1e91536231a0cb/startscreen.png -------------------------------------------------------------------------------- /utils/__init__.py: -------------------------------------------------------------------------------- 1 | # pylint: disable=E0401 2 | 'Utility methods for the project' 3 | from PIL import Image 4 | import numpy as np 5 | 6 | def load_img(path): 7 | """ 8 | Returns an Image object if path is an existing image, otherwise None 9 | Parameters 10 | ---------- 11 | path: string 12 | image path to open 13 | Returns 14 | ------- 15 | Image: 16 | image object 17 | """ 18 | try: 19 | return Image.open(path) 20 | except IOError: 21 | return None 22 | 23 | def max_ndarray(mat): 24 | """ 25 | Returns maximum value within a given 2D Matrix, otherwise 0 26 | Parameters 27 | ---------- 28 | mat: numpy.ndarray 29 | matrix from which we want to compute the max value 30 | Returns 31 | ------- 32 | int32: 33 | matrix maximum value 34 | """ 35 | return np.amax(mat) if type(mat).__name__ == 'ndarray' else 0 36 | -------------------------------------------------------------------------------- /utils/__pycache__/__init__.cpython-37.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/NamitS27/Image-Compression-DWT/616f72cecd893ddd266f5fa32e1e91536231a0cb/utils/__pycache__/__init__.cpython-37.pyc --------------------------------------------------------------------------------