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à.
Accesso alla raccolta dei dati raster di Sentinel-2 e creazione di un processo di osservazione della terra per eseguire la segmentazione del suolo
Questo tutorial basato su Python utilizza il notebook for SDK Python (Boto3) e Amazon Studio Classic. SageMaker Per completare correttamente questa demo, assicurati di disporre delle autorizzazioni necessarie AWS Identity and Access Management (IAM) 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 SageMaker esecuzione che specifichi il responsabile del servizio SageMaker geospaziale nella relativa politica di attendibilità. sagemaker-geospatial.amazonaws.com
Per ulteriori informazioni su questi requisiti, consulta i ruoli geospaziali. SageMaker IAM
Questo tutorial mostra come utilizzare i dati SageMaker geospaziali API 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
. -
Crea un lavoro 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 Geo ottimizzati per il cloud. TIFF
Per cercare un'area di interesse (AOI), hai bisogno dei dati associati ai dati ARN satellitari Sentinel-2. Per trovare le raccolte di dati disponibili e quelle associate ARNs nel tuo Regione AWS, usa l'operazione. list_raster_data_collections
API
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 JSON risposta dell'list_raster_data_collections
APIoperazione. La risposta è troncata per includere solo la raccolta dei dati (Sentinel-2) utilizzata 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, si ottiene la raccolta ARN di dati raster Sentinel-2,. arn:aws:sagemaker-geospatial:us-west-2:378778860802:raster-data-collection/public/nmqj48dcu3g7ayw8
Nella sezione successiva, è possibile interrogare la raccolta di dati Sentinel-2 utilizzando il. search_raster_data_collection
API
Ricerca nella raccolta dei dati raster di Sentinel-2 utilizzando search_raster_data_collection
Nella sezione precedente, si usava ottenere il file list_raster_data_collections
ARN per la raccolta dei dati. Sentinel-2 Ora puoi usarlo ARN per cercare nella raccolta di dati su una determinata area di interesse (AOI), intervallo di tempo, proprietà e bande UV disponibili.
Per search_raster_data_collection
API chiamarli è necessario passare Python un dizionario 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 interrogazione, è possibile utilizzare il search_raster_data_collection
API per effettuare la richiesta.
Il seguente esempio di codice implementa una search_raster_data_collection
API richiesta. Ciò API non supporta l'impaginazione tramite. get_paginator
API Per assicurarsi che la API risposta completa sia stata raccolta, l'esempio di codice utilizza un while
ciclo 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 informazioni susearch_raster_data_collection
, SearchRasterDataCollectionconsulta Amazon SageMaker 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 è riportata una JSON risposta alla tua richiesta. 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 lavoro di osservazione della Terra (EOJ), puoi visualizzare un risultato della nostra interrogazione con matplotlib
. 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, potete avviare Earth Observation Job (EOJ) nel passaggio successivo. Utilizzate il EOJ per identificare i corpi idrici dalle immagini satellitari utilizzando un processo chiamato segmentazione del territorio.
Avvio di un lavoro di osservazione della terra (EOJ) che esegua la segmentazione del territorio su una serie di immagini satellitari
SageMaker geospatial fornisce diversi modelli pre-addestrati che è possibile utilizzare per elaborare dati geospaziali provenienti 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 da. start_earth_observation_job
API 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 iniziare un lavoro di osservazione della terra, usa il. start_earth_observation_job
API 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 EOJ operazione eseguita sui dati. Questo esempio usaLandCoverSegmentationConfig
. -
ExecutionRoleArn
(stringa) — Il ruolo ARN di SageMaker esecuzione con le autorizzazioni necessarie per eseguire il lavoro. -
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. Utilizzate questa variabile quando effettuate la start_earth_observation_job
API richiesta. w.
# 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 che viene utilizzato per specificare l'EOJoperazione che si desidera eseguire sui dati:
eoj_config = {"LandCoverSegmentationConfig": {}}
Con gli elementi del dizionario ora specificati, puoi inviare la tua start_earth_observation_job
API richiesta 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 lavoro di osservazione della terra restituisce un ARN insieme ad altri metadati.
Per ottenere un elenco di tutti i lavori di osservazione della Terra in corso e in corso, utilizza il list_earth_observation_jobs
API. Per monitorare lo stato di un singolo lavoro di osservazione della terra, utilizzare il get_earth_observation_job
API. Per effettuare questa richiesta, utilizza il file ARN creato dopo aver inviato la EOJ richiesta. Per ulteriori informazioni, GetEarthObservationJobconsulta Amazon SageMaker API Reference.
Per trovare ciò che ARNs è associato alla tua, EOJs usa l'list_earth_observation_jobs
APIoperazione. Per ulteriori informazioni, ListEarthObservationJobsconsulta Amazon SageMaker API Reference.
# List all jobs in the account sg_client.list_earth_observation_jobs()["EarthObservationJobSummaries"]
Di seguito è riportato un esempio di JSON risposta:
{ '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 EOJ lavoro è cambiato inCOMPLETED
, passa alla sezione successiva per calcolare la modifica della Mead's superficie del lago.
Calcolo della variazione della superficie nel lago Mead
Per calcolare la variazione della superficie di Lake Mead, esporta innanzitutto i risultati di EOJ in 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 di Lake Mead, scarica le maschere di copertura del suolo sull'istanza del SageMaker notebook locale e scarica le immagini di origine dalla nostra query precedente. Nella mappatura delle classi per il modello di segmentazione del suolo, l'indice di classe dell'acqua è 6.
Per estrarre da un'immagine Sentinel-2 il file maschera relativo all’acqua, segui questa procedura. 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 è diminuita da gennaio 2021 a luglio 2022.