csabhay commited on
Commit
9ef7694
·
1 Parent(s): b50abec

Initial commit

Browse files
Files changed (2) hide show
  1. app.py +72 -0
  2. requirements.txt +4 -0
app.py ADDED
@@ -0,0 +1,72 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import gradio as gr
2
+ import numpy as np
3
+ from sklearn.cluster import KMeans
4
+ from PIL import Image
5
+
6
+ def compress_kmeans(image: np.ndarray, k: int) -> np.ndarray:
7
+ """Reduce image palette to k colours using K-Means vector quantisation."""
8
+ pixels = image.reshape(-1, 3)
9
+ model = KMeans(n_clusters=k, n_init="auto", random_state=42)
10
+ model.fit(pixels)
11
+ centres = model.cluster_centers_.astype(np.uint8)
12
+ labels = model.predict(pixels)
13
+ return centres[labels].reshape(image.shape)
14
+
15
+ def compute_psnr_mse(original: np.ndarray, compressed: np.ndarray):
16
+ """Return (MSE, PSNR) between two images."""
17
+ mse = np.mean((original.astype(np.float64) - compressed.astype(np.float64)) ** 2)
18
+ psnr = float("inf") if mse == 0 else 20.0 * np.log10(255.0 / np.sqrt(mse))
19
+ return mse, psnr
20
+
21
+ def compute_metrics(image: np.ndarray, k: int):
22
+ """Estimate compression ratio and file sizes (theoretical)."""
23
+ h, w, c = image.shape
24
+ original_bits = h * w * c * 8
25
+ compressed_bits = (k * 24) + (h * w * int(np.ceil(np.log2(k))))
26
+ ratio = original_bits / compressed_bits
27
+ return {
28
+ "ratio": ratio,
29
+ "original_kb": original_bits / (8 * 1024),
30
+ "compressed_kb": compressed_bits / (8 * 1024),
31
+ "saved_percent": (1.0 - (1.0 / ratio)) * 100.0,
32
+ }
33
+
34
+ def compress_and_report(image, k):
35
+ """Gradio entry point: compress, compute metrics, return image + report."""
36
+ if isinstance(image, np.ndarray):
37
+ orig = image[:, :, :3] if image.shape[-1] == 4 else image
38
+ else:
39
+ orig = np.array(image.convert("RGB"))
40
+
41
+ compressed = compress_kmeans(orig, k)
42
+ mse, psnr = compute_psnr_mse(orig, compressed)
43
+ metrics = compute_metrics(orig, k)
44
+
45
+ report = (
46
+ f"COMPRESSION REPORT\n"
47
+ f"{'-' * 40}\n"
48
+ f"PSNR : {psnr:.2f} dB\n"
49
+ f"MSE : {mse:.2f}\n"
50
+ f"Compression Ratio : {metrics['ratio']:.2f}x\n"
51
+ f"Original Size (KB) : {metrics['original_kb']:.2f}\n"
52
+ f"Compressed Size (KB): {metrics['compressed_kb']:.2f}\n"
53
+ f"Space Saved (%) : {metrics['saved_percent']:.1f}"
54
+ )
55
+ return compressed, report
56
+
57
+ iface = gr.Interface(
58
+ fn=compress_and_report,
59
+ inputs=[
60
+ gr.Image(type="pil", label="Upload Image"),
61
+ gr.Slider(minimum=2, maximum=64, step=2, value=16, label="Number of Colors (k)"),
62
+ ],
63
+ outputs=[
64
+ gr.Image(type="numpy", label="Compressed Image"),
65
+ gr.Textbox(label="Metrics Report", lines=10),
66
+ ],
67
+ title="Image Compression using K-Means",
68
+ description="Upload an image and adjust the colour palette size to see lossy compression in action.",
69
+ )
70
+
71
+ if __name__ == "__main__":
72
+ iface.launch()
requirements.txt ADDED
@@ -0,0 +1,4 @@
 
 
 
 
 
1
+ gradio
2
+ scikit-learn
3
+ numpy
4
+ Pillow