""" Gradio frontend — Flood Detection + ZoeDepth depth estimation. Improved UI: dark theme, styled cards, progress steps, metric badges. """ import gradio as gr import numpy as np from PIL import Image import sys, os import base64 from gradio.themes.utils.colors import Color sys.path.insert(0, os.path.dirname(__file__)) from app.model_utils import run_pipeline def get_base64_image(path): try: with open(path, "rb") as img_file: return base64.b64encode(img_file.read()).decode('utf-8') except Exception: return "" logo_base64 = get_base64_image(os.path.join(os.path.dirname(__file__), "clipart1553592.png")) logo_src = f"data:image/png;base64,{logo_base64}" # ── Risk config ──────────────────────────────────────────────────────────────── RISK_CFG = { "Low": {"colour": "#27ae60", "bg": "#eafaf1", "bar": 20}, "Moderate": {"colour": "#f39c12", "bg": "#fef9e7", "bar": 50}, "High": {"colour": "#e67e22", "bg": "#fdf2e9", "bar": 75}, "Critical": {"colour": "#e74c3c", "bg": "#fdedec", "bar": 100}, } CSS = """ @import url('https://fonts.googleapis.com/css2?family=Geist:wght@400;500;600;700;800&display=swap'); /* ── page ── */ body, .gradio-container { font-family: 'Geist', -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif !important; } .light body, .light .gradio-container { background-color: #f4f5f8 !important; } /* ── header band ── */ #header-band { background: var(--block-background-fill); border-radius: 12px; padding: 32px 36px 24px; margin-bottom: 24px; box-shadow: var(--block-shadow); border: 1px solid var(--border-color-primary); } #header-band h1 { color: var(--body-text-color); font-size: 2.2em; margin: 0 0 8px; font-weight: 800; letter-spacing: -0.03em; } #header-band p { color: var(--body-text-color-subdued); margin: 0; font-size: 1.05em; font-weight: 400; } /* ── metric pill row ── */ .metric-pill { display: inline-block; background: var(--background-fill-secondary); border: 1px solid var(--border-color-primary); border-radius: 8px; padding: 6px 16px; margin: 6px 6px 6px 0; font-size: 0.9em; color: var(--body-text-color-subdued); font-weight: 500; } .metric-pill strong { color: var(--body-text-color); font-weight: 700; } /* ── upload + button panel ── */ #left-panel { background: var(--block-background-fill); border-radius: 12px; padding: 20px; border: 1px solid var(--border-color-primary); box-shadow: var(--block-shadow); } /* ── analyse button ── */ #analyse-btn { background: var(--primary-500) !important; color: white !important; border: none !important; border-radius: 8px !important; font-size: 1.1em !important; font-weight: 600 !important; padding: 14px !important; margin-top: 12px !important; box-shadow: 0 4px 14px rgba(0,0,0,0.1) !important; transition: all .2s ease !important; } #analyse-btn:hover { transform: translateY(-2px) !important; box-shadow: 0 8px 25px rgba(0,0,0,0.15) !important; background: var(--primary-600) !important; } /* ── section labels ── */ .section-label { font-size: 0.85em; font-weight: 700; letter-spacing: .1em; text-transform: uppercase; color: var(--body-text-color-subdued); margin: 24px 0 10px; } /* ── image cards ── */ .image-card { background: var(--block-background-fill) !important; border-radius: 12px !important; border: 1px solid var(--border-color-primary) !important; overflow: hidden; box-shadow: var(--block-shadow) !important; } /* ── risk card ── */ #risk-card { border-radius: 12px; overflow: hidden; background: var(--block-background-fill); box-shadow: var(--block-shadow); border: 1px solid var(--border-color-primary); } /* ── how-it-works table ── */ .how-table { width:100%; border-collapse:collapse; font-size:0.95em; } .how-table th { background: var(--background-fill-secondary); color: var(--body-text-color); padding:14px 16px; text-align:left; border-bottom: 2px solid var(--border-color-primary); font-weight: 600; } .how-table td { padding:14px 16px; border-bottom:1px solid var(--border-color-primary); color: var(--body-text-color); } .how-table tr:last-child td { border-bottom: none; } """ # ── helpers ─────────────────────────────────────────────────────────────────── def _score_bar(score: float, colour: str) -> str: """Animated CSS progress bar.""" return f"""
""" def _stat_row(label, value, colour) -> str: return f"""Attention UNet segmentation · Grad-CAM explainability · ZoeDepth metric depth · AI-powered risk scoring
| Step | Component | What it does |
|---|---|---|
| 1 | Preprocessing | Resize to 512×512, convert to RGB, normalise to [0,1] |
| 2 | Attention UNet | Predicts binary flood mask: attention gates suppress irrelevant features |
| 3 | Grad-CAM | Gradient-weighted class activation map at conv2d_130: TURBO colormap with contour |
| 4 | ZoeDepth (Intel/zoedepth-nyu) | Monocular metric depth estimation: outputs depth in metres per pixel |
| 5 | Risk Engine | Combines flood coverage % + avg depth → Low / Moderate / High / Critical |