Alexvatti commited on
Commit
38bdd0c
·
verified ·
1 Parent(s): bc3b274

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +24 -43
app.py CHANGED
@@ -158,31 +158,19 @@ def get_transform_from_tif(tif_path):
158
  crs = src.crs
159
  return transform, crs
160
 
161
- def mask_to_polygons(mask, transform, target_class_id):
162
- """
163
- Convert a single-class mask to polygons with proper geospatial reference.
164
-
165
- Args:
166
- mask (np.ndarray): Predicted mask (H, W) with class indices.
167
- transform (Affine): Georeferencing transform from the input TIF.
168
- target_class_id (int): The class ID to convert into polygons.
169
-
170
- Returns:
171
- gpd.GeoDataFrame: Geodataframe containing polygons for the target class.
172
- """
173
- # Binary mask for the target class
174
- binary_mask = (mask == target_class_id).astype(np.uint8)
175
 
176
- # Extract polygon shapes
177
  results = (
178
- {'properties': {'class': f'class_{target_class_id}'}, 'geometry': geom}
179
- for geom, value in shapes(binary_mask, mask=None, transform=transform)
180
- if value == 1
181
  )
182
 
 
183
  geoms = list(results)
184
-
185
- # Return empty GeoDataFrame if no shapes found
186
  if not geoms:
187
  return gpd.GeoDataFrame(columns=['geometry'], geometry='geometry', crs='EPSG:4326')
188
 
@@ -191,21 +179,23 @@ def mask_to_polygons(mask, transform, target_class_id):
191
  return gdf
192
 
193
 
194
- def calculate_area(mining_gdf, wiup_gdf):
195
- # Ensure both are in same CRS
 
196
  mining_gdf = mining_gdf.to_crs(wiup_gdf.crs)
197
 
198
- # Same = parts of mining polygons
199
- area_gdf = gpd.overlay(mining_gdf, wiup_gdf, how='intersection')
200
 
201
  # Convert to metric CRS (e.g., UTM) to calculate area in m²
202
- metric_crs = 'EPSG:4326' # UTM zone for SE Asia (adjust based on location)
203
- area_gdf = area_gdf.to_crs(metric_crs)
204
-
205
- area_gdf['area_m2'] = area_gdf.geometry.area
206
- total_area = area_gdf['area_m2'].sum()
 
207
 
208
- return total_area, area_gdf
209
 
210
  # Streamlit App Title
211
  st.title("Satellite Mining Segmentation: SAR + Optic Image Inference")
@@ -365,28 +355,19 @@ if st.button("Run Inference"):
365
  transform, crs = get_transform_from_tif(optic_path)
366
 
367
  # Convert mask to mining polygons
368
- non_mining_gdf = mask_to_polygons(pred_label_mask, transform, target_class_id=0)
369
- mining_gdf = mask_to_polygons(pred_label_mask, transform, target_class_id=1)
370
- beach_gdf = mask_to_polygons(pred_label_mask, transform, target_class_id=2)
371
-
372
- st.success(f"Non-mining polygons: {len(non_mining_gdf)}")
373
  st.success(f"Mining polygons: {len(mining_gdf)}")
374
- st.success(f"Beach polygons: {len(beach_gdf)}")
375
 
376
  # Make sure WIUP and prediction are in same CRS
377
  wiup_gdf = wiup_gdf.to_crs(mining_gdf.crs)
378
  st.success(f"WIUP CRS: {wiup_gdf.crs}")
379
 
380
  # Find area
381
- non_mining_area, non_mining_area_gdf = calculate_area(non_mining_gdf, wiup_gdf)
382
- mining_area, mining_area_gdf = calculate_area(mining_gdf, wiup_gdf)
383
- beach_area, beach_area_gdf = calculate_area(beach_gdf, wiup_gdf)
384
 
385
  # Display in Streamlit
386
- st.success(f" Non Mining Area : {non_mining_area/1e6:.2f} sq. km")
387
- st.success(f" Mining Area : {mining_area/1e6:.2f} sq. km")
388
- st.success(f" Beach Area : {beach_area/1e6:.2f} sq. km")
389
-
390
 
391
  else:
392
  st.warning("Please upload all three .tiff files to proceed.")
 
158
  crs = src.crs
159
  return transform, crs
160
 
161
+ def mask_to_polygons(mask, transform, mining_class_id=1):
162
+ # Create a binary mask for mining areas
163
+ mining_mask = (mask == mining_class_id).astype(np.uint8)
 
 
 
 
 
 
 
 
 
 
 
164
 
165
+ # Extract shapes (polygons) from the mask
166
  results = (
167
+ {'properties': {'class': 'mining_land'}, 'geometry': s}
168
+ for s, v in shapes(mining_mask, mask=None, transform=transform)
169
+ if v == 1 # Only keep areas marked as mining
170
  )
171
 
172
+ # Create a GeoDataFrame from the polygon results
173
  geoms = list(results)
 
 
174
  if not geoms:
175
  return gpd.GeoDataFrame(columns=['geometry'], geometry='geometry', crs='EPSG:4326')
176
 
 
179
  return gdf
180
 
181
 
182
+ # Function to calculate illegal mining area (mining outside WIUP)
183
+ def calculate_illegal_area(mining_gdf, wiup_gdf):
184
+ # Ensure both are in the same CRS
185
  mining_gdf = mining_gdf.to_crs(wiup_gdf.crs)
186
 
187
+ # Perform overlay operation: difference (mining area outside WIUP)
188
+ illegal_area_gdf = gpd.overlay(mining_gdf, wiup_gdf, how='difference')
189
 
190
  # Convert to metric CRS (e.g., UTM) to calculate area in m²
191
+ metric_crs = ' EPSG:4326' # UTM zone for SE Asia (adjust based on location)
192
+ illegal_area_gdf = illegal_area_gdf.to_crs(metric_crs)
193
+
194
+ # Calculate the area in square meters
195
+ illegal_area_gdf['area_m2'] = illegal_area_gdf.geometry.area
196
+ total_illegal_area = illegal_area_gdf['area_m2'].sum()
197
 
198
+ return total_illegal_area, illegal_area_gdf
199
 
200
  # Streamlit App Title
201
  st.title("Satellite Mining Segmentation: SAR + Optic Image Inference")
 
355
  transform, crs = get_transform_from_tif(optic_path)
356
 
357
  # Convert mask to mining polygons
358
+ mining_gdf = mask_to_polygons(pred_label_mask, transform, mining_class_id=1)
 
 
 
 
359
  st.success(f"Mining polygons: {len(mining_gdf)}")
360
+
361
 
362
  # Make sure WIUP and prediction are in same CRS
363
  wiup_gdf = wiup_gdf.to_crs(mining_gdf.crs)
364
  st.success(f"WIUP CRS: {wiup_gdf.crs}")
365
 
366
  # Find area
367
+ mining_area, mining_area_gdf = calculate_illegal_area(mining_gdf, wiup_gdf)
 
 
368
 
369
  # Display in Streamlit
370
+ st.success(f" Illegal Mining Area : {mining_area/1e6:.2f} sq. km")
 
 
 
371
 
372
  else:
373
  st.warning("Please upload all three .tiff files to proceed.")