Accesso alla raccolta dei dati raster di Sentinel-2 e creazione di un processo di osservazione della terra per eseguire la segmentazione del suolo - Amazon SageMaker

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 Questi satelliti forniscono una copertura globale della superficie terrestre ogni cinque giorni. Oltre a raccogliere immagini della superficie terrestre, i satelliti Sentinel-2 raccolgono anche dati su diverse bande spettrali.

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_collectionsAPIoperazione. 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 Mead nello Utah. Inoltre, Sentinel-2 supporta diversi tipi di bande di immagini. Per misurare la variazione della superficie dell'acqua, è sufficiente la banda visual.

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'NextTokenesistenza. 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 usa LandCoverSegmentationConfig.

  • 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_jobsAPI. Per monitorare lo stato di un singolo lavoro di osservazione della terra, utilizzare il get_earth_observation_jobAPI. 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_jobsAPIoperazione. 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.

Un istogramma che mostra che la superficie del lago Mead è diminuita da gennaio 2021 a luglio 2022