Ce guide explique comment commencer rapidement à envoyer 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 commencer par 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 d'accueil de Colab, puis en saisissant les exemples de code ci-dessous dans une nouvelle cellule de code. Colab est déjà équipé du SDK Cloud. Cela inclut l'outil de ligne de commande gcloud
que vous pouvez utiliser pour gérer les services Cloud. Vous pouvez également exécuter le notebook de démonstration à partir du bouton en haut 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 le script localement, à partir d'une ligne de commande, en supposant que le SDK Cloud est installé :)
PROJECT='my-project' gcloud auth login --project $PROJECT
Acceptez l'option de connexion avec votre compte utilisateur Google et finalisez la procédure 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 fichier 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 permettant d'effectuer des requêtes HTTP. Vous pouvez saisir ce code dans une nouvelle cellule de code de votre notebook Colab. (Si vous utilisez la ligne de commande, vous devrez 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 génère un résultat semblable à celui-ci :
{'id': 'LANDSAT',
'name': 'projects/earthengine-public/assets/LANDSAT',
'type': 'FOLDER'}
Choisir 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 de la page. Plusieurs ensembles de données raster apparaissent :

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 un ensemble de données dans le catalogue de données publiques Earth Engine. Elles comprennent 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 éventuelles restrictions d'utilisation qui peuvent s'appliquer à l'ensemble de données et l'ID de l'ensemble de données dans Earth Engine.
Dans ce cas, nous voyons sur la droite de la fenêtre qu'il s'agit d'un élément de collection d'images dont le chemin est COPERNICUS/S2
.
Requête pour des images spécifiques
Cet ensemble de données Sentinel-2 inclut plus de deux millions d'images couvrant le monde entier de 2015 à aujourd'hui. Exécutons une requête projects.assets.listImages sur la collection d'images pour trouver des données d'avril 2017 avec une faible couverture nuageuse incluant un point spécifique à Mountain View, en Californie.
import urllib coords = [-122.085, 37.422] project = 'projects/earthengine-public' asset_id = 'COPERNICUS/S2' 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 et affiche l'ID de l'élément et la couverture nuageuse pour chaque élément d'image correspondant. Le résultat doit se présenter comme suit :
COPERNICUS/S2/20170420T184921_20170420T190203_T10SEG : 4.3166
COPERNICUS/S2/20170430T190351_20170430T190351_T10SEG : 0
Il y a manifestement deux images au-dessus de ce point qui ont été prises ce mois-ci et qui présentent 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/20170430T190351_20170430T190351_T10SEG
. Notez que tous les composants du catalogue public appartiennent au projet earthengine-public
. Voici un extrait de code Python qui émettra une requête projects.assets.get pour récupérer les détails de cet élément spécifique par ID, imprimer les bandes de données disponibles et imprimer des informations plus détaillées sur la première bande :
asset_id = 'COPERNICUS/S2/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 devrait ressembler à ceci :
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 entières de 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 pixels y
correspond à la diminution des coordonnées spatiales y
(vers le sud).
Récupérer les valeurs de pixel
Exécutons une requête projects.assets.getPixels pour extraire 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 numpy
NPY facilite le décodage de la réponse en 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 à partir 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 ajuster l'emplacement de l'origine dans les coordonnées en pixels, utilisez cette formule simple :
request_origin = image_origin + pixel_scale * offset_in_pixels
Générer une 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 spécifierons 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 vignette RVB attrayante.
En regroupant tout, l'extrait de code Python se présente comme suit (à l'aide du widget d'affichage d'images IPython
de Colab) :
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 l'image miniature obtenue :
