mouadenna commited on
Commit
eb12373
·
verified ·
1 Parent(s): 5d91a16

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +58 -39
app.py CHANGED
@@ -1,6 +1,6 @@
1
  import streamlit as st
2
- import torch
3
- import numpy as np
4
  from PIL import Image
5
  import rasterio
6
  from rasterio.windows import Window
@@ -11,11 +11,11 @@ import os
11
  import albumentations as albu
12
  import segmentation_models_pytorch as smp
13
  from albumentations.pytorch.transforms import ToTensorV2
14
- import geopandas as gpd
15
  from shapely.geometry import shape
16
  from shapely.ops import unary_union
17
  from rasterio.features import shapes
18
-
 
19
 
20
  DEVICE = torch.device("cuda" if torch.cuda.is_available() else "cpu")
21
  ENCODER = 'se_resnext50_32x4d'
@@ -25,7 +25,7 @@ ENCODER_WEIGHTS = 'imagenet'
25
  # Load and prepare the model
26
  @st.cache_resource
27
  def load_model():
28
- model = torch.load('deeplabv3 v15.pth', map_location=DEVICE)
29
  model.eval().float()
30
  return model
31
 
@@ -76,7 +76,7 @@ def process_and_predict(image, model):
76
  return mask_image
77
 
78
 
79
- def extract_tiles(map_file, model, tile_size=512, overlap=0, batch_size=4,threshold=0.6):
80
  tiles = []
81
 
82
  with rasterio.open(map_file) as src:
@@ -113,8 +113,8 @@ def extract_tiles(map_file, model, tile_size=512, overlap=0, batch_size=4,thresh
113
  "width": tile_size,
114
  "transform": rasterio.windows.transform(window, src.transform)
115
  })
116
- tile_image = np.array(tile_image)
117
 
 
118
  preprocessed_tile = preprocess(image=tile_image)['image']
119
  batch_images.append(preprocessed_tile)
120
  batch_metas.append(out_meta)
@@ -124,7 +124,7 @@ def extract_tiles(map_file, model, tile_size=512, overlap=0, batch_size=4,thresh
124
 
125
  batch_tensor = torch.cat([img.unsqueeze(0).to(DEVICE) for img in batch_images], dim=0)
126
  with torch.no_grad():
127
- batch_masks = model(batch_tensor.to(DEVICE))
128
 
129
  batch_masks = torch.sigmoid(batch_masks)
130
  batch_masks = (batch_masks > threshold).float()
@@ -142,58 +142,76 @@ def extract_tiles(map_file, model, tile_size=512, overlap=0, batch_size=4,thresh
142
  return tiles
143
 
144
 
145
-
146
-
147
-
148
-
149
  def create_vector_mask(tiles, output_path):
150
  all_polygons = []
151
  for mask_array, meta in tiles:
152
- # Ensure mask is binary
153
  mask_array = (mask_array > 0).astype(np.uint8)
154
 
155
- # Get shapes from the mask
156
  mask_shapes = list(shapes(mask_array, mask=mask_array, transform=meta['transform']))
157
 
158
- # Convert shapes to Shapely polygons
159
  polygons = [shape(geom) for geom, value in mask_shapes if value == 1]
160
 
161
  all_polygons.extend(polygons)
162
- # Perform union of all polygons
163
  union_polygon = unary_union(all_polygons)
164
- # Create a GeoDataFrame
165
  gdf = gpd.GeoDataFrame({'geometry': [union_polygon]}, crs=meta['crs'])
166
  # Save to file
167
  gdf.to_file(output_path)
168
 
169
- # Calculate area in square meters
170
  area_m2 = gdf.to_crs(epsg=3857).area.sum()
171
- # Convert to hectares
172
 
173
  return gdf, area_m2
174
 
175
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
176
  def main():
177
- st.title("PV segmentor")
178
 
179
  uploaded_file = st.file_uploader("Choose a TIF file", type="tif")
180
 
181
  if uploaded_file is not None:
182
  st.write("File uploaded successfully!")
183
 
184
- threshold= st.slider(
185
- 'Select the value of the threshold',
186
- min_value=0.1,
187
- max_value=0.9,
188
- value=0.5,
189
- step=0.05
190
  )
191
- overlap= st.slider(
192
- 'Select the value of overlap',
193
- min_value=50,
194
- max_value=150,
195
- value=100,
196
- step=25
197
  )
198
  st.write('Selected threshold value:', threshold)
199
  st.write('Selected overlap value:', overlap)
@@ -205,7 +223,7 @@ def main():
205
  f.write(uploaded_file.getbuffer())
206
 
207
  best_model.float()
208
- tiles = extract_tiles("temp.tif", best_model, tile_size=512, overlap=overlap, batch_size=4,threshold=threshold)
209
 
210
  st.write("Processing complete!")
211
 
@@ -213,7 +231,7 @@ def main():
213
  result_gdf, area_m2 = create_vector_mask(tiles, output_path)
214
 
215
  st.write("Vector mask created successfully!")
216
- st.write(f"Total area occupied by polygons: {area_m2:.4f} m^2")
217
 
218
  # Offer the shapefile for download
219
  shp_files = [f for f in os.listdir() if
@@ -232,11 +250,12 @@ def main():
232
  mime="application/zip"
233
  )
234
 
235
- # Clean up temporary files
236
- os.remove("temp.tif")
237
- for file in shp_files:
238
- os.remove(file)
 
239
 
240
 
241
  if __name__ == "__main__":
242
- main()
 
1
  import streamlit as st
2
+ import geopandas as gpd
3
+ import leafmap.foliumap as leafmap
4
  from PIL import Image
5
  import rasterio
6
  from rasterio.windows import Window
 
11
  import albumentations as albu
12
  import segmentation_models_pytorch as smp
13
  from albumentations.pytorch.transforms import ToTensorV2
 
14
  from shapely.geometry import shape
15
  from shapely.ops import unary_union
16
  from rasterio.features import shapes
17
+ import torch
18
+ import numpy as np
19
 
20
  DEVICE = torch.device("cuda" if torch.cuda.is_available() else "cpu")
21
  ENCODER = 'se_resnext50_32x4d'
 
25
  # Load and prepare the model
26
  @st.cache_resource
27
  def load_model():
28
+ model = torch.load('deeplabv3+ v15.pth', map_location=DEVICE)
29
  model.eval().float()
30
  return model
31
 
 
76
  return mask_image
77
 
78
 
79
+ def extract_tiles(map_file, model, tile_size=512, overlap=0, batch_size=4, threshold=0.6):
80
  tiles = []
81
 
82
  with rasterio.open(map_file) as src:
 
113
  "width": tile_size,
114
  "transform": rasterio.windows.transform(window, src.transform)
115
  })
 
116
 
117
+ tile_image = np.array(tile_image)
118
  preprocessed_tile = preprocess(image=tile_image)['image']
119
  batch_images.append(preprocessed_tile)
120
  batch_metas.append(out_meta)
 
124
 
125
  batch_tensor = torch.cat([img.unsqueeze(0).to(DEVICE) for img in batch_images], dim=0)
126
  with torch.no_grad():
127
+ batch_masks = model(batch_tensor)
128
 
129
  batch_masks = torch.sigmoid(batch_masks)
130
  batch_masks = (batch_masks > threshold).float()
 
142
  return tiles
143
 
144
 
 
 
 
 
145
  def create_vector_mask(tiles, output_path):
146
  all_polygons = []
147
  for mask_array, meta in tiles:
148
+
149
  mask_array = (mask_array > 0).astype(np.uint8)
150
 
 
151
  mask_shapes = list(shapes(mask_array, mask=mask_array, transform=meta['transform']))
152
 
153
+ # to shapely polygons
154
  polygons = [shape(geom) for geom, value in mask_shapes if value == 1]
155
 
156
  all_polygons.extend(polygons)
157
+ #union of all polygons
158
  union_polygon = unary_union(all_polygons)
159
+ # create gdf
160
  gdf = gpd.GeoDataFrame({'geometry': [union_polygon]}, crs=meta['crs'])
161
  # Save to file
162
  gdf.to_file(output_path)
163
 
164
+ #area in square meters
165
  area_m2 = gdf.to_crs(epsg=3857).area.sum()
 
166
 
167
  return gdf, area_m2
168
 
169
 
170
+ def display_map(shapefile_path, tif_path):
171
+ st.title("Map with Shape and TIFF Overlay")
172
+
173
+ mask = gpd.read_file(shapefile_path)
174
+
175
+ if mask.crs is None or mask.crs.to_string() != 'EPSG:3857':
176
+ mask = mask.to_crs('EPSG:3857')
177
+
178
+ bounds = mask.total_bounds # [minx, miny, maxx, maxy]
179
+ center = [(bounds[1] + bounds[3]) / 2, (bounds[0] + bounds[2]) / 2]
180
+
181
+ m = leafmap.Map(
182
+ center=[center[1], center[0]], # leafmap uses [latitude, longitude]
183
+ zoom=10,
184
+ crs='EPSG3857'
185
+ )
186
+
187
+ m.add_gdf(mask, layer_name="Shapefile Mask")
188
+
189
+ m.add_raster(tif_path, layer_name="Satellite Image", rgb=True, opacity=0.9)
190
+
191
+ m.to_streamlit()
192
+
193
+
194
  def main():
195
+ st.title("PV Segmentor")
196
 
197
  uploaded_file = st.file_uploader("Choose a TIF file", type="tif")
198
 
199
  if uploaded_file is not None:
200
  st.write("File uploaded successfully!")
201
 
202
+ threshold = st.slider(
203
+ 'Select the value of the threshold',
204
+ min_value=0.1,
205
+ max_value=0.9,
206
+ value=0.6,
207
+ step=0.05
208
  )
209
+ overlap = st.slider(
210
+ 'Select the value of overlap',
211
+ min_value=50,
212
+ max_value=150,
213
+ value=100,
214
+ step=25
215
  )
216
  st.write('Selected threshold value:', threshold)
217
  st.write('Selected overlap value:', overlap)
 
223
  f.write(uploaded_file.getbuffer())
224
 
225
  best_model.float()
226
+ tiles = extract_tiles("temp.tif", best_model, tile_size=512, overlap=overlap, batch_size=4, threshold=threshold)
227
 
228
  st.write("Processing complete!")
229
 
 
231
  result_gdf, area_m2 = create_vector_mask(tiles, output_path)
232
 
233
  st.write("Vector mask created successfully!")
234
+ st.write(f"Total area occupied by PV panels: {area_m2:.4f} m^2")
235
 
236
  # Offer the shapefile for download
237
  shp_files = [f for f in os.listdir() if
 
250
  mime="application/zip"
251
  )
252
 
253
+ display_map("output_mask.shp", "temp.tif")
254
+
255
+ #os.remove("temp.tif")
256
+ #for file in shp_files:
257
+ # os.remove(file)
258
 
259
 
260
  if __name__ == "__main__":
261
+ main()