ahmedxeno commited on
Commit
d66076c
·
verified ·
1 Parent(s): db07735

Create app.py

Browse files
Files changed (1) hide show
  1. app.py +122 -0
app.py ADDED
@@ -0,0 +1,122 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import cv2
2
+ import numpy as np
3
+ import matplotlib.pyplot as plt
4
+ import pywt
5
+ from skimage import exposure
6
+ import gradio as gr
7
+ from io import BytesIO
8
+ from PIL import Image
9
+
10
+ def musica_enhancement(image):
11
+ """
12
+ Enhances a 16-bit TIFF image using wavelet decomposition, CLAHE, gamma correction,
13
+ and edge-preserving sharpening.
14
+
15
+ Args:
16
+ image (PIL.Image): Uploaded image.
17
+
18
+ Returns:
19
+ enhanced_image (PIL.Image): Enhanced image.
20
+ histogram (PIL.Image): Histogram of the enhanced image.
21
+ """
22
+ # Convert PIL Image to numpy array
23
+ img = np.array(image)
24
+
25
+ # Handle different image modes
26
+ if image.mode == 'I;16':
27
+ # 16-bit image
28
+ img = img.astype(np.uint16)
29
+ img_norm = img.astype(np.float32) / 65535.0
30
+ elif image.mode == 'I':
31
+ # 32-bit integer image
32
+ img = img.astype(np.int32)
33
+ img_norm = img.astype(np.float32) / (2**32 - 1)
34
+ elif image.mode in ['RGB', 'RGBA']:
35
+ # Convert to grayscale if it's a color image
36
+ img = cv2.cvtColor(img, cv2.COLOR_RGB2GRAY)
37
+ img_norm = img.astype(np.float32) / 255.0
38
+ elif image.mode == 'L':
39
+ # 8-bit grayscale
40
+ img_norm = img.astype(np.float32) / 255.0
41
+ else:
42
+ raise ValueError(f"Unsupported image mode: {image.mode}")
43
+
44
+ # 1. Multi-Scale Decomposition (3-level wavelet transform)
45
+ coeffs = pywt.wavedec2(img_norm, 'bior1.3', level=3)
46
+ cA3, (cH3, cV3, cD3), (cH2, cV2, cD2), (cH1, cV1, cD1) = coeffs
47
+
48
+ # 2. Adaptive Processing per Sub-band
49
+ cD1 = pywt.threshold(cD1, 0.05 * np.max(cD1), mode='soft')
50
+ cD2 = pywt.threshold(cD2, 0.07 * np.max(cD2), mode='soft')
51
+ cH1 = cH1 * 1.2
52
+ cV1 = cV1 * 1.2
53
+
54
+ # 3. Reconstruct Enhanced Image with clipping
55
+ coeffs_enhanced = [cA3, (cH3, cV3, cD3), (cH2, cV2, cD2), (cH1, cV1, cD1)]
56
+ img_recon = pywt.waverec2(coeffs_enhanced, 'bior1.3')
57
+ img_recon = np.clip(img_recon, 0, 1) # Critical fix
58
+
59
+ # 4. Adaptive CLAHE
60
+ entropy = -np.sum(img_recon * np.log2(img_recon + 1e-7)) # Now safe
61
+ clip_limit = 0.02 if entropy > 7 else 0.05
62
+ img_clahe = exposure.equalize_adapthist(img_recon, clip_limit=clip_limit, kernel_size=64)
63
+
64
+ # 5. Gamma correction
65
+ p5, p95 = np.percentile(img_clahe, (5, 95))
66
+ gamma = 0.7 if (p95 - p5) < 0.3 else 0.9
67
+ img_gamma = exposure.adjust_gamma(img_clahe, gamma=gamma)
68
+
69
+ # 6. Edge-Preserving Sharpening (convert to BGR first)
70
+ img_gamma_8bit = (img_gamma * 255).astype(np.uint8)
71
+ img_bgr = cv2.cvtColor(img_gamma_8bit, cv2.COLOR_GRAY2BGR) # Convert to 3-channel
72
+ img_sharp = cv2.detailEnhance(img_bgr, sigma_s=12, sigma_r=0.15)
73
+ img_sharp = cv2.cvtColor(img_sharp, cv2.COLOR_BGR2GRAY) # Convert back to grayscale
74
+
75
+ # Convert enhanced image to PIL Image
76
+ enhanced_image = Image.fromarray(img_sharp)
77
+
78
+ # Create histogram plot
79
+ plt.figure(figsize=(6, 4))
80
+ plt.hist(img_sharp.ravel(), bins=256, range=(0, 255), color='gray')
81
+ plt.title('Enhanced Histogram')
82
+ plt.xlabel('Pixel Intensity')
83
+ plt.ylabel('Frequency')
84
+ plt.tight_layout()
85
+ buf = BytesIO()
86
+ plt.savefig(buf, format='png')
87
+ plt.close()
88
+ buf.seek(0)
89
+ histogram = Image.open(buf)
90
+
91
+ return enhanced_image, histogram
92
+
93
+ # Define Gradio interface
94
+ with gr.Blocks() as demo:
95
+ gr.Markdown("# Musica Image Enhancement")
96
+ gr.Markdown(
97
+ """
98
+ Upload a 16-bit TIFF image to enhance it using wavelet decomposition, CLAHE,
99
+ gamma correction, and edge-preserving sharpening.
100
+ """
101
+ )
102
+ with gr.Row():
103
+ with gr.Column():
104
+ input_image = gr.Image(
105
+ type="pil",
106
+ label="Upload 16-bit TIFF Image",
107
+ source="upload",
108
+ tool="editor",
109
+ )
110
+ run_button = gr.Button("Enhance Image")
111
+ with gr.Column():
112
+ output_image = gr.Image(type="pil", label="Enhanced Image")
113
+ output_hist = gr.Image(type="pil", label="Enhanced Histogram")
114
+
115
+ run_button.click(
116
+ fn=musica_enhancement,
117
+ inputs=input_image,
118
+ outputs=[output_image, output_hist],
119
+ )
120
+
121
+ if __name__ == "__main__":
122
+ demo.launch()