|
|
import os |
|
|
|
|
|
os.environ['HF_HOME'] = '/tmp/huggingface' |
|
|
os.environ['TRANSFORMERS_CACHE'] = '/tmp/huggingface/transformers' |
|
|
os.environ['TORCH_HOME'] = '/tmp/torch' |
|
|
|
|
|
import gradio as gr |
|
|
import tempfile |
|
|
from pathlib import Path |
|
|
from wrapper import run_pipeline_on_image |
|
|
from PIL import Image |
|
|
|
|
|
|
|
|
BASE_DIR = Path(__file__).resolve().parent |
|
|
|
|
|
|
|
|
PRESET_IMAGES = { |
|
|
"Sorghum": str(BASE_DIR / "Sorghum.tif"), |
|
|
"Corn": str(BASE_DIR / "Corn.tif"), |
|
|
"Cotton": str(BASE_DIR / "Cotton.tif"), |
|
|
} |
|
|
|
|
|
|
|
|
LOGO_PATH = str(BASE_DIR / "logo.png") |
|
|
|
|
|
|
|
|
def process(file_path, preset_choice): |
|
|
"""Process image and yield results progressively for immediate display.""" |
|
|
|
|
|
single_plant_mode = False |
|
|
if preset_choice: |
|
|
chosen = PRESET_IMAGES.get(preset_choice) |
|
|
if chosen: |
|
|
file_path = chosen |
|
|
|
|
|
single_plant_mode = (preset_choice == "Corn") |
|
|
|
|
|
if not file_path: |
|
|
|
|
|
return None, None, None, 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: |
|
|
|
|
|
img_bytes = src.read_bytes() |
|
|
img_path.write_bytes(img_bytes) |
|
|
except Exception: |
|
|
|
|
|
Image.open(src).save(img_path) |
|
|
|
|
|
|
|
|
input_preview = None |
|
|
|
|
|
|
|
|
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 |
|
|
|
|
|
|
|
|
for outputs in run_pipeline_on_image(str(img_path), tmpdir, save_artifacts=True, single_plant_mode=single_plant_mode): |
|
|
|
|
|
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')) or input_preview |
|
|
size_img = load_pil(str(Path(tmpdir) / 'results/size.size_analysis.png')) |
|
|
|
|
|
|
|
|
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 |
|
|
|
|
|
|
|
|
order = ['NDVI', 'GNDVI', 'SAVI'] |
|
|
gallery_items = [load_pil(outputs[k]) for k in order if k in outputs] |
|
|
|
|
|
stats_text = outputs.get('StatsText', '') |
|
|
|
|
|
|
|
|
yield ( |
|
|
input_img, |
|
|
composite, |
|
|
mask, |
|
|
overlay, |
|
|
texture_img, |
|
|
hog_img, |
|
|
lac1_img, |
|
|
gallery_items, |
|
|
size_img, |
|
|
stats_text, |
|
|
) |
|
|
|
|
|
|
|
|
with gr.Blocks(fill_width=True) as demo: |
|
|
|
|
|
gr.Image( |
|
|
value=LOGO_PATH, |
|
|
show_label=False, |
|
|
interactive=False, |
|
|
height=80, |
|
|
container=False, |
|
|
show_download_button=False, |
|
|
show_share_button=False, |
|
|
show_fullscreen_button=False, |
|
|
) |
|
|
gr.Markdown("# 🌿 Automated Plant Analysis Demo") |
|
|
gr.Markdown("Upload a plant image (TIFF preferred) to compute and visualize composite, mask, overlay, texture, vegetation indices, and statistics.") |
|
|
|
|
|
with gr.Row(): |
|
|
with gr.Column(): |
|
|
|
|
|
inp = gr.File( |
|
|
type="filepath", |
|
|
file_types=[".tif", ".tiff", ".png", ".jpg"], |
|
|
label="Upload Image" |
|
|
) |
|
|
preset = gr.Radio( |
|
|
choices=list(PRESET_IMAGES.keys()), |
|
|
label="Or choose a preset image", |
|
|
value=None |
|
|
) |
|
|
run = gr.Button("Run Pipeline", variant="primary") |
|
|
|
|
|
|
|
|
with gr.Row(): |
|
|
input_img = gr.Image(type="pil", label="Input Image", interactive=False, height=380) |
|
|
|
|
|
|
|
|
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) |
|
|
|
|
|
|
|
|
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) |
|
|
|
|
|
|
|
|
gallery = gr.Gallery(label="Vegetation Indices", columns=3, height="auto") |
|
|
|
|
|
|
|
|
with gr.Row(): |
|
|
size_img = gr.Image(type="pil", label="Plant Morphology", interactive=False) |
|
|
|
|
|
|
|
|
stats = gr.Textbox(label="Statistics", lines=4) |
|
|
|
|
|
run.click( |
|
|
process, |
|
|
inputs=[inp, preset], |
|
|
outputs=[ |
|
|
input_img, |
|
|
composite_img, |
|
|
mask_img, |
|
|
overlay_img, |
|
|
texture_img, |
|
|
hog_img, |
|
|
lac1_img, |
|
|
gallery, |
|
|
size_img, |
|
|
stats, |
|
|
] |
|
|
) |
|
|
|
|
|
if __name__ == "__main__": |
|
|
demo.launch() |
|
|
|