File size: 3,919 Bytes
3834351
4768cde
dd1d7f5
a32df56
4c1c4a7
 
 
3834351
49abd9f
7c80781
 
 
 
 
3c8af25
 
 
7c80781
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
3c8af25
 
 
49abd9f
4768cde
3834351
e768711
4768cde
49abd9f
 
 
4768cde
 
e768711
 
3c8af25
 
 
 
 
 
 
 
 
 
 
 
 
 
 
5f6c42c
e768711
3c8af25
e768711
5f6c42c
3834351
9226311
d807150
e768711
 
d807150
 
 
 
 
 
e768711
 
5f6c42c
3c8af25
 
e768711
 
 
 
d807150
49abd9f
5f6c42c
3834351
 
dd1d7f5
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
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
import gradio as gr
import tempfile
from pathlib import Path
from wrapper import run_pipeline_on_image
import numpy as np
from PIL import Image
from itertools import product

def show_preview(image):
    """Render uploaded image faithfully, including 16-bit/single-channel inputs.

    - RGB/RGBA: show as-is (strip alpha)
    - 16-bit or single-channel: min-max (or 1-99%ile) normalize to 8-bit for display
    """
    if image is None:
        return None
    try:
        arr = np.array(image)
        # RGBA → RGB
        if arr.ndim == 3 and arr.shape[2] == 4:
            return image.convert("RGB")
        # RGB → as-is
        if arr.ndim == 3 and arr.shape[2] == 3:
            return image
        # Single-channel or higher bit-depth
        if arr.ndim == 2 or (arr.ndim == 3 and arr.shape[2] == 1):
            if arr.ndim == 3:
                arr = arr[..., 0]
            a = np.nan_to_num(arr.astype(np.float64), nan=0.0, posinf=0.0, neginf=0.0)
            # Robust contrast stretch
            vmin = np.percentile(a, 1.0)
            vmax = np.percentile(a, 99.0)
            if not np.isfinite(vmin) or not np.isfinite(vmax) or vmax <= vmin:
                vmin, vmax = float(np.min(a)), float(np.max(a))
            denom = max(vmax - vmin, 1e-6)
            vis = np.clip((a - vmin) / denom, 0.0, 1.0) * 255.0
            vis8 = vis.astype(np.uint8)
            return Image.fromarray(vis8, mode='L')
        # Fallback
        return image.convert("RGB")
    except Exception:
        return image

def process(image):
    if image is None:
        return None, None, [], ""
    with tempfile.TemporaryDirectory() as tmpdir:
        # Save PIL image preserving original format
        ext = image.format.lower() if image.format else 'png'
        img_path = Path(tmpdir) / f"input.{ext}"
        image.save(img_path)
        outputs = run_pipeline_on_image(str(img_path), tmpdir, save_artifacts=True)

        # Assemble displays
        def load_pil(path_str):
            try:
                if not path_str:
                    return None
                im = Image.open(path_str)
                im = im.convert('RGB')
                # Copy to memory so it survives after tmpdir is removed
                copied = im.copy()
                im.close()
                return copied
            except Exception:
                return None

        overlay = load_pil(outputs.get('Overlay'))
        mask = load_pil(outputs.get('Mask'))
        composite = load_pil(outputs.get('Composite'))
        order = ['NDVI', 'ARI', 'GNDVI']
        gallery_items = [load_pil(outputs[k]) for k in order if k in outputs]
        stats_text = outputs.get('StatsText', '')
        return composite, overlay, mask, gallery_items, stats_text

with gr.Blocks() as demo:
    gr.Markdown("# 🌿 Sorghum Plant Analysis Demo")
    gr.Markdown("Upload a sorghum plant image to analyze vegetation indices, segmentation overlay, and stats.")

    with gr.Row():
        with gr.Column():
            inp = gr.Image(type="pil", label="Upload Image")
            run = gr.Button("Run Pipeline", variant="primary")
        with gr.Column():
            preview = gr.Image(type="pil", label="Uploaded Image Preview", interactive=False)

    with gr.Row():
        composite_img = gr.Image(type="pil", label="Composite (Segmentation Input)", interactive=False)
        overlay_img = gr.Image(type="pil", label="Segmentation Overlay", interactive=False)
        mask_img = gr.Image(type="pil", label="Mask", interactive=False)

    gallery = gr.Gallery(label="Vegetation Indices", columns=3, height="auto")
    stats = gr.Textbox(label="Statistics", lines=4)

    # Update preview when image is uploaded
    inp.change(fn=show_preview, inputs=inp, outputs=preview)
    run.click(process, inputs=inp, outputs=[composite_img, overlay_img, mask_img, gallery, stats])

if __name__ == "__main__":
    demo.launch()