Menezes commited on
Commit
52eabca
·
verified ·
1 Parent(s): 22ffa10

Upload app.py

Browse files
Files changed (1) hide show
  1. app.py +145 -0
app.py ADDED
@@ -0,0 +1,145 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import os
2
+ import zipfile
3
+ import tempfile
4
+ import uuid
5
+ import rasterio
6
+ import numpy as np
7
+ import matplotlib.pyplot as plt
8
+ import gradio as gr
9
+ from rasterio.enums import Resampling
10
+
11
+ def generate_temp_path(suffix=".tif"):
12
+ return os.path.join(tempfile.gettempdir(), f"{uuid.uuid4().hex}{suffix}")
13
+
14
+ def read_band(path):
15
+ with rasterio.open(path) as src:
16
+ return src.read(1).astype(np.float32), src.profile
17
+
18
+ def resample_to_10m(band_path, ref_shape, ref_transform):
19
+ with rasterio.open(band_path) as src:
20
+ data = src.read(
21
+ out_shape=(1, ref_shape[0], ref_shape[1]),
22
+ resampling=Resampling.bilinear
23
+ )
24
+ return data[0].astype(np.float32)
25
+
26
+ def normalize(array):
27
+ array /= 10000.0
28
+ return np.clip(array, 0, 1)
29
+
30
+ def array_to_plot(img, title, cmap=None):
31
+ fig = plt.figure(figsize=(6, 6))
32
+ if cmap:
33
+ plt.imshow(img, cmap=cmap)
34
+ plt.colorbar()
35
+ else:
36
+ plt.imshow(img)
37
+ plt.title(title)
38
+ plt.axis('off')
39
+ return fig
40
+
41
+ def save_tif(path, array, profile, count=3):
42
+ profile = profile.copy()
43
+ profile.update({
44
+ 'driver': 'GTiff',
45
+ 'count': count,
46
+ 'dtype': rasterio.float32,
47
+ 'compress': 'deflate',
48
+ 'predictor': 2,
49
+ 'tiled': True,
50
+ 'blockxsize': 512,
51
+ 'blockysize': 512
52
+ })
53
+ with rasterio.open(path, 'w', **profile) as dst:
54
+ if count == 1:
55
+ dst.write(array, 1)
56
+ else:
57
+ for i in range(count):
58
+ dst.write(array[:, :, i], i + 1)
59
+
60
+ def process_visualization(zip_file_path, vis_type):
61
+ with tempfile.TemporaryDirectory() as temp_dir:
62
+ with zipfile.ZipFile(zip_file_path, 'r') as zip_ref:
63
+ zip_ref.extractall(temp_dir)
64
+
65
+ dirs = [d for d in os.listdir(temp_dir) if d.endswith(".SAFE")]
66
+ if not dirs:
67
+ raise Exception(".SAFE folder not found inside the zip file.")
68
+ extract_dir = os.path.join(temp_dir, dirs[0])
69
+
70
+ granule_dir = os.path.join(extract_dir, "GRANULE")
71
+ granule_path = [os.path.join(granule_dir, d) for d in os.listdir(granule_dir) if d.startswith("L2A_")][0]
72
+ img_data_dir = os.path.join(granule_path, "IMG_DATA")
73
+
74
+ res_paths = {
75
+ "R10m": os.path.join(img_data_dir, "R10m"),
76
+ "R20m": os.path.join(img_data_dir, "R20m")
77
+ }
78
+
79
+ # Geometry reference
80
+ b4, profile = read_band(os.path.join(res_paths["R10m"], [f for f in os.listdir(res_paths["R10m"]) if "_B04" in f][0]))
81
+
82
+ if vis_type == "Natural Color (B4, B3, B2)":
83
+ b2, _ = read_band(os.path.join(res_paths["R10m"], [f for f in os.listdir(res_paths["R10m"]) if "_B02" in f][0]))
84
+ b3, _ = read_band(os.path.join(res_paths["R10m"], [f for f in os.listdir(res_paths["R10m"]) if "_B03" in f][0]))
85
+ rgb = np.stack([b4, b3, b2], axis=-1)
86
+ rgb_plot = array_to_plot(normalize(rgb), vis_type)
87
+ tif_path = generate_temp_path(".tif")
88
+ save_tif(tif_path, rgb, profile, count=3)
89
+ return rgb_plot, tif_path
90
+
91
+ elif vis_type == "False Color Vegetation (B8, B4, B3)":
92
+ b3, _ = read_band(os.path.join(res_paths["R10m"], [f for f in os.listdir(res_paths["R10m"]) if "_B03" in f][0]))
93
+ b8, _ = read_band(os.path.join(res_paths["R10m"], [f for f in os.listdir(res_paths["R10m"]) if "_B08" in f][0]))
94
+ fcv = np.stack([b8, b4, b3], axis=-1)
95
+ fcv_plot = array_to_plot(normalize(fcv), vis_type)
96
+ tif_path = generate_temp_path(".tif")
97
+ save_tif(tif_path, fcv, profile, count=3)
98
+ return fcv_plot, tif_path
99
+
100
+ elif vis_type == "False Color SWIR (B12, B8, B4)":
101
+ b8, _ = read_band(os.path.join(res_paths["R10m"], [f for f in os.listdir(res_paths["R10m"]) if "_B08" in f][0]))
102
+ b12_path = os.path.join(res_paths["R20m"], [f for f in os.listdir(res_paths["R20m"]) if "_B12" in f][0])
103
+ b12 = resample_to_10m(b12_path, b4.shape, profile["transform"])
104
+ fcswir = np.stack([b12, b8, b4], axis=-1)
105
+ swir_plot = array_to_plot(normalize(fcswir), vis_type)
106
+ tif_path = generate_temp_path(".tif")
107
+ save_tif(tif_path, fcswir, profile, count=3)
108
+ return swir_plot, tif_path
109
+
110
+ elif vis_type == "NDVI":
111
+ b8, _ = read_band(os.path.join(res_paths["R10m"], [f for f in os.listdir(res_paths["R10m"]) if "_B08" in f][0]))
112
+ ndvi = (b8 - b4) / (b8 + b4 + 1e-6)
113
+ ndvi_plot = array_to_plot(ndvi, "NDVI", cmap='RdYlGn')
114
+ tif_path = generate_temp_path(".tif")
115
+ save_tif(tif_path, ndvi, profile, count=1)
116
+ return ndvi_plot, tif_path
117
+
118
+ else:
119
+ raise ValueError("Invalid visualization type.")
120
+
121
+ # === Gradio Interface ===
122
+ demo = gr.Interface(
123
+ fn=process_visualization,
124
+ inputs=[
125
+ gr.File(label="Sentinel-2 Archive (.zip)", type="filepath"),
126
+ gr.Dropdown(
127
+ choices=[
128
+ "Natural Color (B4, B3, B2)",
129
+ "False Color Vegetation (B8, B4, B3)",
130
+ "False Color SWIR (B12, B8, B4)",
131
+ "NDVI"
132
+ ],
133
+ label="Visualization Type"
134
+ )
135
+ ],
136
+ outputs=[
137
+ gr.Plot(label="Preview"),
138
+ gr.File(label="Download GeoTIFF")
139
+ ],
140
+ title="Sentinel-2 Viewer + GeoTIFF Export",
141
+ description="Upload a .SAFE.zip file, choose a visualization type, and download the corresponding GeoTIFF file."
142
+ )
143
+
144
+ if __name__ == "__main__":
145
+ demo.launch()