Ce guide explique comment envoyer rapidement des requêtes à l'API REST Earth Engine depuis Python à l'aide de Google Colab. Les mêmes concepts s'appliquent à l'accès à l'API à partir d'autres langages et environnements.
Remarque : L'API REST contient des fonctionnalités nouvelles et avancées qui peuvent ne pas convenir à tous les utilisateurs. Si vous débutez avec Earth Engine, veuillez consulter le guide JavaScript.
Avant de commencer
Suivez ces instructions pour :
- Configurer l'accès à Earth Engine
- Créer un compte de service
Configurer votre notebook Colab
Si vous commencez ce guide de démarrage rapide à partir de zéro, vous pouvez créer un notebook Colab en cliquant sur NOUVEAU NOTEBOOK sur la page de démarrage de Colab, puis saisir les exemples de code ci-dessous dans une nouvelle cellule de code. Le SDK Cloud est déjà installé dans Colab. Cela inclut l'outil de ligne de commande gcloud, qui vous permet de gérer les services cloud. Vous pouvez également exécuter le notebook de démonstration à l'aide du bouton situé au début de cette page.
S'authentifier sur Google Cloud
La première chose à faire est de vous connecter pour pouvoir envoyer des requêtes authentifiées à Google Cloud.
Dans Colab, vous pouvez exécuter :
PROJECT = 'my-project' !gcloud auth login --project {PROJECT}
(ou si vous exécutez l'application localement, à partir d'une ligne de commande, en supposant que vous avez installé le Cloud SDK) :
PROJECT='my-project' gcloud auth login --project $PROJECT
Acceptez l'option de connexion à l'aide de votre compte utilisateur Google et terminez le processus de connexion.
Obtenir un fichier de clé privée pour votre compte de service
Avant de pouvoir utiliser le compte de service pour l'authentification, vous devez télécharger un fichier de clé privée. Pour ce faire dans Colab, téléchargez-le sur la VM du notebook :
SERVICE_ACCOUNT='foo-name@project-name.iam.gserviceaccount.com' KEY = 'my-secret-key.json' !gcloud iam service-accounts keys create {KEY} --iam-account {SERVICE_ACCOUNT}
Vous pouvez également utiliser la ligne de commande :
SERVICE_ACCOUNT='foo-name@project-name.iam.gserviceaccount.com' KEY='my-secret-key.json' gcloud iam service-accounts keys create $KEY --iam-account $SERVICE_ACCOUNT
Accéder à vos identifiants et les tester
Vous êtes maintenant prêt à envoyer votre première requête à l'API Earth Engine. Utilisez la clé privée pour obtenir des identifiants. Utilisez les identifiants pour créer une session autorisée afin d'effectuer des requêtes HTTP. Vous pouvez le saisir dans une nouvelle cellule de code de votre notebook Colab. (Si vous utilisez la ligne de commande, vous devez vous assurer que les bibliothèques nécessaires sont installées.)
from google.auth.transport.requests import AuthorizedSession from google.oauth2 import service_account credentials = service_account.Credentials.from_service_account_file(KEY) scoped_credentials = credentials.with_scopes( ['https://www.googleapis.com/auth/cloud-platform']) session = AuthorizedSession(scoped_credentials) url = 'https://earthengine.googleapis.com/v1alpha/projects/earthengine-public/assets/LANDSAT' response = session.get(url) from pprint import pprint import json pprint(json.loads(response.content))
Si tout est correctement configuré, l'exécution de cette commande produira un résultat semblable à celui-ci :
{'id': 'LANDSAT',
'name': 'projects/earthengine-public/assets/LANDSAT',
'type': 'FOLDER'}
Sélectionner un ensemble de données
Vous pouvez rechercher et explorer les ensembles de données disponibles à l'aide de l'éditeur de code Earth Engine sur code.earthengine.google.com. Recherchons des données Sentinel 2. (Si vous utilisez l'éditeur de code pour la première fois, vous serez invité à l'autoriser à accéder à Earth Engine en votre nom lorsque vous vous connecterez.) Dans l'éditeur de code, recherchez "sentinel" dans le champ de recherche en haut. Plusieurs ensembles de données matricielles s'affichent :

Cliquez sur "Sentinel-2: MultiSpectral Instrument (MSI), Level-1C" :

Les pages de description des ensembles de données comme celle-ci incluent les informations essentielles dont vous avez besoin pour utiliser n'importe quel ensemble de données du Data Catalog public Earth Engine, y compris une brève description de l'ensemble de données, des liens vers le fournisseur de données pour obtenir des informations supplémentaires, des informations sur les restrictions d'utilisation qui peuvent s'appliquer à l'ensemble de données et l'ID d'élément Earth Engine de l'ensemble de données.
Dans ce cas, nous voyons sur le côté droit de la fenêtre qu'il s'agit d'un composant de collection d'images dont le chemin d'accès est COPERNICUS/S2_HARMONIZED.
Interroger des images spécifiques
Cet ensemble de données Sentinel-2 comprend plus de deux millions d'images couvrant le monde entier de 2015 à aujourd'hui. Émettons une requête projects.assets.listImages sur la collection d'images pour trouver des données d'avril 2017, avec une faible couverture nuageuse, qui incluent un point particulier à Mountain View, en Californie.
import urllib coords = [-122.085, 37.422] project = 'projects/earthengine-public' asset_id = 'COPERNICUS/S2_HARMONIZED' name = '{}/assets/{}'.format(project, asset_id) url = 'https://earthengine.googleapis.com/v1alpha/{}:listImages?{}'.format( name, urllib.parse.urlencode({ 'startTime': '2017-04-01T00:00:00.000Z', 'endTime': '2017-05-01T00:00:00.000Z', 'region': '{"type":"Point", "coordinates":' + str(coords) + '}', 'filter': 'CLOUDY_PIXEL_PERCENTAGE < 10', })) response = session.get(url) content = response.content for asset in json.loads(content)['images']: id = asset['id'] cloud_cover = asset['properties']['CLOUDY_PIXEL_PERCENTAGE'] print('%s : %s' % (id, cloud_cover))
Ce script interroge la collection pour trouver les images correspondantes, décode la réponse JSON obtenue, puis affiche l'ID d'élément et la couverture nuageuse pour chaque élément d'image correspondant. Le résultat doit se présenter comme suit :
COPERNICUS/S2_HARMONIZED/20170420T184921_20170420T190203_T10SEG : 4.3166
COPERNICUS/S2_HARMONIZED/20170430T190351_20170430T190351_T10SEG : 0
Il existe deux images de ce point prises ce mois-ci et présentant une faible couverture nuageuse.
Inspecter une image spécifique
Il semble que l'une des correspondances ne présente pratiquement aucune couverture nuageuse. Examinons de plus près cet asset, dont l'ID est COPERNICUS/S2_HARMONIZED/20170430T190351_20170430T190351_T10SEG. Notez que tous les éléments du catalogue public appartiennent au projet earthengine-public. Voici un extrait de code Python qui émet une requête projects.assets.get pour récupérer les détails de cet asset spécifique par ID, afficher les bandes de données disponibles et afficher des informations plus détaillées sur la première bande :
asset_id = 'COPERNICUS/S2_HARMONIZED/20170430T190351_20170430T190351_T10SEG' name = '{}/assets/{}'.format(project, asset_id) url = 'https://earthengine.googleapis.com/v1alpha/{}'.format(name) response = session.get(url) content = response.content asset = json.loads(content) print('Band Names: %s' % ','.join(band['id'] for band in asset['bands'])) print('First Band: %s' % json.dumps(asset['bands'][0], indent=2, sort_keys=True))
Le résultat doit se présenter comme suit :
Band Names: B1,B2,B3,B4,B5,B6,B7,B8,B8A,B9,B10,B11,B12,QA10,QA20,QA60
First Band: {
"dataType": {
"precision": "INTEGER",
"range": {
"max": 65535
}
},
"grid": {
"affineTransform": {
"scaleX": 60,
"scaleY": -60,
"translateX": 499980,
"translateY": 4200000
},
"crsCode": "EPSG:32610",
"dimensions": {
"height": 1830,
"width": 1830
}
},
"id": "B1",
"pyramidingPolicy": "MEAN"
}
La liste des bandes de données correspond à ce que nous avons vu précédemment dans la description de l'ensemble de données. Nous pouvons voir que cet ensemble de données contient des données d'entiers 16 bits dans le système de coordonnées EPSG:32610, ou UTM Zone 10N. Cette première bande a l'ID B1 et une résolution de 60 mètres par pixel. L'origine de l'image se trouve à la position (499980,4200000) dans ce système de coordonnées.
La valeur négative de affineTransform.scaleY indique que l'origine se trouve dans l'angle nord-ouest de l'image, comme c'est généralement le cas : l'augmentation des indices de pixel y correspond à la diminution des coordonnées spatiales y (vers le sud).
Récupération des valeurs de pixel…
Émettons une requête projects.assets.getPixels pour récupérer des données des bandes haute résolution de cette image. La page de description de l'ensemble de données indique que les bandes B2, B3, B4 et B8 ont une résolution de 10 mètres par pixel. Ce script récupère la tuile de données de 256 x 256 pixels en haut à gauche de ces quatre bandes. Le chargement des données au format NPY numpy facilite le décodage de la réponse dans un tableau de données Python.
import numpy import io name = '{}/assets/{}'.format(project, asset_id) url = 'https://earthengine.googleapis.com/v1alpha/{}:getPixels'.format(name) body = json.dumps({ 'fileFormat': 'NPY', 'bandIds': ['B2', 'B3', 'B4', 'B8'], 'grid': { 'affineTransform': { 'scaleX': 10, 'scaleY': -10, 'translateX': 499980, 'translateY': 4200000, }, 'dimensions': {'width': 256, 'height': 256}, }, }) pixels_response = session.post(url, body) pixels_content = pixels_response.content array = numpy.load(io.BytesIO(pixels_content)) print('Shape: %s' % (array.shape,)) print('Data:') print(array)
Le résultat doit se présenter comme suit :
Shape: (256, 256)
Data:
[[( 899, 586, 351, 189) ( 918, 630, 501, 248) (1013, 773, 654, 378) ...,
(1014, 690, 419, 323) ( 942, 657, 424, 260) ( 987, 691, 431, 315)]
[( 902, 630, 541, 227) (1059, 866, 719, 429) (1195, 922, 626, 539) ...,
( 978, 659, 404, 287) ( 954, 672, 426, 279) ( 990, 678, 397, 304)]
[(1050, 855, 721, 419) (1257, 977, 635, 569) (1137, 770, 400, 435) ...,
( 972, 674, 421, 312) (1001, 688, 431, 311) (1004, 659, 378, 284)]
...,
[( 969, 672, 375, 275) ( 927, 680, 478, 294) (1018, 724, 455, 353) ...,
( 924, 659, 375, 232) ( 921, 664, 438, 273) ( 966, 737, 521, 306)]
[( 920, 645, 391, 248) ( 979, 728, 481, 327) ( 997, 708, 425, 324) ...,
( 927, 673, 387, 243) ( 927, 688, 459, 284) ( 962, 732, 509, 331)]
[( 978, 723, 449, 330) (1005, 712, 446, 314) ( 946, 667, 393, 269) ...,
( 949, 692, 413, 271) ( 927, 689, 472, 285) ( 966, 742, 516, 331)]]
Pour sélectionner un autre ensemble de pixels de cette image, il vous suffit de spécifier le affineTransform en conséquence. N'oubliez pas que affineTransform est spécifié dans le système de référence des coordonnées spatiales de l'image. Si vous souhaitez plutôt ajuster l'emplacement de l'origine en coordonnées de pixel, utilisez cette formule simple :
request_origin = image_origin + pixel_scale * offset_in_pixels
Générer une image miniature
Nous pouvons utiliser un mécanisme similaire pour générer une miniature RVB de cette image. Au lieu de demander des données à leur résolution native, nous allons spécifier explicitement une région et des dimensions d'image. Pour obtenir une miniature de l'image entière, nous pouvons utiliser la géométrie de l'empreinte de l'image comme région de la requête. Enfin, en spécifiant les bandes d'image rouge, verte et bleue, ainsi qu'une plage de valeurs de données appropriée, nous pouvons obtenir une image miniature RVB attrayante.
En résumé, l'extrait de code Python se présente comme suit (à l'aide du widget d'affichage d'images Colab IPython) :
url = 'https://earthengine.googleapis.com/v1alpha/{}:getPixels'.format(name) body = json.dumps({ 'fileFormat': 'PNG', 'bandIds': ['B4', 'B3', 'B2'], 'region': asset['geometry'], 'grid': { 'dimensions': {'width': 256, 'height': 256}, }, 'visualizationOptions': { 'ranges': [{'min': 0, 'max': 3000}], }, }) image_response = session.post(url, body) image_content = image_response.content from IPython.display import Image Image(image_content)
Voici la miniature obtenue :
Exécuter dans Google Colab
Afficher la source sur GitHub