Le traduzioni sono generate tramite traduzione automatica. In caso di conflitto tra il contenuto di una traduzione e la versione originale in Inglese, quest'ultima prevarrà.
Questo tutorial basato su Python utilizza l'SDK per Python (Boto3) e un notebook Amazon Studio Classic. SageMaker Per completare correttamente questa demo, assicurati di disporre delle autorizzazioni AWS Identity and Access Management (IAM) necessarie per utilizzare geospatial e Studio Classic. SageMaker SageMaker geospatial richiede la presenza di un utente, gruppo o ruolo che possa accedere a Studio Classic. È inoltre necessario disporre di un ruolo di esecuzione dell' SageMaker IA che specifichi il responsabile del servizio SageMaker geospaziale nella sua politica di fiducia. sagemaker-geospatial.amazonaws.com
Per ulteriori informazioni su questi requisiti, consulta SageMaker i ruoli IAM geospaziali.
Questo tutorial mostra come utilizzare l'API SageMaker geospaziale per completare le seguenti attività:
-
Trovare le raccolte dei dati raster disponibili con
list_raster_data_collections
. -
Cercare una raccolta dei dati raster specificata utilizzando
search_raster_data_collection
. -
Creare un processo di osservazione della terra (EOJ) utilizzando
start_earth_observation_job
.
Utilizzare list_raster_data_collections
per trovare le raccolte dei dati disponibili
SageMaker geospatial supporta più raccolte di dati raster. Per ulteriori informazioni sulle raccolte dei dati disponibili, consulta Raccolte dati.
Questa demo utilizza dati satellitari raccolti da Sentinel-2 Satelliti
Per cercare un'area di interesse (AOI), hai bisogno dell'ARN associato ai dati satellitari Sentinel-2. Per trovare le raccolte di dati disponibili e quelle associate ARNs nel tuo Regione AWS, utilizza l'operazione API. list_raster_data_collections
Poiché la risposta può essere impaginata, devi utilizzare l'operazione get_paginator
affinché restituisca tutti i dati pertinenti:
import boto3
import sagemaker
import sagemaker_geospatial_map
import json
## SageMaker Geospatial is currently only avaialable in US-WEST-2
session = boto3.Session(region_name='us-west-2')
execution_role = sagemaker.get_execution_role()
## Creates a SageMaker Geospatial client instance
geospatial_client = session.client(service_name="sagemaker-geospatial")
# Creates a resusable Paginator for the list_raster_data_collections API operation
paginator = geospatial_client.get_paginator("list_raster_data_collections")
# Create a PageIterator from the paginator class
page_iterator = paginator.paginate()
# Use the iterator to iterate throught the results of list_raster_data_collections
results = []
for page in page_iterator:
results.append(page['RasterDataCollectionSummaries'])
print(results)
Questo è un esempio di risposta JSON dall'operazione API list_raster_data_collections
. Viene troncato per includere solo la raccolta di dati (Sentinel-2) utilizzato in questo esempio di codice. Per ulteriori dettagli su una specifica raccolta dei dati raster, usa get_raster_data_collection
:
{
"Arn": "arn:aws:sagemaker-geospatial:us-west-2:378778860802:raster-data-collection/public/nmqj48dcu3g7ayw8",
"Description": "Sentinel-2a and Sentinel-2b imagery, processed to Level 2A (Surface Reflectance) and converted to Cloud-Optimized GeoTIFFs",
"DescriptionPageUrl": "https://registry.opendata.aws/sentinel-2-l2a-cogs",
"Name": "Sentinel 2 L2A COGs",
"SupportedFilters": [
{
"Maximum": 100,
"Minimum": 0,
"Name": "EoCloudCover",
"Type": "number"
},
{
"Maximum": 90,
"Minimum": 0,
"Name": "ViewOffNadir",
"Type": "number"
},
{
"Name": "Platform",
"Type": "string"
}
],
"Tags": {},
"Type": "PUBLIC"
}
Dopo aver eseguito l'esempio di codice precedente, otterrai l'ARN della raccolta dei dati raster Sentinel-2, arn:aws:sagemaker-geospatial:us-west-2:378778860802:raster-data-collection/public/nmqj48dcu3g7ayw8
. Nella sezione successiva, puoi eseguire query sulla raccolta dei dati Sentinel-2 utilizzando l'API search_raster_data_collection
.
Sto cercando il Sentinel-2 raccolta di dati raster utilizzando search_raster_data_collection
Nella sezione precedente, si otteneva list_raster_data_collections
l'ARN per il Sentinel-2 raccolta dati. Ora puoi usare quell'ARN per cercare la raccolta dei dati su una determinata area di interesse (AOI), intervallo temporale, proprietà e bande UV disponibili.
Per chiamare l'search_raster_data_collection
API devi inserire un Python dictionary al RasterDataCollectionQuery
parametro. Questo esempio utilizza AreaOfInterest
, TimeRangeFilter
, PropertyFilters
e BandFilter
. Per semplicità, puoi specificare il dizionario Python usando la variabile search_rdc_query
per contenere i parametri di query della ricerca:
search_rdc_query = {
"AreaOfInterest": {
"AreaOfInterestGeometry": {
"PolygonGeometry": {
"Coordinates": [
[
# coordinates are input as longitute followed by latitude
[-114.529, 36.142]
,
[-114.373, 36.142]
,
[-114.373, 36.411]
,
[-114.529, 36.411]
,
[-114.529, 36.142]
,
]
]
}
}
},
"TimeRangeFilter": {
"StartTime": "2022-01-01T00:00:00Z"
,
"EndTime": "2022-07-10T23:59:59Z"
},
"PropertyFilters": {
"Properties": [
{
"Property": {
"EoCloudCover": {
"LowerBound": 0,
"UpperBound": 1
}
}
}
],
"LogicalOperator": "AND"
},
"BandFilter": [
"visual"
]
}
In questo esempio, esegui una query su un oggetto AreaOfInterest
che include Lago Meadvisual
.
Dopo aver creato i parametri di query, puoi utilizzare l'API search_raster_data_collection
per effettuare la richiesta.
Il seguente esempio di codice implementa una richiesta API search_raster_data_collection
. Questa API non supporta l'impaginazione tramite l'API get_paginator
. Per assicurarsi che sia stata restituita la risposta API completa, l'esempio di codice utilizza un ciclo while
per verificarne l'NextToken
esistenza. L'esempio di codice viene quindi utilizzato .extend()
per aggiungere l'immagine satellitare URLs e altri metadati di risposta a. items_list
Per ulteriori informazionisearch_raster_data_collection
, consulta SearchRasterDataCollectionAmazon SageMaker AI API Reference.
search_rdc_response = sm_geo_client.search_raster_data_collection(
Arn='arn:aws:sagemaker-geospatial:us-west-2:378778860802:raster-data-collection/public/nmqj48dcu3g7ayw8',
RasterDataCollectionQuery=search_rdc_query
)
## items_list is the response from the API request.
items_list = []
## Use the python .get() method to check that the 'NextToken' exists, if null returns None breaking the while loop
while search_rdc_response.get('NextToken'):
items_list.extend(search_rdc_response['Items'])
search_rdc_response = sm_geo_client.search_raster_data_collection(
Arn='arn:aws:sagemaker-geospatial:us-west-2:378778860802:raster-data-collection/public/nmqj48dcu3g7ayw8',
RasterDataCollectionQuery=search_rdc_query, NextToken=search_rdc_response['NextToken']
)
## Print the number of observation return based on the query
print (len(items_list))
Di seguito è riportato un esempio di risposta JSON alla tua query. La risposta è stata troncata per maggiore chiarezza. Nella coppia chiave-valore Assets
viene restituito solo il "BandFilter": ["visual"]
specificato nella richiesta:
{
'Assets': {
'visual': {
'Href': 'https://sentinel-cogs.s3.us-west-2.amazonaws.com/sentinel-s2-l2a-cogs/15/T/UH/2022/6/S2A_15TUH_20220623_0_L2A/TCI.tif'
}
},
'DateTime': datetime.datetime(2022, 6, 23, 17, 22, 5, 926000, tzinfo = tzlocal()),
'Geometry': {
'Coordinates': [
[
[-114.529, 36.142]
,
[-114.373, 36.142]
,
[-114.373, 36.411]
,
[-114.529, 36.411]
,
[-114.529, 36.142]
,
]
],
'Type': 'Polygon'
},
'Id': 'S2A_15TUH_20220623_0_L2A',
'Properties': {
'EoCloudCover': 0.046519,
'Platform': 'sentinel-2a'
}
}
Ora che hai i risultati della tua query, puoi visualizzarli nella sezione successiva utilizzando matplotlib
. Questo serve a verificare che i risultati provengano dalla regione geografica corretta.
Visualizzazione di search_raster_data_collection
utilizzando matplotlib
Prima di iniziare il processo di osservazione della terra (EOJ), puoi visualizzare un risultato della query conmatplotlib
. Il seguente esempio di codice prende il primo elemento, items_list[0]["Assets"]["visual"]["Href"]
, dalla variabile items_list
creata nell'esempio di codice precedente e stampa un'immagine utilizzando matplotlib
.
# Visualize an example image.
import os
from urllib import request
import tifffile
import matplotlib.pyplot as plt
image_dir = "./images/lake_mead"
os.makedirs(image_dir, exist_ok=True)
image_dir = "./images/lake_mead"
os.makedirs(image_dir, exist_ok=True)
image_url = items_list[0]["Assets"]["visual"]["Href"]
img_id = image_url.split("/")[-2]
path_to_image = image_dir + "/" + img_id + "_TCI.tif"
response = request.urlretrieve(image_url, path_to_image)
print("Downloaded image: " + img_id)
tci = tifffile.imread(path_to_image)
plt.figure(figsize=(6, 6))
plt.imshow(tci)
plt.show()
Dopo aver verificato che i risultati siano nella regione geografica corretta, puoi avviare il processo di osservazione della terra (EOJ) nella fase successiva. Si utilizza il processo EOJ per identificare i corpi idrici dalle immagini satellitari utilizzando un processo chiamato segmentazione del suolo.
Avvio di un processo di osservazione della terra (EOJ) che esegue la segmentazione del suolo su una serie di immagini satellitari
SageMaker geospatial fornisce diversi modelli pre-addestrati che puoi utilizzare per elaborare dati geospaziali da raccolte di dati raster. Per ulteriori informazioni sui modelli preaddestrati disponibili e sulle operazioni personalizzate, consulta Tipi di operazioni.
Per calcolare la variazione della superficie dell'acqua, devi identificare quali pixel delle immagini corrispondono all'acqua. La segmentazione della copertura del suolo è un modello di segmentazione semantica supportato dall'API start_earth_observation_job
. I modelli di segmentazione semantica associano un'etichetta a ogni pixel di ogni immagine. Nei risultati, a ogni pixel viene assegnata un'etichetta basata sulla mappatura delle classi del modello. Di seguito è riportata la mappatura delle classi per il modello di segmentazione del suolo:
{
0: "No_data",
1: "Saturated_or_defective",
2: "Dark_area_pixels",
3: "Cloud_shadows",
4: "Vegetation",
5: "Not_vegetated",
6: "Water",
7: "Unclassified",
8: "Cloud_medium_probability",
9: "Cloud_high_probability",
10: "Thin_cirrus",
11: "Snow_ice"
}
Per avviare un processo di osservazione della terra, usa l'API start_earth_observation_job
. Quando invii la richiesta, devi specificare quanto segue:
-
InputConfig
(dict): utilizzato per specificare le coordinate dell'area in cui desideri cercare e altri metadati associati alla tua ricerca. -
JobConfig
(dict): utilizzato per specificare il tipo di operazione EOJ eseguita sui dati. Questo esempio usaLandCoverSegmentationConfig
. -
ExecutionRoleArn
(stringa) — L'ARN del ruolo di esecuzione SageMaker AI con le autorizzazioni necessarie per eseguire il processo. -
Name
(string): un nome per il processo di osservazione della terra.
Il InputConfig
è un Python dizionario. Utilizza la seguente variabile eoj_input_config
per contenere i parametri di query della ricerca. Usa questa variabile quando effettui la richiesta API start_earth_observation_job
.
# Perform land cover segmentation on images returned from the Sentinel-2 dataset.
eoj_input_config = {
"RasterDataCollectionQuery": {
"RasterDataCollectionArn": "arn:aws:sagemaker-geospatial:us-west-2:378778860802:raster-data-collection/public/nmqj48dcu3g7ayw8",
"AreaOfInterest": {
"AreaOfInterestGeometry": {
"PolygonGeometry": {
"Coordinates":[
[
[-114.529, 36.142]
,
[-114.373, 36.142]
,
[-114.373, 36.411]
,
[-114.529, 36.411]
,
[-114.529, 36.142]
,
]
]
}
}
},
"TimeRangeFilter": {
"StartTime": "2021-01-01T00:00:00Z"
,
"EndTime": "2022-07-10T23:59:59Z"
,
},
"PropertyFilters": {
"Properties": [{"Property": {"EoCloudCover": {"LowerBound": 0, "UpperBound": 1}}}],
"LogicalOperator": "AND",
},
}
}
Il JobConfig
è un Python dizionario utilizzato per specificare l'operazione EOJ da eseguire sui dati:
eoj_config = {"LandCoverSegmentationConfig": {}}
Con gli elementi del dizionario ora specificati, puoi inviare la tua richiesta API start_earth_observation_job
utilizzando il seguente esempio di codice:
# Gets the execution role arn associated with current notebook instance
execution_role_arn = sagemaker.get_execution_role()
# Starts an earth observation job
response = sm_geo_client.start_earth_observation_job(
Name="lake-mead-landcover"
,
InputConfig=eoj_input_config,
JobConfig=eoj_config,
ExecutionRoleArn=execution_role_arn,
)
print(response)
L'avvio di un processo di osservazione della terra restituisce un ARN insieme ad altri metadati.
Per ottenere un elenco di tutti i processi di osservazione della terra in corso e correnti, utilizza l'API list_earth_observation_jobs
. Per monitorare lo stato di un singolo processo di osservazione della Terra, utilizza l'API get_earth_observation_job
. Per effettuare questa richiesta, utilizza l'ARN creato dopo aver inviato la richiesta EOJ. Per ulteriori informazioni, GetEarthObservationJobconsulta Amazon SageMaker AI API Reference.
Per trovare le informazioni ARNs associate alla tua, EOJs utilizza l'operazione list_earth_observation_jobs
API. Per ulteriori informazioni, ListEarthObservationJobsconsulta Amazon SageMaker AI API Reference.
# List all jobs in the account
sg_client.list_earth_observation_jobs()["EarthObservationJobSummaries"]
Di seguito è riportato un esempio di risposta JSON:
{
'Arn': 'arn:aws:sagemaker-geospatial:us-west-2:111122223333:earth-observation-job/futg3vuq935t',
'CreationTime': datetime.datetime(2023, 10, 19, 4, 33, 54, 21481, tzinfo = tzlocal()),
'DurationInSeconds': 3493,
'Name': 'lake-mead-landcover'
,
'OperationType': 'LAND_COVER_SEGMENTATION',
'Status': 'COMPLETED',
'Tags': {}
}, {
'Arn': 'arn:aws:sagemaker-geospatial:us-west-2:111122223333:earth-observation-job/wu8j9x42zw3d',
'CreationTime': datetime.datetime(2023, 10, 20, 0, 3, 27, 270920, tzinfo = tzlocal()),
'DurationInSeconds': 1,
'Name': 'mt-shasta-landcover'
,
'OperationType': 'LAND_COVER_SEGMENTATION',
'Status': 'INITIALIZING',
'Tags': {}
}
Dopo che lo stato del tuo job EOJ diventaCOMPLETED
, passa alla sezione successiva per calcolare la modifica in Lake Mead's superficie.
Calcolo della variazione del lago Mead superficie
Per calcolare la variazione della superficie del lago Mead, esporta innanzitutto i risultati del processo EOJ su Amazon S3 utilizzando export_earth_observation_job
:
sagemaker_session = sagemaker.Session()
s3_bucket_name = sagemaker_session.default_bucket() # Replace with your own bucket if needed
s3_bucket = session.resource("s3").Bucket(s3_bucket_name)
prefix = "export-lake-mead-eoj"
# Replace with the S3 prefix desired
export_bucket_and_key = f"s3://{s3_bucket_name}/{prefix}/"
eoj_output_config = {"S3Data": {"S3Uri": export_bucket_and_key}}
export_response = sm_geo_client.export_earth_observation_job(
Arn="arn:aws:sagemaker-geospatial:us-west-2:111122223333:earth-observation-job/7xgwzijebynp
",
ExecutionRoleArn=execution_role_arn,
OutputConfig=eoj_output_config,
ExportSourceImages=False,
)
Per visualizzare lo stato del tuo processo di esportazione, utilizza get_earth_observation_job
:
export_job_details = sm_geo_client.get_earth_observation_job(Arn=export_response["Arn"])
Per calcolare le variazioni del livello dell'acqua del Lago Mead, scarica le maschere di copertura del terreno sull'istanza SageMaker notebook locale e scarica le immagini di origine della nostra query precedente. Nella mappatura delle classi per il modello di segmentazione del suolo, l'indice di classe dell'acqua è 6.
Per estrarre la maschera d'acqua da un Sentinel-2 immagine, segui questi passaggi. Innanzitutto, conta nell'immagine il numero di pixel contrassegnati come acqua (indice di classe 6). In secondo luogo, moltiplica il conteggio per l'area coperta da ciascun pixel. Le bande possono differire in termini di risoluzione spaziale. Per il modello di segmentazione della copertura del suolo, tutte le bande vengono sottocampionate con una risoluzione spaziale pari a 60 metri.
import os
from glob import glob
import cv2
import numpy as np
import tifffile
import matplotlib.pyplot as plt
from urllib.parse import urlparse
from botocore import UNSIGNED
from botocore.config import Config
# Download land cover masks
mask_dir = "./masks/lake_mead"
os.makedirs(mask_dir, exist_ok=True)
image_paths = []
for s3_object in s3_bucket.objects.filter(Prefix=prefix).all():
path, filename = os.path.split(s3_object.key)
if "output" in path:
mask_name = mask_dir + "/" + filename
s3_bucket.download_file(s3_object.key, mask_name)
print("Downloaded mask: " + mask_name)
# Download source images for visualization
for tci_url in tci_urls:
url_parts = urlparse(tci_url)
img_id = url_parts.path.split("/")[-2]
tci_download_path = image_dir + "/" + img_id + "_TCI.tif"
cogs_bucket = session.resource(
"s3", config=Config(signature_version=UNSIGNED, region_name="us-west-2")
).Bucket(url_parts.hostname.split(".")[0])
cogs_bucket.download_file(url_parts.path[1:], tci_download_path)
print("Downloaded image: " + img_id)
print("Downloads complete.")
image_files = glob("images/lake_mead/*.tif")
mask_files = glob("masks/lake_mead/*.tif")
image_files.sort(key=lambda x: x.split("SQA_")[1])
mask_files.sort(key=lambda x: x.split("SQA_")[1])
overlay_dir = "./masks/lake_mead_overlay"
os.makedirs(overlay_dir, exist_ok=True)
lake_areas = []
mask_dates = []
for image_file, mask_file in zip(image_files, mask_files):
image_id = image_file.split("/")[-1].split("_TCI")[0]
mask_id = mask_file.split("/")[-1].split(".tif")[0]
mask_date = mask_id.split("_")[2]
mask_dates.append(mask_date)
assert image_id == mask_id
image = tifffile.imread(image_file)
image_ds = cv2.resize(image, (1830, 1830), interpolation=cv2.INTER_LINEAR)
mask = tifffile.imread(mask_file)
water_mask = np.isin(mask, [6]).astype(np.uint8) # water has a class index 6
lake_mask = water_mask[1000:, :1100]
lake_area = lake_mask.sum() * 60 * 60 / (1000 * 1000) # calculate the surface area
lake_areas.append(lake_area)
contour, _ = cv2.findContours(water_mask, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)
combined = cv2.drawContours(image_ds, contour, -1, (255, 0, 0), 4)
lake_crop = combined[1000:, :1100]
cv2.putText(lake_crop, f"{mask_date}", (10,50), cv2.FONT_HERSHEY_SIMPLEX, 1.5, (0, 0, 0), 3, cv2.LINE_AA)
cv2.putText(lake_crop, f"{lake_area} [sq km]", (10,100), cv2.FONT_HERSHEY_SIMPLEX, 1.5, (0, 0, 0), 3, cv2.LINE_AA)
overlay_file = overlay_dir + '/' + mask_date + '.png'
cv2.imwrite(overlay_file, cv2.cvtColor(lake_crop, cv2.COLOR_RGB2BGR))
# Plot water surface area vs. time.
plt.figure(figsize=(20,10))
plt.title('Lake Mead surface area for the 2021.02 - 2022.07 period.', fontsize=20)
plt.xticks(rotation=45)
plt.ylabel('Water surface area [sq km]', fontsize=14)
plt.plot(mask_dates, lake_areas, marker='o')
plt.grid('on')
plt.ylim(240, 320)
for i, v in enumerate(lake_areas):
plt.text(i, v+2, "%d" %v, ha='center')
plt.show()
Utilizzando matplotlib
, puoi visualizzare i risultati su un grafico. Il grafico mostra che la superficie del lago Mead è diminuito da gennaio 2021 a luglio 2022.
