Detecting Mine Perimeter with Segment Geospatial

Detecting Mine Perimeter with Segment Geospatial#

Overview#

We use the samgeo package to segment a GeoTIFF image of a mining area. To ensure we get only the mine boundary, we will prompt the model with a set of ‘foreground’ and ‘background’ points.

The image used here is a RGB composite of a mining area derived from a Sentinel-2 image. The image has been exported from Google Earth Engine. See reference script.

# Installlation of segment-geospatial can take a few minutes. Please be patient
%%capture
if 'google.colab' in str(get_ipython()):
    !pip install segment-geospatial rioxarray
import geopandas as gpd
import os
import matplotlib.pyplot as plt
import rioxarray as rxr
from samgeo import SamGeo
data_folder = 'data'
output_folder = 'output'

if not os.path.exists(data_folder):
    os.mkdir(data_folder)
if not os.path.exists(output_folder):
    os.mkdir(output_folder)
def download(url):
    filename = os.path.join(data_folder, os.path.basename(url))
    if not os.path.exists(filename):
        from urllib.request import urlretrieve
        local, _ = urlretrieve(url, filename)
        print('Downloaded ' + local)

data_url = 'https://github.com/spatialthoughts/geopython-tutorials/releases/download/data/'

image = 's2_mines_rgb.tif'

download(data_url + image)
image_path = os.path.join(data_folder, image)
image = rxr.open_rasterio(image_path)
fig, ax = plt.subplots(1, 1)
fig.set_size_inches(7,10)
image.plot.imshow(ax=ax)
ax.set_axis_off()
ax.set_aspect('equal')
ax.set_title('Image')
plt.show()
../_images/3da52483d66a59404b4688d776b508fba4ed5dec8356da900b5044a204f4ee50.png

Segmentation with Training Samples#

If we wanted to extract boundaries for a lot of mines without manually adding training data, we can use a set of training samples to prompt the model. These training samples can be automatically generated using existing databases such as Global mining footprint mapped from high-resolution satellite imagery the following method:

  • Foreground Points: Take the mine polyogn and buffer it inwards by XX meters. Sample N points within the buffer.

  • Background Points: Take the mine polygon and buffer is outwards by XX meters. Take the difference between the AOI and buffer. Sample M points from the resulting region.

sam = SamGeo(
    model_type="vit_h",
    automatic=False,
    sam_kwargs=None,
)
mask = 'mining_perimeter.tif'
training_mask_path = os.path.join(output_folder, mask)
vector = 'mining_perimeter.gpkg'
training_vector_path = os.path.join(output_folder, vector)
foreground_coords = [
    [-105.2030365777389, 43.59243279130138],
    [-105.31799690813952, 43.58165243450691],
    [-105.31389118205367, 43.65410388290101],
    [-105.33134051791814, 43.69753284641334],
    [-105.29130968858229, 43.75501854039891],
    [-105.31127393080612, 43.72971279039413],
    [-105.34977689826118, 43.74965309055227]
]

background_coords = [
    [-105.27024271682525, 43.59987910041002],
    [-105.24252906574645, 43.72165914628937],
    [-105.22507972988198, 43.64334727429318],
    [-105.32310394017892, 43.609913006905344],
    [-105.38109732113958, 43.74094305344275]
]

n_foreground_pts = len(foreground_coords)
n_background_pts = len(background_coords)


point_coords = foreground_coords + background_coords

point_labels = [1] * n_foreground_pts + [0] * n_background_pts

sam.set_image(image_path)
sam.predict(
    point_coords=point_coords,
    point_labels=point_labels,
    point_crs='EPSG:4326',
    output=training_mask_path
)

Convert the predicted mask to vectors.

sam.tiff_to_gpkg(
    training_mask_path,
    training_vector_path,
    simplify_tolerance=None)

Visualize the results.

fig, ax = plt.subplots(1, 1)
fig.set_size_inches(7,10)
image.plot.imshow(ax=ax)

perimeter_gdf = gpd.read_file(training_vector_path)
perimeter_gdf.plot(
    ax=ax,
    linewidth=1,
    facecolor='none',
    edgecolor='blue',
    alpha=0.6
)
ax.set_axis_off()
ax.set_aspect('equal')
ax.set_title('Extracted Mining Perimeter')
plt.show()
../_images/d3e4f62116ba5f8612d5f9ca25a0e3bce15c1a1e716859c32c4c88f9bca533e7.png

If you want to give feedback or share your experience with this tutorial, please comment below. (requires GitHub account)