File size: 7,021 Bytes
9b6d1e9
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
27bfb83
 
 
 
 
 
 
 
 
9b6d1e9
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
43bbeaa
 
9b6d1e9
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
99f4b1d
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
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
from matplotlib import image
plt.style.use("fivethirtyeight")
import PIL
from PIL import Image, ImageFile
import os, shutil
from tqdm.auto import tqdm, trange
import gradio as gr

import torch, torchvision
import torch.nn as nn
from torchvision.transforms import v2 as v2
import lightning.pytorch as pl
from lightning.pytorch import LightningModule, LightningDataModule
import tempfile

ImageFile.LOAD_TRUNCATED_IMAGES = True

import utils
from utils.utils import prepare_image, make_preds_return_mask, load_model, get_gt


def run_gradio_app():
    def process_image(img_path_):
        lightning_model = load_model()
        image = prepare_image(path=img_path_)
        mask_array = make_preds_return_mask(img=image, model=lightning_model)  # return numpy
        gt_array = np.array(get_gt(img_path_))

        # Visualization
        gt_pil = Image.fromarray(gt_array).resize((500,500))
        mask_pil = Image.fromarray((mask_array * 255.0).astype(np.uint8)).resize((500,500))

        # Flood ratio
        flood_pixels = np.sum(mask_array > 0.5)
        total_pixels = mask_array.size
        flood_ratio = flood_pixels / total_pixels
        if flood_ratio > 0.05:
            status_text = (
                f"Flood detected in approximately {flood_ratio*100:.2f}% of the area.\n\n"
                "πŸ“Œ Recommended Actions for Urban Planners:\n"
                "- Prioritize evacuation and relief efforts in the most affected zones.\n"
                "- Assess drainage and waterway capacity; reinforce weak infrastructure.\n"
                "- Deploy flood barriers or temporary defenses where feasible.\n"
                "- Coordinate with emergency services for rapid response.\n"
                "- Use these flood maps for long-term planning: zoning, flood-resilient housing, "
                "and sustainable water management strategies."
            )
        else:
            status_text = (
                "⚠️ No significant flooding detected.\n\n"
                "πŸ“Œ Recommendations:\n"
                "- Continue monitoring the area, as conditions may change with rainfall.\n"
                "- Maintain drainage systems to prevent localized flooding.\n"
                "- Use this opportunity to strengthen flood preparedness measures "
                "and update urban planning models with the latest satellite data."
            )

        # Save mask to temp file for download
        temp_file = tempfile.NamedTemporaryFile(delete=False, suffix=".png")
        mask_pil.save(temp_file.name)

        return gt_pil, mask_pil, status_text, temp_file.name

    title = "🌊 Flood Detection & Mapping (Sentinel-1 & Sentinel-2)"
    
    description = """
    ## 🌍 Automated Flood Mapping & Evaluation Platform  

    This platform leverages **Sentinel-2 satellite imagery** combined with a trained **UNet deep learning model** 
    to deliver high-resolution flood detection and mapping. The system is designed to support **urban planners, 
    emergency response teams, and environmental agencies** in making timely, data-driven decisions.  

    ### πŸ“Š What the System Provides
    - **Automated Processing** of raw satellite imagery to generate accurate flood masks.  
    - **Visual Insights** with side-by-side comparisons of **Ground Truth** and **Predicted Flood Masks**.  
    - **Quantitative Summaries** including the percentage of land area inundated.  
    - **Downloadable GIS-Ready Outputs** (flood masks) for integration into planning and analysis tools.  
    - **Scalable Utility** across disaster response, environmental monitoring, climate adaptation, 
    and risk assessment workflows.  

    """
    # ### πŸ› οΈ How to Use
    # 1. Upload a **Sentinel-2 TIFF image** (preferably cloud-free).  
    # 2. Let the model process and generate the predicted flood mask.  
    # 3. Review the **visual outputs and textual summary** to assess flood extent.  
    # 4. Download the mask for use in **GIS software** or further analysis.  

    # ⚑ *This tool bridges cutting-edge AI with remote sensing data to empower better decisions 
    # for disaster management and long-term resilience planning.*  
    
    description2 = """
    ### 🌐 Why This Matters
    Flooding remains one of the most destructive natural disasters worldwide. Rapid, reliable detection 
    is essential for:  
    - Guiding **evacuation planning** and **emergency relief operations**.  
    - Supporting **sustainable urban development** through flood-resilient zoning.  
    - Enhancing **climate resilience strategies** for vulnerable regions.
    """


    professional_theme = gr.themes.Base(
        primary_hue="blue",
        secondary_hue="slate",
    ).set(
        button_primary_background_fill="linear-gradient(90deg, #0F4C75, #3282B8)",  
        button_primary_background_fill_hover="linear-gradient(90deg, #3282B8, #0F4C75)",
        button_primary_text_color="white",
        button_primary_shadow="0px 2px 6px rgba(0,0,0,0.15)",
        block_title_text_color="#0F3057",
        body_background_fill="#F8FAFC",     # light gray background
        block_background_fill="#FFFFFF",    # white for content cards
        block_shadow="0px 2px 6px rgba(0,0,0,0.1)",
        border_color_primary="#D1D5DB",
    )

    # ----------------------------
    # Gradio App Layout
    # ----------------------------
    with gr.Blocks(theme=professional_theme) as demo:
        
        # ---- HEADER BAR ----
        with gr.Row():
            with gr.Column(scale = 1):
                gr.Markdown(
                    f"<h1 style='color:#0F3057; margin-bottom:0'>Flood Detection & Mapping Platform</h1>"
                    "<p style='font-size:18px; color:#555;'>Powered by Sentinel-2 Imagery & Deep Learning</p>"
                )

        # ---- DESCRIPTION ----
        gr.Markdown(description)

        # ---- INPUT & STATUS ----
        with gr.Row():
            with gr.Column():
                input_img = gr.File(file_types=["image"], label="Upload Sentinel Image")
                run_btn = gr.Button("Run Flood Detection", variant="primary")
            with gr.Column():
                status_box = gr.Textbox(label="Detection Summary", interactive=False)
                gr.Markdown(description2)

        # ---- OUTPUT VISUALS ----
        with gr.Row():
            gt_out = gr.Image(type="pil", label="Ground Truth", width = 500, height = 500)
            pred_out = gr.Image(type="pil", label="Predicted Flood Mask", height = 500, width = 500)

        # ---- DOWNLOAD ----
        with gr.Row():
            download_mask = gr.File(label="Download Predicted Mask")

        # ---- BUTTON ACTION ----
        run_btn.click(
            fn=process_image,
            inputs=[input_img],
            outputs=[gt_out, pred_out, status_box, download_mask]
        )
        # gr.Markdown(description2)

    demo.launch(share=False)


if __name__ == "__main__":
    run_gradio_app()