File size: 2,506 Bytes
4ae08c7
 
f850371
ac2c4c0
 
f850371
0e7f8ec
f850371
ac2c4c0
f850371
 
 
 
 
ac2c4c0
 
f850371
ac2c4c0
f850371
 
 
 
 
 
 
ac2c4c0
f850371
 
 
ac2c4c0
f850371
 
 
4ae08c7
f850371
 
 
4ae08c7
f850371
 
ac2c4c0
f850371
4ae08c7
f850371
 
 
 
4ae08c7
f850371
 
0e7f8ec
f850371
 
 
 
 
 
4ae08c7
f850371
 
 
 
 
 
 
 
 
 
 
 
 
 
 
4ae08c7
f850371
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
import cv2
import numpy as np
import matplotlib.pyplot as plt
import pywt
from skimage import exposure
import gradio as gr
from PIL import Image
from io import BytesIO

def process_tiff(file):
    # Load 16-bit TIFF
    img = cv2.imread(file.name, cv2.IMREAD_ANYDEPTH | cv2.IMREAD_GRAYSCALE)
    if img is None:
        raise gr.Error("Could not read TIFF file. Ensure it's 16-bit grayscale.")
    
    # Normalize to [0, 1]
    img_norm = img.astype(np.float32) / 65535.0

    # Wavelet decomposition
    try:
        coeffs = pywt.wavedec2(img_norm, 'bior1.3', level=3)
    except ValueError as e:
        raise gr.Error(f"Image dimensions must be divisible by 8. {str(e)}")
    
    # Processing coefficients (same as original)
    cA3, (cH3, cV3, cD3), (cH2, cV2, cD2), (cH1, cV1, cD1) = coeffs
    cD1 = pywt.threshold(cD1, 0.05*np.max(cD1), 'soft')
    cD2 = pywt.threshold(cD2, 0.07*np.max(cD2), 'soft')
    cH1 *= 1.2; cV1 *= 1.2

    # Reconstruction
    recon = pywt.waverec2([cA3, (cH3, cV3, cD3), (cH2, cV2, cD2), (cH1, cV1, cD1)], 'bior1.3')
    recon = np.clip(recon, 0, 1)

    # CLAHE
    entropy = -np.sum(recon * np.log2(recon + 1e-7))
    clahe_img = exposure.equalize_adapthist(recon, clip_limit=0.02 if entropy >7 else 0.05, kernel_size=64)

    # Gamma correction
    p5, p95 = np.percentile(clahe_img, (5, 95))
    gamma = 0.7 if (p95 - p5) < 0.3 else 0.9
    gamma_img = exposure.adjust_gamma(clahe_img, gamma)

    # Sharpening
    sharp = cv2.detailEnhance(cv2.cvtColor((gamma_img*255).astype(np.uint8), cv2.COLOR_GRAY2BGR), 
                            sigma_s=12, sigma_r=0.15)
    sharp = cv2.cvtColor(sharp, cv2.COLOR_BGR2GRAY)

    # Prepare outputs
    original_display = (np.clip(img/np.percentile(img, 99.5), 0, 1)*255).astype(np.uint8)
    
    buf = BytesIO()
    plt.hist(sharp.ravel(), bins=256, range=(0, 255))
    plt.title("Enhanced Histogram")
    plt.savefig(buf, format='png', bbox_inches='tight')
    plt.close()
    hist_img = Image.open(buf)

    return original_display, sharp, hist_img

# Create Gradio interface
interface = gr.Interface(
    fn=process_tiff,
    inputs=gr.File(label="Upload TIFF", file_types=[".tif", ".tiff"]),
    outputs=[
        gr.Image(label="Original (Clipped)"),
        gr.Image(label="Enhanced Image"),
        gr.Image(label="Histogram")
    ],
    title="MUSICA Image Enhancement",
    description="Upload 16-bit grayscale TIFF for enhancement using wavelet-based processing",
    allow_flagging="never"
)

interface.launch()