Die vorliegende Übersetzung wurde maschinell erstellt. Im Falle eines Konflikts oder eines Widerspruchs zwischen dieser übersetzten Fassung und der englischen Fassung (einschließlich infolge von Verzögerungen bei der Übersetzung) ist die englische Fassung maßgeblich.
Greifen Sie auf die Sentinel-2-Rasterdatensammlung zu und erstellen Sie einen Erdbeobachtungsauftrag zur Landsegmentierung
Dieses Python-basierte Tutorial verwendet das SDK für Python (Boto3) und ein Amazon Studio Classic-Notizbuch. SageMaker Um diese Demo erfolgreich abzuschließen, stellen Sie sicher, dass Sie über die erforderlichen AWS Identity and Access Management (IAM-) Berechtigungen für die Verwendung von Geospatial und Studio Classic verfügen. SageMaker SageMaker Geospatial erfordert, dass Sie über einen Benutzer, eine Gruppe oder eine Rolle verfügen, die auf Studio Classic zugreifen können. Sie müssen außerdem über eine SageMaker AI-Ausführungsrolle verfügen, die den Prinzipal des SageMaker Geospatial Service sagemaker-geospatial.amazonaws.com
in ihrer Vertrauensrichtlinie spezifiziert.
Weitere Informationen zu diesen Anforderungen finden Sie unter SageMaker Geospatial IAM-Rollen.
In diesem Tutorial erfahren Sie, wie Sie die SageMaker Geospatial-API verwenden, um die folgenden Aufgaben auszuführen:
-
Finden Sie die verfügbaren Raster-Datensammlungen mit
list_raster_data_collections
. -
Suchen Sie eine angegebene Raster-Datensammlung mithilfe von
search_raster_data_collection
. -
Erstellen Sie einen Erdbeobachtungsauftrag (EOJ) mithilfe von
start_earth_observation_job
.
Verwenden von list_raster_data_collections
, um verfügbare Datensammlungen zu finden
SageMaker Geospatial unterstützt mehrere Rasterdatensammlungen. Weitere Informationen zu den verfügbaren Datensammlungen finden Sie unter Datenerfassung.
Diese Demo verwendet Satellitendaten, die gesammelt wurden von Sentinel-2 Cloud-optimierte GeoTIFF-Satelliten
Um ein Interessengebiet (AOI) zu durchsuchen, benötigen Sie den ARN, der mit den Sentinel-2-Satellitendaten verknüpft ist. Verwenden Sie den list_raster_data_collections
API-Vorgang, um die verfügbaren Datensammlungen und die zugehörigen Datensammlungen ARNs in Ihrem AWS-Region zu finden.
Da die Antwort paginiert werden kann, müssen Sie den get_paginator
Vorgang verwenden, um alle relevanten Daten zurückzugeben:
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)
Dies ist ein Beispiel für eine JSON-Antwort aus dem list_raster_data_collections
API-Vorgang. Es ist gekürzt, sodass es nur die Datensammlung enthält (Sentinel-2), das in diesem Codebeispiel verwendet wird. Weitere Informationen zu einer bestimmten Raster-Datensammlung erhalten Sie mit 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" }
Nachdem Sie das vorherige Codebeispiel ausgeführt haben, erhalten Sie den ARN der Sentinel-2-Raster-Datensammlung, arn:aws:sagemaker-geospatial:us-west-2:378778860802:raster-data-collection/public/nmqj48dcu3g7ayw8
. Im nächsten Abschnitt können Sie die Sentinel-2-Datensammlung mithilfe der search_raster_data_collection
API abfragen.
Ich suche die Sentinel-2 Erfassung von Rasterdaten mit search_raster_data_collection
Im vorherigen Abschnitt haben Sie früher list_raster_data_collections
den ARN für die abgerufen Sentinel-2 Datenerfassung. Jetzt können Sie diesen ARN verwenden, um die Datensammlung über einen bestimmten Interessenbereich (AOI), einen bestimmten Zeitraum, Eigenschaften und die verfügbaren UV-Bänder zu durchsuchen.
Um die search_raster_data_collection
API aufzurufen, müssen Sie eine übergeben Python Wörterbuch zum RasterDataCollectionQuery
Parameter. Dieses Beispiel verwendet AreaOfInterest
, TimeRangeFilter
, PropertyFilters
, und BandFilter
. Der Einfachheit halber können Sie das Python-Wörterbuch mithilfe der Variablen search_rdc_query
angeben, die die Suchabfrageparameter enthalten:
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 diesem Beispiel fragen Sie einen AreaOfInterest
ab, der Lake Meadvisual
Band.
Nachdem Sie die Abfrageparameter erstellt haben, können Sie die search_raster_data_collection
API verwenden, um die Anfrage zu stellen.
Das folgende Codebeispiel implementiert eine search_raster_data_collection
API-Anfrage. Diese API unterstützt keine Paginierung mithilfe der get_paginator
API. Um sicherzustellen, dass die vollständige API-Antwort erfasst wurde, verwendet das Codebeispiel eine while
Schleife, um zu überprüfen, ob NextToken
vorhanden ist. Das Codebeispiel wird dann verwendet.extend()
, um das Satellitenbild URLs und andere Antwortmetadaten an den items_list
anzuhängen.
Weitere Informationen zu finden Sie SearchRasterDataCollectionin der Amazon SageMaker AI API-Referenz. search_raster_data_collection
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))
Nachfolgend sehen Sie eine JSON-Antwort auf Ihre Abfrage. Sie wurde aus Gründen der Übersichtlichkeit gekürzt. Nur das in der Anfrage angegebene "BandFilter": ["visual"]
wird im Schlüssel-Wert-Paar Assets
zurückgegeben:
{ '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' } }
Jetzt, wo Sie Ihre Abfrageergebnisse haben, können Sie die Ergebnisse im nächsten Abschnitt visualisieren, indem Sie matplotlib
verwenden. Auf diese Weise wird überprüft, ob die Ergebnisse aus der richtigen geografischen Region stammen.
Visualisierung von search_raster_data_collection
mit matplotlib
Bevor Sie mit dem Erdbeobachtungsjob (EOJ) beginnen, können Sie ein Ergebnis unserer Abfrage mit matplotlib
visualisieren. Das folgende Codebeispiel verwendet das erste Element, items_list[0]["Assets"]["visual"]["Href"]
, aus der items_list
-Variablen, die im vorherigen Codebeispiel erstellt wurde, und druckt ein Bild mit 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()
Nachdem Sie überprüft haben, ob sich die Ergebnisse in der richtigen geografischen Region befinden, können Sie im nächsten Schritt den Earth Observation Job (EOJ) starten. Sie verwenden das EOJ, um die Gewässer anhand der Satellitenbilder zu identifizieren, indem Sie ein Verfahren verwenden, das als Landsegmentierung bezeichnet wird.
Starten Sie einen Erdbeobachtungsauftrag (EOJ), der eine Landsegmentierung anhand einer Reihe von Satellitenbildern durchführt
SageMaker Geospatial bietet mehrere vortrainierte Modelle, mit denen Sie Geodaten aus Rasterdatensammlungen verarbeiten können. Weitere Informationen zu den verfügbaren vortrainierten Modellen und benutzerdefinierten Operationen finden Sie unter Arten von Operationen.
Um die Veränderung der Wasseroberfläche zu berechnen, müssen Sie ermitteln, welche Pixel in den Bildern Wasser entsprechen. Die Landbedeckungssegmentierung ist ein semantisches Segmentierungsmodell, das von der start_earth_observation_job
API unterstützt wird. Semantische Segmentierungsmodelle ordnen jedem Pixel in jedem Bild eine Bezeichnung zu. In den Ergebnissen wird jedem Pixel eine Bezeichnung zugewiesen, die auf der Klassenzuweisung für das Modell basiert. Im Folgenden finden Sie die Klassenkarte für das Landsegmentierungsmodell:
{ 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" }
Verwenden Sie die start_earth_observation_job
API, um einen Erdbeobachtungsjob zu starten. Beim Senden Ihrer Anfrage müssen Sie Folgendes angeben:
-
InputConfig
(dict) – Wird verwendet, um die Koordinaten des Bereichs, den Sie durchsuchen möchten, und andere Metadaten, die mit Ihrer Suche verknüpft sind, anzugeben. -
JobConfig
(dict) – Wird verwendet, um den Typ der EOJ-Operation anzugeben, die Sie mit den Daten ausgeführt haben. Dieses Beispiel verwendetLandCoverSegmentationConfig
. -
ExecutionRoleArn
(string) — Der ARN der SageMaker AI-Ausführungsrolle mit den erforderlichen Berechtigungen zur Ausführung des Jobs. -
Name
(string) – Ein Name für den Erdbeobachtungsauftrag.
Das InputConfig
ist ein Python Wörterbuch. Verwenden Sie die folgende Variable eoj_input_config
, um die Suchabfrageparameter zu speichern. Verwenden Sie diese Variable, wenn Sie die start_earth_observation_job
API-Anfrage stellen. 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", }, } }
Das JobConfig
ist ein Python Wörterbuch, das verwendet wird, um den EOJ-Vorgang zu spezifizieren, den Sie für Ihre Daten ausführen möchten:
eoj_config = {"LandCoverSegmentationConfig": {}}
Nachdem die Wörterbuchelemente jetzt angegeben sind, können Sie Ihre start_earth_observation_job
API-Anfrage mithilfe des folgenden Codebeispiels einreichen:
# 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)
Der Job „Eine Erdbeobachtung starten“ gibt einen ARN zusammen mit anderen Metadaten zurück.
Um eine Liste aller laufenden und aktuellen Erdbeobachtungsaufträge abzurufen, verwenden Sie die list_earth_observation_jobs
API. Verwenden Sie die get_earth_observation_job
API, um den Status eines einzelnen Erdbeobachtungsauftrags zu überwachen. Verwenden Sie für diese Anfrage den ARN, der nach dem Absenden Ihrer EOJ-Anfrage erstellt wurde. Weitere Informationen finden Sie GetEarthObservationJobin der Amazon SageMaker AI API-Referenz.
Um herauszufinden, was mit Ihrer EOJs Verwendung der list_earth_observation_jobs
API-Operation ARNs verknüpft ist. Weitere Informationen finden Sie ListEarthObservationJobsin der Amazon SageMaker AI API-Referenz.
# List all jobs in the account sg_client.list_earth_observation_jobs()["EarthObservationJobSummaries"]
Nachfolgend finden Sie ein Beispiel einer JSON-Antwort:
{ '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': {} }
Nachdem sich der Status Ihres EOJ-Jobs auf geändert hatCOMPLETED
, fahren Sie mit dem nächsten Abschnitt fort, um die Änderung in Lake zu berechnen Mead's Oberfläche.
Berechnung der Veränderung im See Mead Oberfläche
Um die Änderung der Oberfläche von Lake Mead zu berechnen, exportieren Sie zunächst die Ergebnisse des EOJ nach Amazon S3, indem Sie Folgendes verwenden: 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, )
Um den Status Ihres Exportauftrags zu sehen, verwenden Sie: get_earth_observation_job
export_job_details = sm_geo_client.get_earth_observation_job(Arn=export_response["Arn"])
Um die Veränderungen des Wasserspiegels von Lake Mead zu berechnen, laden Sie die Landbedeckungsmasken in die lokale SageMaker Notebook-Instanz herunter und laden Sie die Quellbilder aus unserer vorherigen Abfrage herunter. In der Klassenkarte für das Landsegmentierungsmodell ist der Klassenindex für Wasser 6.
Um die Wassermaske aus einem zu extrahieren Sentinel-2 Bild, folge diesen Schritten. Zählen Sie zunächst die Anzahl der Pixel, die im Bild als Wasser (Klassenindex 6) markiert sind. Zweitens multiplizieren Sie die Anzahl mit der Fläche, die jedes Pixel abdeckt. Bänder können sich in ihrer räumlichen Auflösung unterscheiden. Für das Modell der Landbedeckungssegmentierung werden alle Bänder auf eine räumliche Auflösung von 60 Metern heruntergerechnet.
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()
Mithilfe von matplotlib
können Sie die Ergebnisse grafisch visualisieren. Die Grafik zeigt, dass die Oberfläche des Sees Mead ist von Januar 2021 bis Juli 2022 gesunken.
