1
- #TODO: Dividere in moduli, testare scaling algoritmo
1
+ from gui_module import *
2
2
3
- import tkinter as tk
4
- from tkinter import ttk , filedialog , messagebox
5
- from PIL import Image , ImageOps , ImageTk
6
- import numpy as np
7
- import time
8
- import matplotlib .pyplot as plt
9
- import os
10
- from scipy .fftpack import dct , idct
11
- import threading
12
- import queue
13
-
14
- normalize_coefficients = False
15
-
16
- def dct2_manual (matrix ):
17
- N = matrix .shape [0 ]
18
- result = np .zeros_like (matrix , dtype = np .float32 )
19
- for u in range (N ):
20
- for v in range (N ):
21
- sum_val = 0
22
- for x in range (N ):
23
- for y in range (N ):
24
- sum_val += matrix [x , y ] * np .cos (np .pi * u * (2 * x + 1 ) / (2 * N )) * np .cos (np .pi * v * (2 * y + 1 ) / (2 * N ))
25
- alpha_u = np .sqrt (1 / N ) if u == 0 else np .sqrt (2 / N )
26
- alpha_v = np .sqrt (1 / N ) if v == 0 else np .sqrt (2 / N )
27
- result [u , v ] = alpha_u * alpha_v * sum_val
28
- return result
29
-
30
-
31
-
32
- def idct2_manual (matrix ):
33
- N = matrix .shape [0 ]
34
- result = np .zeros_like (matrix , dtype = np .float32 )
35
- for x in range (N ):
36
- for y in range (N ):
37
- sum_val = 0
38
- for u in range (N ):
39
- for v in range (N ):
40
- alpha_u = np .sqrt (1 / N ) if u == 0 else np .sqrt (2 / N )
41
- alpha_v = np .sqrt (1 / N ) if v == 0 else np .sqrt (2 / N )
42
- sum_val += alpha_u * alpha_v * matrix [u , v ] * np .cos (np .pi * u * (2 * x + 1 ) / (2 * N )) * np .cos (np .pi * v * (2 * y + 1 ) / (2 * N ))
43
- result [x , y ] = sum_val
44
- return result
45
-
46
- def dct2 (matrix ):
47
- return dct (dct (matrix .T , norm = 'ortho' ).T , norm = 'ortho' )
48
-
49
- def idct2 (matrix ):
50
- return idct (idct (matrix .T , norm = 'ortho' ).T , norm = 'ortho' )
51
-
52
- def compare_dct2_algorithms (progress_queue , plot_queue ):
53
- sizes = [8 , 16 , 32 ]
54
- manual_times = []
55
- library_times = []
56
-
57
- total_steps = len (sizes ) * 2
58
- step = 0
59
-
60
- for size in sizes :
61
- print ("size: " , size )
62
- matrix = np .random .rand (size , size ).astype (np .float32 )
63
-
64
- start_time = time .time ()
65
- dct2_manual (matrix )
66
- manual_times .append (time .time () - start_time )
67
- step += 1
68
- progress_queue .put ((step / total_steps ) * 100 )
69
-
70
- start_time = time .time ()
71
- dct2 (matrix )
72
- library_times .append (time .time () - start_time )
73
- step += 1
74
- progress_queue .put ((step / total_steps ) * 100 )
75
-
76
- progress_queue .put ("done" )
77
- plot_queue .put ((sizes , manual_times , library_times ))
78
-
79
- def compare_dct2_algorithms_thread (progress_var , progress_bar ):
80
- progress_queue = queue .Queue ()
81
- plot_queue = queue .Queue ()
82
- threading .Thread (target = compare_dct2_algorithms , args = (progress_queue , plot_queue )).start ()
83
- root .after (100 , check_progress , progress_queue , progress_var , progress_bar )
84
- root .after (100 , check_plot , plot_queue )
85
-
86
- def check_progress (progress_queue , progress_var , progress_bar ):
87
- try :
88
- progress = progress_queue .get_nowait ()
89
- if progress == "done" :
90
- return
91
- progress_var .set (progress )
92
- progress_bar .update_idletasks ()
93
- except queue .Empty :
94
- pass
95
- root .after (100 , check_progress , progress_queue , progress_var , progress_bar )
96
-
97
- def check_plot (plot_queue ):
98
- try :
99
- plot_data = plot_queue .get_nowait ()
100
- sizes , manual_times , library_times = plot_data
101
-
102
- plt .figure ()
103
- plt .plot (sizes , manual_times , label = 'Manual DCT2 ' , marker = 'o' )
104
- plt .plot (sizes , library_times , label = 'Library DCT2' , marker = 'o' )
105
- plt .xlabel ('Matrix size (N)' )
106
- plt .ylabel ('Time (s)' )
107
- plt .yscale ('log' )
108
- plt .legend ()
109
- plt .title ('Comparison of DCT2 Algorithms' )
110
- plt .show ()
111
- except queue .Empty :
112
- root .after (100 , check_plot , plot_queue )
113
-
114
- def process_image (file_path , F , d ):
115
- try :
116
- img = Image .open (file_path ).convert ('L' )
117
- except Exception as e :
118
- print (f"Error in opening image: { e } " )
119
- return ""
120
-
121
- gray_img = ImageOps .grayscale (img )
122
- matrix = image_to_matrix (gray_img )
123
-
124
- compressed_matrix = apply_dct_and_idct (matrix , F , d )
125
-
126
- compressed_img = matrix_to_image (compressed_matrix )
127
- compressed_file_path = "compressed_image.png"
128
- compressed_img .save (compressed_file_path )
129
-
130
- return compressed_file_path
131
-
132
- def image_to_matrix (img ):
133
- return np .array (img , dtype = np .float32 )
134
-
135
- def matrix_to_image (matrix ):
136
- min_val , max_val = matrix .min (), matrix .max ()
137
- normalized_matrix = 255 * (matrix - min_val ) / (max_val - min_val )
138
- return Image .fromarray (np .uint8 (normalized_matrix ))
139
-
140
- def apply_dct_and_idct (matrix , F , d ):
141
- height , width = matrix .shape
142
- compressed_matrix = np .zeros_like (matrix )
143
-
144
- for y in range (0 , height , F ):
145
- for x in range (0 , width , F ):
146
- if y + F <= height and x + F <= width :
147
- block = matrix [y :y + F , x :x + F ]
148
- dct_block = dct2 (block )
149
- filtered_dct_block = filter_frequencies (dct_block , d )
150
- idct_block = idct2 (filtered_dct_block )
151
- compressed_matrix [y :y + F , x :x + F ] = idct_block
152
-
153
- return compressed_matrix
154
-
155
- def filter_frequencies (matrix , d ):
156
- size = matrix .shape [0 ]
157
- for k in range (size ):
158
- for l in range (size ):
159
- if k + l >= d :
160
- matrix [k , l ] = 0
161
- return matrix
162
-
163
- def load_image ():
164
- file_path = filedialog .askopenfilename (filetypes = [("BMP files" , "*.bmp" )])
165
- if not file_path :
166
- return
167
-
168
- file_label .config (text = file_path )
169
- original_image = Image .open (file_path )
170
- resized_original_image = resize_image (original_image , 400 , 400 )
171
- original_photo = ImageTk .PhotoImage (resized_original_image )
172
- img_label .config (image = original_photo )
173
- img_label .image = original_photo
174
-
175
- try :
176
- F = int (f_entry .get () or 10 )
177
- d = int (d_entry .get () or 7 )
178
- except ValueError :
179
- messagebox .showerror ("Error" , "Invalid F or d value" )
180
- return
181
-
182
- original_size = os .path .getsize (file_path )
183
- compressed_file_path = process_image (file_path , F , d )
184
- if compressed_file_path :
185
- compressed_size = os .path .getsize (compressed_file_path )
186
- compression_ratio = 100 * (original_size - compressed_size ) / original_size
187
- compression_label .config (text = f"Dimensione originale: { original_size } bytes\n "
188
- f"Dimensione compressa: { compressed_size } bytes\n "
189
- f"Compressione: { compression_ratio :.2f} %" )
190
-
191
- compressed_image = Image .open (compressed_file_path )
192
- resized_compressed_image = resize_image (compressed_image , 400 , 400 )
193
- compressed_photo = ImageTk .PhotoImage (resized_compressed_image )
194
- compressed_img_label .config (image = compressed_photo )
195
- compressed_img_label .image = compressed_photo
196
-
197
- def resize_image (image , max_width , max_height ):
198
- width , height = image .size
199
- if width > max_width or height > max_height :
200
- ratio = min (max_width / width , max_height / height )
201
- new_size = (int (width * ratio ), int (height * ratio ))
202
- image = image .resize (new_size )
203
- return image
204
-
205
- def toggle_normalize ():
206
- global normalize_coefficients
207
- normalize_coefficients = not normalize_coefficients
208
- print ("normalize_coefficients set to" , normalize_coefficients )
209
-
210
- root = tk .Tk ()
211
- root .title ("Compressione di immagini tramite la DCT" )
212
-
213
- root .geometry ("800x600" )
214
-
215
- # Menu bar
216
- menu_bar = tk .Menu (root )
217
- root .config (menu = menu_bar )
218
-
219
- # Create a Notebook
220
- notebook = ttk .Notebook (root )
221
- notebook .pack (expand = True , fill = 'both' )
222
-
223
- # Create frames for each tab
224
- dct_frame = ttk .Frame (notebook )
225
- hello_frame = ttk .Frame (notebook )
226
-
227
- notebook .add (dct_frame , text = "DCT" )
228
- notebook .add (hello_frame , text = ("Comp" ))
229
-
230
- f_entry = tk .Entry (dct_frame )
231
- f_entry .insert (0 , "10" )
232
- d_entry = tk .Entry (dct_frame )
233
- d_entry .insert (0 , "7" )
234
-
235
- normalize_button = tk .Checkbutton (dct_frame , text = "“Normalizzare coefficenti DTC”" , command = toggle_normalize )
236
- load_button = tk .Button (dct_frame , text = "“Load .bmp image”" , command = load_image )
237
- file_label = tk .Label (dct_frame , text = "“Nessun file selezionato”" )
238
- compression_label = tk .Label (dct_frame , text = "””" )
239
-
240
- image_frame = tk .Frame (dct_frame )
241
- image_frame .pack ()
242
-
243
- img_label = tk .Label (image_frame )
244
- compressed_img_label = tk .Label (image_frame )
245
- f_entry .pack ()
246
- d_entry .pack ()
247
- normalize_button .pack ()
248
- load_button .pack ()
249
- file_label .pack ()
250
- compression_label .pack ()
251
- img_label .pack (side = tk .LEFT )
252
- compressed_img_label .pack (side = tk .LEFT )
253
-
254
- progress_var = tk .DoubleVar ()
255
- progress_bar = ttk .Progressbar (hello_frame , variable = progress_var , maximum = 100 )
256
- progress_bar .pack (pady = 10 )
257
-
258
- compare_button = tk .Button (hello_frame , text = "“Compare DCT2 Algorithms”" , command = lambda : compare_dct2_algorithms_thread (progress_var , progress_bar ))
259
- compare_button .pack ()
260
-
261
- root .mainloop ()
3
+ if __name__ == "__main__" :
4
+ root .mainloop ()
0 commit comments