Skip to content

Commit 746fa96

Browse files
Nicol EmanueleNicol Emanuele
Nicol Emanuele
authored and
Nicol Emanuele
committed
Import project
1 parent bbbc7be commit 746fa96

13 files changed

+261
-0
lines changed

Diff for: .DS_Store

6 KB
Binary file not shown.

Diff for: compressed_image.png

2.63 KB
Loading

Diff for: dct_image_processor.py

+261
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,261 @@
1+
#TODO: Dividere in moduli, testare scaling algoritmo
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, 64]
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()

Diff for: immagini/160x160.bmp

26.1 KB
Binary file not shown.

Diff for: immagini/20x20.bmp

1.44 KB
Binary file not shown.

Diff for: immagini/320x320.bmp

101 KB
Binary file not shown.

Diff for: immagini/40x40.bmp

2.62 KB
Binary file not shown.

Diff for: immagini/640x640.bmp

401 KB
Binary file not shown.

Diff for: immagini/80x80.bmp

7.3 KB
Binary file not shown.

Diff for: immagini/deer.bmp

1.91 MB
Binary file not shown.

Diff for: immagini/gradient.bmp

587 KB
Binary file not shown.

Diff for: immagini/prova.bmp

29.4 KB
Binary file not shown.

Diff for: immagini/shoe.bmp

198 KB
Binary file not shown.

0 commit comments

Comments
 (0)