Menezes commited on
Commit
743694d
·
verified ·
1 Parent(s): 26a848b

Upload 2 files

Browse files
Files changed (2) hide show
  1. app.py +145 -0
  2. requirements.txt +4 -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 gerar_caminho_temporario(suffix=".tif"):
12
+ return os.path.join(tempfile.gettempdir(), f"{uuid.uuid4().hex}{suffix}")
13
+
14
+ def ler_banda(caminho):
15
+ with rasterio.open(caminho) as src:
16
+ return src.read(1).astype(np.float32), src.profile
17
+
18
+ def reamostrar_para_10m(banda_path, ref_shape, ref_transform):
19
+ with rasterio.open(banda_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 normalizar(arr):
27
+ arr /= 10000.0
28
+ return np.clip(arr, 0, 1)
29
+
30
+ def imagem_para_fig(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 salvar_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 processar_visualizacao(zip_file_path, tipo_vis):
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("Pasta .SAFE não encontrada dentro do zip.")
68
+ extract_dir = os.path.join(temp_dir, dirs[0])
69
+
70
+ granule = os.path.join(extract_dir, "GRANULE")
71
+ granule_path = [os.path.join(granule, d) for d in os.listdir(granule) if d.startswith("L2A_")][0]
72
+ img_data_path = os.path.join(granule_path, "IMG_DATA")
73
+
74
+ res_paths = {
75
+ "R10m": os.path.join(img_data_path, "R10m"),
76
+ "R20m": os.path.join(img_data_path, "R20m")
77
+ }
78
+
79
+ # Referência para geometria
80
+ b4, prof = ler_banda(os.path.join(res_paths["R10m"], [f for f in os.listdir(res_paths["R10m"]) if "_B04" in f][0]))
81
+
82
+ if tipo_vis == "RGB Natural (B4, B3, B2)":
83
+ b2, _ = ler_banda(os.path.join(res_paths["R10m"], [f for f in os.listdir(res_paths["R10m"]) if "_B02" in f][0]))
84
+ b3, _ = ler_banda(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_fig = imagem_para_fig(normalizar(rgb), tipo_vis)
87
+ tif_path = gerar_caminho_temporario(".tif")
88
+ salvar_tif(tif_path, rgb, prof, count=3)
89
+ return rgb_fig, tif_path
90
+
91
+ elif tipo_vis == "Falsa Cor Vegetação (B8, B4, B3)":
92
+ b3, _ = ler_banda(os.path.join(res_paths["R10m"], [f for f in os.listdir(res_paths["R10m"]) if "_B03" in f][0]))
93
+ b8, _ = ler_banda(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_fig = imagem_para_fig(normalizar(fcv), tipo_vis)
96
+ tif_path = gerar_caminho_temporario(".tif")
97
+ salvar_tif(tif_path, fcv, prof, count=3)
98
+ return fcv_fig, tif_path
99
+
100
+ elif tipo_vis == "Falso Colorido SWIR (B12, B8, B4)":
101
+ b8, _ = ler_banda(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 = reamostrar_para_10m(b12_path, b4.shape, prof["transform"])
104
+ fcswir = np.stack([b12, b8, b4], axis=-1)
105
+ fcswir_fig = imagem_para_fig(normalizar(fcswir), tipo_vis)
106
+ tif_path = gerar_caminho_temporario(".tif")
107
+ salvar_tif(tif_path, fcswir, prof, count=3)
108
+ return fcswir_fig, tif_path
109
+
110
+ elif tipo_vis == "NDVI":
111
+ b8, _ = ler_banda(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_fig = imagem_para_fig(ndvi, "NDVI", cmap='RdYlGn')
114
+ tif_path = gerar_caminho_temporario(".tif")
115
+ salvar_tif(tif_path, ndvi, prof, count=1)
116
+ return ndvi_fig, tif_path
117
+
118
+ else:
119
+ raise ValueError("Tipo de visualização inválido.")
120
+
121
+ # === Interface Gradio ===
122
+ demo = gr.Interface(
123
+ fn=processar_visualizacao,
124
+ inputs=[
125
+ gr.File(label="Arquivo Sentinel-2 (.zip)", type="filepath"),
126
+ gr.Dropdown(
127
+ choices=[
128
+ "RGB Natural (B4, B3, B2)",
129
+ "Falsa Cor Vegetação (B8, B4, B3)",
130
+ "Falso Colorido SWIR (B12, B8, B4)",
131
+ "NDVI"
132
+ ],
133
+ label="Tipo de visualização"
134
+ )
135
+ ],
136
+ outputs=[
137
+ gr.Plot(label="Visualização"),
138
+ gr.File(label="Download do GeoTIFF")
139
+ ],
140
+ title="Sentinel-2: Visualizar + Exportar GeoTIFF",
141
+ description="Escolha uma visualização, envie um arquivo .SAFE.zip e baixe o GeoTIFF correspondente."
142
+ )
143
+
144
+ if __name__ == "__main__":
145
+ demo.launch()
requirements.txt ADDED
@@ -0,0 +1,4 @@
 
 
 
 
 
1
+ gradio>=4.0
2
+ rasterio>=1.3
3
+ numpy>=1.21
4
+ matplotlib>=3.5