Quickstart

Questa guida spiega come iniziare rapidamente a inviare query all'API REST di Earth Engine da Python utilizzando Google Colab. Gli stessi concetti si applicano all'accesso all'API da altri linguaggi e ambienti.

Nota:l'API REST contiene funzionalità nuove e avanzate che potrebbero non essere adatte a tutti gli utenti. Se non hai mai utilizzato Earth Engine, inizia con la guida JavaScript.

Prima di iniziare

Segui queste istruzioni per:

Configurare il notebook di Colab

Se inizi questa guida di avvio rapido da zero, puoi creare un nuovo notebook Colab facendo clic su NUOVO NOTEBOOK dalla pagina iniziale di Colab e inserendo gli esempi di codice riportati di seguito in una nuova cella di codice. Colab ha già installato Cloud SDK. Ciò include lo strumento a riga di comando gcloud, che puoi utilizzare per gestire i servizi cloud. In alternativa, esegui il blocco note demo dal pulsante all'inizio di questa pagina.

Autenticarsi su Google Cloud

La prima cosa da fare è accedere per poter effettuare richieste autenticate a Google Cloud.

In Colab puoi eseguire:

PROJECT = 'my-project'
!gcloud auth login --project {PROJECT}

(o, se esegui l'operazione localmente, da una riga di comando, supponendo che tu abbia installato Cloud SDK:)

PROJECT='my-project'
gcloud auth login --project $PROJECT

Accetta l'opzione di accesso utilizzando il tuo account utente Google e completa la procedura di accesso.

Ottenere un file della chiave privata per il service account

Prima di poter utilizzare il service account per l'autenticazione, devi scaricare un file della chiave privata. Per farlo in Colab, scarica nella VM del 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}

In alternativa, dalla riga di comando:

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

Accedere alle credenziali e testarle

Ora puoi inviare la tua prima query all'API Earth Engine. Utilizza la chiave privata per ottenere le credenziali. Utilizza le credenziali per creare una sessione autorizzata per effettuare richieste HTTP. Puoi inserirlo in una nuova cella di codice del notebook Colab. Se utilizzi la riga di comando, devi assicurarti che le librerie necessarie siano installate.

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))

Se tutto è configurato correttamente, l'esecuzione di questo comando produrrà un output simile al seguente:

{'id': 'LANDSAT',
 'name': 'projects/earthengine-public/assets/LANDSAT',
 'type': 'FOLDER'}

Scegliere un set di dati

Puoi cercare ed esplorare i set di dati disponibili utilizzando Earth Engine Code Editor all'indirizzo code.earthengine.google.com. Cerchiamo alcuni dati di Sentinel 2. Se è la prima volta che utilizzi l'editor di codice, ti verrà chiesto di autorizzarlo ad accedere a Earth Engine per tuo conto quando accedi. Nell'editor di codice, cerca "sentinel" nella casella di ricerca in alto. Vengono visualizzati diversi set di dati raster:

Fai clic su "Sentinel-2: MultiSpectral Instrument (MSI), Level-1C":

Le pagine di descrizione dei set di dati come questa includono le informazioni essenziali necessarie per utilizzare qualsiasi set di dati nel catalogo dei dati pubblici di Earth Engine, tra cui una breve descrizione del set di dati, link al fornitore di dati per ottenere ulteriori dettagli, informazioni su eventuali limitazioni di utilizzo che potrebbero essere applicate al set di dati e l'ID asset Earth Engine del set di dati.

In questo caso, sul lato destro della finestra vediamo che si tratta di un asset di raccolta di immagini il cui percorso è COPERNICUS/S2.

Query per immagini specifiche

Questo set di dati Sentinel-2 include oltre due milioni di immagini che coprono il mondo dal 2015 a oggi. Eseguiamo una query projects.assets.listImages sulla raccolta di immagini per trovare alcuni dati di aprile 2017 con una copertura nuvolosa bassa che includono un punto specifico di Mountain View, in California.

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))

Questo script esegue una query sulla raccolta per trovare le immagini corrispondenti, decodifica la risposta JSON risultante e stampa l'ID risorsa e la copertura nuvolosa per ogni risorsa immagine corrispondente. L'output dovrebbe essere simile al seguente:

COPERNICUS/S2/20170420T184921_20170420T190203_T10SEG : 4.3166
COPERNICUS/S2/20170430T190351_20170430T190351_T10SEG : 0

Evidentemente ci sono due immagini sopra questo punto che sono state scattate in questo mese e hanno una copertura nuvolosa bassa.

Esaminare un'immagine specifica

Sembra che una delle corrispondenze abbia una copertura nuvolosa praticamente nulla. Diamo un'occhiata più da vicino a questo asset, il cui ID è COPERNICUS/S2/20170430T190351_20170430T190351_T10SEG. Tieni presente che tutti gli asset del catalogo pubblico appartengono al progetto earthengine-public. Ecco un snippet Python che eseguirà una query projects.assets.get per recuperare i dettagli di una risorsa specifica in base all'ID, stampare le bande di dati disponibili e stampare informazioni più dettagliate sulla prima banda:

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))

L'output dovrebbe essere simile al seguente:

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"
}

L'elenco delle bande di dati corrisponde a quanto visto in precedenza nella descrizione del set di dati. Possiamo vedere che questo set di dati contiene numeri interi a 16 bit nel sistema di coordinate EPSG:32610 o UTM Zone 10N. Questa prima banda ha l'ID B1 e una risoluzione di 60 metri per pixel. L'origine dell'immagine si trova nella posizione (499980,4200000) in questo sistema di coordinate.

Il valore negativo di affineTransform.scaleY indica che l'origine si trova nell'angolo nord-ovest dell'immagine, come di solito accade: l'aumento degli indici dei pixel y corrisponde alla diminuzione delle coordinate spaziali y (direzione sud).

Recupero dei valori dei pixel

Eseguiamo una query projects.assets.getPixels per recuperare alcuni dati dalle bande ad alta risoluzione di questa immagine. La pagina di descrizione del set di dati indica che le bande B2, B3, B4 e B8 hanno una risoluzione di 10 metri per pixel. Questo script recupera il riquadro di dati 256 x 256 pixel in alto a sinistra da queste quattro bande. Il caricamento dei dati nel formato numpy NPY semplifica la decodifica della risposta in un array di dati 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)

L'output dovrebbe essere simile al seguente:

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)]]

Per selezionare un insieme diverso di pixel da questa immagine, specifica semplicemente affineTransform di conseguenza. Ricorda che affineTransform è specificato nel sistema di riferimento delle coordinate spaziali dell'immagine. Se vuoi regolare la posizione dell'origine nelle coordinate pixel, utilizza questa semplice formula:

request_origin = image_origin + pixel_scale * offset_in_pixels

Generare un'immagine in miniatura

Possiamo utilizzare un meccanismo simile per generare una miniatura RGB di questa immagine. Anziché richiedere i dati alla risoluzione nativa, specificheremo esplicitamente una regione e le dimensioni dell'immagine. Per ottenere una miniatura dell'intera immagine, possiamo utilizzare la geometria dell'impronta dell'immagine come regione della richiesta. Infine, specificando le bande dell'immagine rossa, verde e blu e un intervallo appropriato di valori dei dati, possiamo ottenere un'accattivante immagine miniatura RGB.

Mettendo insieme tutto questo, lo snippet Python ha questo aspetto (utilizzando il widget di visualizzazione delle immagini IPython di 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)

Ecco l'immagine in miniatura risultante: