Les traductions sont fournies par des outils de traduction automatique. En cas de conflit entre le contenu d'une traduction et celui de la version originale en anglais, la version anglaise prévaudra.
Utilisation ScriptProcessor
pour calculer l'indice de végétation différentiel normalisé (NDVI) en utilisant Sentinel-2 données satellitaires
Les exemples de code suivants vous montrent comment calculer l'indice de végétation différentiel normalisé d'une zone géographique spécifique à l'aide de l'image géospatiale spécialement conçue dans un bloc-notes Studio Classic et comment exécuter une charge de travail à grande échelle avec Amazon Processing à SageMaker l'aide de Python. ScriptProcessor
Cette démonstration utilise également une instance de bloc-notes Amazon SageMaker Studio Classic qui utilise le noyau géospatial et le type d'instance. Pour savoir comment créer une instance de bloc-notes géospatial Studio Classic, consultezCréation d'un bloc-notes Amazon SageMaker Studio Classic à l'aide de l'image géospatiale.
Vous pouvez suivre cette démonstration dans votre propre instance de bloc-notes en copiant et en collant les extraits de code suivants :
Interrogez le Sentinel-2 collecte de données matricielles à l'aide SearchRasterDataCollection
search_raster_data_collection
Vous pouvez ainsi interroger les collections de données raster prises en charge. Cet exemple utilise des données extraites de Sentinel-2 satellites. La zone d'intérêt (AreaOfInterest
) spécifiée est la zone rurale du nord de l'Iowa, et la période (TimeRangeFilter
) va du 1er janvier 2022 au 30 décembre 2022. Pour voir les collections de données raster disponibles que vous Région AWS utilisezlist_raster_data_collections
. Pour voir un exemple de code utilisant ce codeAPI, consultez ListRasterDataCollectionsle manuel Amazon SageMaker Developer Guide.
Dans les exemples de code suivants, vous utilisez le code ARN associé à Sentinel-2 collecte de données matricielles,arn:aws:sagemaker-geospatial:us-west-2:378778860802:raster-data-collection/public/nmqj48dcu3g7ayw8
.
Une search_raster_data_collection
API demande nécessite deux paramètres :
-
Vous devez spécifier un
Arn
paramètre correspondant à la collection de données raster que vous souhaitez interroger. -
Vous devez également spécifier un
RasterDataCollectionQuery
paramètre, qui prend en compte un Python dictionnaire.
L'exemple de code suivant contient les paires clé-valeur nécessaires pour le RasterDataCollectionQuery
paramètre enregistré dans la search_rdc_query
variable.
search_rdc_query = { "AreaOfInterest": { "AreaOfInterestGeometry": { "PolygonGeometry": { "Coordinates": [[ [ -94.50938680498298, 43.22487436936203 ], [ -94.50938680498298, 42.843474642037194 ], [ -93.86520004156142, 42.843474642037194 ], [ -93.86520004156142, 43.22487436936203 ], [ -94.50938680498298, 43.22487436936203 ] ]] } } }, "TimeRangeFilter": {"StartTime": "2022-01-01T00:00:00Z", "EndTime": "2022-12-30T23:59:59Z"} }
Pour faire la search_raster_data_collection
demande, vous devez spécifier le ARN Sentinel-2 collecte de données matricielles :arn:aws:sagemaker-geospatial:us-west-2:378778860802:raster-data-collection/public/nmqj48dcu3g7ayw8
. Vous devez également transmettre le dictionnaire Python défini précédemment, qui spécifie les paramètres de requête.
## Creates a SageMaker Geospatial client instance sm_geo_client= session.create_client(service_name="sagemaker-geospatial") search_rdc_response1 = 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 )
Les résultats ne API peuvent pas être paginés. Pour collecter toutes les images satellites renvoyées par l'search_raster_data_collection
opération, vous pouvez implémenter une while
boucle. Cela vérifie NextToken
dans la API réponse :
## Holds the list of API responses from search_raster_data_collection items_list = [] while search_rdc_response1.get('NextToken') and search_rdc_response1['NextToken'] != None: items_list.extend(search_rdc_response1['Items']) search_rdc_response1 = 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_response1['NextToken'] )
La API réponse renvoie une liste de URLs Assets
sous-touches correspondant à des bandes d'image spécifiques. Voici une version tronquée de la API réponse. Certaines bandes d'image ont été supprimées pour des raisons de clarté.
{ 'Assets': { 'aot': { 'Href': 'https://sentinel-cogs.s3.us-west-2.amazonaws.com/sentinel-s2-l2a-cogs/15/T/UH/2022/12/S2A_15TUH_20221230_0_L2A/AOT.tif' }, 'blue': { 'Href': 'https://sentinel-cogs.s3.us-west-2.amazonaws.com/sentinel-s2-l2a-cogs/15/T/UH/2022/12/S2A_15TUH_20221230_0_L2A/B02.tif' }, 'swir22-jp2': { 'Href': 's3://sentinel-s2-l2a/tiles/15/T/UH/2022/12/30/0/B12.jp2' }, 'visual-jp2': { 'Href': 's3://sentinel-s2-l2a/tiles/15/T/UH/2022/12/30/0/TCI.jp2' }, 'wvp-jp2': { 'Href': 's3://sentinel-s2-l2a/tiles/15/T/UH/2022/12/30/0/WVP.jp2' } }, 'DateTime': datetime.datetime(2022, 12, 30, 17, 21, 52, 469000, tzinfo = tzlocal()), 'Geometry': { 'Coordinates': [ [ [-95.46676936182894, 43.32623760511659], [-94.11293433656887, 43.347431265475954], [-94.09532154452742, 42.35884880571144], [-95.42776890002203, 42.3383710796791], [-95.46676936182894, 43.32623760511659] ] ], 'Type': 'Polygon' }, 'Id': 'S2A_15TUH_20221230_0_L2A', 'Properties': { 'EoCloudCover': 62.384969, 'Platform': 'sentinel-2a' } }
Dans la section suivante, vous allez créer un fichier manifeste à l'aide de la 'Id'
clé de la API réponse.
Créez un fichier manifeste d'entrée à l'aide de la Id
clé de la search_raster_data_collection
API réponse
Lorsque vous exécutez une tâche de traitement, vous devez spécifier une entrée de données provenant d'Amazon S3. Le type de données d'entrée peut être un fichier manifeste, qui pointe ensuite vers les fichiers de données individuels. Vous pouvez également ajouter un préfixe à chaque fichier que vous souhaitez traiter. L'exemple de code suivant définit le dossier dans lequel vos fichiers manifestes seront générés.
Utilisez SDK for Python (Boto3) pour obtenir le bucket par défaut et le rôle ARN d'exécution associés à votre instance de bloc-notes Studio Classic :
sm_session = sagemaker.session.Session() s3 = boto3.resource('s3') # Gets the default excution role associated with the notebook execution_role_arn = sagemaker.get_execution_role() # Gets the default bucket associated with the notebook s3_bucket = sm_session.default_bucket() # Can be replaced with any name s3_folder =
"script-processor-input-manifest"
Ensuite, vous créez un fichier manifeste. Il contiendra les URLs images satellites que vous souhaitez traiter lorsque vous exécuterez votre tâche de traitement ultérieurement à l'étape 4.
# Format of a manifest file manifest_prefix = {} manifest_prefix['prefix'] = 's3://' + s3_bucket + '/' + s3_folder + '/' manifest = [manifest_prefix] print(manifest)
L'exemple de code suivant renvoie le S3 URI dans lequel vos fichiers manifestes seront créés.
[{'prefix': 's3://sagemaker-us-west-2-111122223333/script-processor-input-manifest/'}]
Tous les éléments de réponse de la réponse search_raster_data_collection ne sont pas nécessaires pour exécuter la tâche de traitement.
L'extrait de code suivant supprime les éléments inutiles 'Properties'
'Geometry'
, et. 'DateTime'
La paire 'Id'
clé-valeur contient 'Id': 'S2A_15TUH_20221230_0_L2A'
l'année et le mois. L'exemple de code suivant analyse ces données pour créer de nouvelles clés dans Python dictionnairedict_month_items
. Les valeurs sont les actifs renvoyés par la SearchRasterDataCollection
requête.
# For each response get the month and year, and then remove the metadata not related to the satelite images. dict_month_items = {} for item in items_list: # Example ID being split: 'S2A_15TUH_20221230_0_L2A' yyyymm = item['Id'].split("_")[2][:6] if yyyymm not in dict_month_items: dict_month_items[yyyymm] = [] # Removes uneeded metadata elements for this demo item.pop('Properties', None) item.pop('Geometry', None) item.pop('DateTime', None) # Appends the response from search_raster_data_collection to newly created key above dict_month_items[yyyymm].append(item)
Cet exemple de code télécharge le dict_month_items
vers Amazon S3 en tant qu'JSONobjet à l'aide de l'.upload_file()
## key_ is the yyyymm timestamp formatted above ## value_ is the reference to all the satellite images collected via our searchRDC query for key_, value_ in dict_month_items.items(): filename = f'manifest_{key_}.json' with open(filename, 'w') as fp: json.dump(value_, fp) s3.meta.client.upload_file(filename, s3_bucket, s3_folder + '/' + filename) manifest.append(filename) os.remove(filename)
Cet exemple de code télécharge un manifest.json
fichier parent qui pointe vers tous les autres manifestes chargés sur Amazon S3. Il enregistre également le chemin d'une variable locale :s3_manifest_uri
. Vous utiliserez à nouveau cette variable pour spécifier la source des données d'entrée lorsque vous exécuterez la tâche de traitement à l'étape 4.
with open('manifest.json', 'w') as fp: json.dump(manifest, fp) s3.meta.client.upload_file('manifest.json', s3_bucket, s3_folder + '/' + 'manifest.json') os.remove('manifest.json') s3_manifest_uri = f's3://{s3_bucket}/{s3_folder}/manifest.json'
Maintenant que vous avez créé les fichiers manifestes d'entrée et que vous les avez téléchargés, vous pouvez écrire un script qui traite vos données dans le cadre de la tâche de traitement. Il traite les données des images satellites, les calculeNDVI, puis renvoie les résultats vers un autre emplacement Amazon S3.
Écrivez un script qui calcule le NDVI
Amazon SageMaker Studio Classic prend en charge l'utilisation de la commande %%writefile
cell magic. Après avoir exécuté une cellule avec cette commande, son contenu sera enregistré dans votre répertoire Studio Classic local. Il s'agit d'un code spécifique au calculNDVI. Toutefois, les éléments suivants peuvent être utiles lorsque vous écrivez votre propre script pour une tâche de traitement :
-
Dans votre conteneur de tâches de traitement, les chemins locaux à l'intérieur du conteneur doivent commencer par
/opt/ml/processing/
. Dans cet exemple,input_data_path = '/opt/ml/processing/input_data/'
etprocessed_data_path = '/opt/ml/processing/output_data/'
sont spécifiés de cette manière. -
Avec Amazon SageMaker Processing, un script exécuté par une tâche de traitement peut télécharger vos données traitées directement sur Amazon S3. Pour ce faire, assurez-vous que le rôle d'exécution associé à votre
ScriptProcessor
instance possède les conditions requises pour accéder au compartiment S3. Vous pouvez également spécifier un paramètre de sortie lorsque vous exécutez votre tâche de traitement. Pour en savoir plus, consultez le.run()
APIfonctionnementdans Amazon SageMaker Python SDK. Dans cet exemple de code, les résultats du traitement des données sont chargés directement sur Amazon S3. -
Pour gérer la taille de l'Amazon EBScontainer associé à votre tâche de traitement, utilisez le
volume_size_in_gb
paramètre. La taille par défaut des conteneurs est de 30 Go. Vous pouvez également éventuellement utiliser la bibliothèque Python Garbage Collectorpour gérer le stockage dans votre EBS conteneur Amazon. L'exemple de code suivant charge les tableaux dans le conteneur de tâches de traitement. Lorsque les tableaux s'accumulent et remplissent la mémoire, la tâche de traitement se bloque. Pour éviter ce crash, l'exemple suivant contient des commandes qui suppriment les tableaux du conteneur de la tâche de traitement.
%%writefile compute_ndvi.py import os import pickle import sys import subprocess import json import rioxarray if __name__ == "__main__": print("Starting processing") input_data_path = '/opt/ml/processing/input_data/' input_files = [] for current_path, sub_dirs, files in os.walk(input_data_path): for file in files: if file.endswith(".json"): input_files.append(os.path.join(current_path, file)) print("Received {} input_files: {}".format(len(input_files), input_files)) items = [] for input_file in input_files: full_file_path = os.path.join(input_data_path, input_file) print(full_file_path) with open(full_file_path, 'r') as f: items.append(json.load(f)) items = [item for sub_items in items for item in sub_items] for item in items: red_uri = item["Assets"]["red"]["Href"] nir_uri = item["Assets"]["nir"]["Href"] red = rioxarray.open_rasterio(red_uri, masked=True) nir = rioxarray.open_rasterio(nir_uri, masked=True) ndvi = (nir - red)/ (nir + red) file_name = 'ndvi_' + item["Id"] + '.tif' output_path = '/opt/ml/processing/output_data' output_file_path = f"{output_path}/{file_name}" ndvi.rio.to_raster(output_file_path) print("Written output:", output_file_path)
Vous disposez à présent d'un script qui permet de calculer leNDVI. Ensuite, vous pouvez créer une instance de la tâche de traitement ScriptProcessor et exécuter votre tâche de traitement.
Création d'une instance de la ScriptProcessor
classe
Cette démo utilise la ScriptProcessor.run()
méthode.
from sagemaker.processing import ScriptProcessor, ProcessingInput, ProcessingOutput image_uri =
'081189585635.dkr.ecr.us-west-2.amazonaws.com/sagemaker-geospatial-v1-0:latest'
processor = ScriptProcessor( command=['python3'], image_uri=image_uri, role=execution_role_arn, instance_count=4, instance_type='ml.m5.4xlarge', sagemaker_session=sm_session ) print('Starting processing job.')
Lorsque vous démarrez votre tâche de traitement, vous devez spécifier un ProcessingInput
-
Le chemin d'accès au fichier manifeste que vous avez créé à l'étape 2,
s3_manifest_uri
. Il s'agit de la source des données d'entrée du conteneur. -
Le chemin vers lequel vous souhaitez que les données d'entrée soient enregistrées dans le conteneur. Il doit correspondre au chemin que vous avez indiqué dans votre script.
-
Utilisez le
s3_data_type
paramètre pour spécifier l'entrée sous la forme"ManifestFile"
.
s3_output_prefix_url = f"s3://{s3_bucket}/{s3_folder}/output" processor.run( code='compute_ndvi.py', inputs=[ ProcessingInput( source=s3_manifest_uri, destination='/opt/ml/processing/input_data/', s3_data_type="ManifestFile", s3_data_distribution_type="ShardedByS3Key" ), ], outputs=[ ProcessingOutput( source='/opt/ml/processing/output_data/', destination=s3_output_prefix_url, s3_upload_mode="Continuous" ) ] )
L'exemple de code suivant utilise la .describe()
méthode
preprocessing_job_descriptor = processor.jobs[-1].describe() s3_output_uri = preprocessing_job_descriptor["ProcessingOutputConfig"]["Outputs"][0]["S3Output"]["S3Uri"] print(s3_output_uri)
Visualisez vos résultats à l'aide de matplotlib
Avec la bibliothèque Python Matplotlib.open_rasterio()
APIopération, puis calcule le résultat NDVI en utilisant les bandes d'red
image nir
et à partir du Sentinel-2 données satellitaires.
# Opens the python arrays import rioxarray red_uri = items[25]["Assets"]["red"]["Href"] nir_uri = items[25]["Assets"]["nir"]["Href"] red = rioxarray.open_rasterio(red_uri, masked=True) nir = rioxarray.open_rasterio(nir_uri, masked=True) # Calculates the NDVI ndvi = (nir - red)/ (nir + red) # Common plotting library in Python import matplotlib.pyplot as plt f, ax = plt.subplots(figsize=(18, 18)) ndvi.plot(cmap='viridis', ax=ax) ax.set_title("NDVI for {}".format(items[25]["Id"])) ax.set_axis_off() plt.show()
La sortie de l'exemple de code précédent est une image satellite sur laquelle les NDVI valeurs sont superposées. Une NDVI valeur proche de 1 indique la présence d'une grande quantité de végétation, et des valeurs proches de 0 indiquent qu'aucune végétation n'est présentée.
Ceci termine la démonstration d'utilisationScriptProcessor
.