File size: 7,337 Bytes
3834351 4768cde dd1d7f5 a32df56 4c1c4a7 3834351 ca48751 2a055cf 916b83d 4768cde 916b83d 2716edf 49abd9f 916b83d 2716edf 916b83d 2716edf 7c31b44 916b83d 4768cde e768711 3c8af25 c170961 3c8af25 93d0941 c170961 93d0941 916b83d 93d0941 c170961 93d0941 c170961 93d0941 916b83d c170961 3c8af25 916b83d e768711 916b83d 2a055cf 3834351 ca48751 916b83d 9226311 2716edf 916b83d e768711 d807150 916b83d d807150 e768711 2a055cf e768711 5f6c42c 3c8af25 c170961 2a055cf c170961 93d0941 2a055cf e768711 2a055cf e768711 916b83d 2a055cf 916b83d 3834351 a28653b ca48751 3834351 69b6a19 |
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 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 |
import gradio as gr
import tempfile
from pathlib import Path
from wrapper import run_pipeline_on_image
from PIL import Image
# Precomputed demo outputs inside the repo (placed by you once)
PRECOMPUTED_DIR = (Path(__file__).resolve().parent / "precomputed_demo")
##add the process function
def process(file_path):
if not file_path:
return None, None, None, None, None, [], ""
with tempfile.TemporaryDirectory() as tmpdir:
src = Path(file_path)
ext = src.suffix.lstrip('.') or 'tif'
img_path = Path(tmpdir) / f"input.{ext}"
try:
# Copy raw uploaded bytes
img_bytes = src.read_bytes()
img_path.write_bytes(img_bytes)
except Exception:
# Fallback: save via PIL if direct copy fails
Image.open(src).save(img_path)
# Run the full sorghum pipeline
outputs = run_pipeline_on_image(str(img_path), tmpdir, save_artifacts=True)
def load_pil(path_str):
try:
if not path_str:
return None
im = Image.open(path_str)
copied = im.copy()
im.close()
return copied
except Exception:
return None
composite = load_pil(outputs.get('Composite'))
overlay = load_pil(outputs.get('Overlay'))
mask = load_pil(outputs.get('Mask'))
input_img = load_pil(outputs.get('InputImage'))
size_img = load_pil(str(Path(tmpdir) / 'results/size.size_analysis.png'))
yolo_img = load_pil(str(Path(tmpdir) / 'results/yolo_tips.png'))
# Texture images (green band)
lbp_path = Path(tmpdir) / 'texture_output/lbp_green.png'
hog_path = Path(tmpdir) / 'texture_output/hog_green.png'
lac1_path = Path(tmpdir) / 'texture_output/lac1_green.png'
texture_img = load_pil(str(lbp_path)) if lbp_path.exists() else None
hog_img = load_pil(str(hog_path)) if hog_path.exists() else None
lac1_img = load_pil(str(lac1_path)) if lac1_path.exists() else None
# Vegetation indices
order = ['NDVI', 'GNDVI', 'SAVI']
gallery_items = [load_pil(outputs[k]) for k in order if k in outputs]
stats_text = outputs.get('StatsText', '')
# Output order matches UI components defined below
# Row 1: Input image (slightly larger)
# Row 2: Composite, Mask, Overlay
# Row 3: Texture images (LBP, HOG, Lac1)
# Row 4: Vegetation indices (gallery)
# Row 5: Morphology Size and YOLO Tips
# Final: Stats table
return (
input_img,
composite,
mask,
overlay,
texture_img,
hog_img,
lac1_img,
gallery_items,
size_img,
yolo_img,
stats_text,
)
def _load_pil(path: Path):
try:
if not path or not path.exists():
return None
im = Image.open(path)
out = im.copy()
im.close()
return out
except Exception:
return None
def _first_existing(paths):
for p in paths:
if p and p.exists():
return p
return None
def load_precomputed():
base = PRECOMPUTED_DIR
if not base.exists():
return None, None, None, None, None, None, None, [], None, None, ""
# Common subdirs
results = base / "results"
veg = base / "Vegetation_indices_images"
tex = base / "texture_output"
input_img = _load_pil(_first_existing([
base / "input_image.png",
base / "input_image.tif",
base / "input.png",
]))
composite = _load_pil(_first_existing([
results / "composite.png",
]))
mask = _load_pil(results / "mask.png")
overlay = _load_pil(results / "overlay.png")
texture_img = _load_pil(_first_existing([
tex / "lbp_green.png",
tex / "lbp.png",
]))
hog_img = _load_pil(_first_existing([
tex / "hog_green.png",
tex / "hog.png",
]))
lac1_img = _load_pil(_first_existing([
tex / "lac1_green.png",
tex / "lacunarity.png",
]))
# Vegetation gallery in order
veg_order = ["ndvi.png", "gndvi.png", "savi.png"]
gallery_items = []
for fname in veg_order:
p = veg / fname
img = _load_pil(p)
if img is not None:
gallery_items.append(img)
size_img = _load_pil(results / "size.size_analysis.png")
yolo_img = _load_pil(results / "yolo_tips.png")
stats_txt_path = _first_existing([
base / "stats.txt",
results / "stats.txt",
])
stats_text = ""
if stats_txt_path and stats_txt_path.exists():
try:
stats_text = stats_txt_path.read_text()
except Exception:
stats_text = ""
return (
input_img,
composite,
mask,
overlay,
texture_img,
hog_img,
lac1_img,
gallery_items,
size_img,
yolo_img,
stats_text,
)
with gr.Blocks() as demo:
gr.Markdown("# 🌿 Automated Plant Analysis Demo")
gr.Markdown("Upload a sorghum plant image (TIFF preferred) to compute and visualize composite, mask, overlay, texture (LBP), vegetation indices, and statistics.")
with gr.Row():
with gr.Column():
# Use File input to preserve raw TIFFs
inp = gr.File(
type="filepath",
file_types=[".tif", ".tiff", ".png", ".jpg"],
label="Upload Image"
)
run = gr.Button("Run Pipeline", variant="primary")
# Row 1: input image, slightly larger
with gr.Row():
input_img = gr.Image(type="pil", label="Input Image", interactive=False, height=380)
# Row 2: composite, mask, overlay
with gr.Row():
composite_img = gr.Image(type="pil", label="Composite (Segmentation Input)", interactive=False)
mask_img = gr.Image(type="pil", label="Mask", interactive=False)
overlay_img = gr.Image(type="pil", label="Segmentation Overlay", interactive=False)
# Row 3: textures
with gr.Row():
texture_img = gr.Image(type="pil", label="Texture LBP (Green Band)", interactive=False)
hog_img = gr.Image(type="pil", label="Texture HOG (Green Band)", interactive=False)
lac1_img = gr.Image(type="pil", label="Texture Lac1 (Green Band)", interactive=False)
# Row 4: vegetation indices
gallery = gr.Gallery(label="Vegetation Indices", columns=3, height="auto")
# Row 5: morphology and YOLO tips
with gr.Row():
size_img = gr.Image(type="pil", label="Morphology Size", interactive=False)
yolo_img = gr.Image(type="pil", label="YOLO Tips", interactive=False)
# Final: statistics table
stats = gr.Textbox(label="Statistics", lines=4)
run.click(
process,
inputs=inp,
outputs=[
input_img,
composite_img,
mask_img,
overlay_img,
texture_img,
hog_img,
lac1_img,
gallery,
size_img,
yolo_img,
stats,
]
)
# No preloading: start with empty UI until the user runs the pipeline
if __name__ == "__main__":
demo.launch()
|