Neste guia, explicamos como começar a emitir consultas para a API REST do Earth Engine em Python usando o Google Colab. Os mesmos conceitos se aplicam ao acesso à API em outras linguagens e ambientes.
Observação: a API REST contém recursos novos e avançados que podem não ser adequados para todos os usuários. Se você não conhece o Earth Engine, comece com o guia de JavaScript.
Antes de começar
Siga estas instruções para:
- Configurar o acesso ao Earth Engine
- Crie uma conta de serviço
Configurar o bloco do Colab
Se você estiver começando este guia de início rápido do zero, crie um notebook do Colab clicando em NOVO NOTEBOOK na página inicial do Colab e insira os exemplos de código abaixo em uma nova célula de código. O Colab já tem o SDK do Cloud instalado. Isso inclui a ferramenta de linha de comando gcloud
que pode ser usada para gerenciar serviços do Cloud. Ou execute o notebook de demonstração usando o botão no início desta página.
Autenticar no Google Cloud
Primeiro, faça login para poder fazer solicitações autenticadas ao Google Cloud.
No Colab, é possível executar:
PROJECT = 'my-project' !gcloud auth login --project {PROJECT}
Ou, se você estiver executando localmente, em uma linha de comando, supondo que o SDK do Cloud esteja instalado:
PROJECT='my-project' gcloud auth login --project $PROJECT
Aceite a opção de fazer login com sua conta de usuário do Google e conclua o processo de login.
Extrair um arquivo de chave privada para sua conta de serviço
Antes de usar a conta de serviço para autenticar, faça o download de um arquivo de chave privada. Para fazer isso no Colab, faça o download para a VM do 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}
Ou, na linha de 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
Como acessar e testar suas credenciais
Agora você pode enviar sua primeira consulta para a API Earth Engine. Use a chave privada para receber credenciais. Use as credenciais para criar uma sessão autorizada e fazer solicitações HTTP. Você pode inserir isso em uma nova célula de código do seu notebook do Colab. Se você estiver usando a linha de comando, verifique se as bibliotecas necessárias estão instaladas.
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 tudo estiver configurado corretamente, a execução desse comando vai gerar uma saída como esta:
{'id': 'LANDSAT',
'name': 'projects/earthengine-public/assets/LANDSAT',
'type': 'FOLDER'}
Escolher um conjunto de dados
É possível pesquisar e explorar os conjuntos de dados disponíveis usando o Editor de código do Earth Engine em code.earthengine.google.com. Vamos procurar alguns dados do Sentinel 2. Se esta for a primeira vez que você usa o Editor de código, será necessário autorizar o acesso ao Earth Engine em seu nome ao fazer login. No editor de código, pesquise "sentinel" na caixa de pesquisa na parte de cima. Vários conjuntos de dados raster aparecem:

Clique em "Sentinel-2: MultiSpectral Instrument (MSI), Level-1C":

As páginas de descrição do conjunto de dados, como esta, incluem as informações essenciais necessárias para usar qualquer conjunto de dados no catálogo público do Earth Engine, incluindo uma breve descrição do conjunto de dados, links para o provedor de dados para mais detalhes, informações sobre restrições de uso que podem se aplicar ao conjunto de dados e o ID do recurso do Earth Engine.
Nesse caso, vemos no lado direito da janela que esse é um recurso de coleção de imagens cujo caminho é COPERNICUS/S2
.
Consultar imagens específicas
Esse conjunto de dados do Sentinel-2 inclui mais de dois milhões de imagens que cobrem o mundo de 2015 até o presente. Vamos emitir uma consulta projects.assets.listImages na coleção de imagens para encontrar alguns dados de abril de 2017 com baixa cobertura de nuvens que incluem um ponto específico em Mountain View, na Califórnia.
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))
Esse script consulta a coleção para encontrar imagens correspondentes, decodifica a resposta JSON resultante e imprime o ID do recurso e a cobertura de nuvens de cada recurso de imagem correspondente. O resultado será semelhante a isso:
COPERNICUS/S2/20170420T184921_20170420T190203_T10SEG : 4.3166
COPERNICUS/S2/20170430T190351_20170430T190351_T10SEG : 0
Há duas imagens sobre esse ponto que foram tiradas neste mês e têm pouca cobertura de nuvens.
Inspecionar uma imagem específica
Parece que uma das correspondências tem essencialmente zero cobertura de nuvens. Vamos analisar mais de perto esse recurso, cujo ID é COPERNICUS/S2/20170430T190351_20170430T190351_T10SEG
. Todos os recursos do catálogo público pertencem ao projeto earthengine-public
. Confira um snippet do Python que vai emitir uma consulta projects.assets.get para buscar os detalhes desse recurso específico por ID, imprimir as bandas de dados disponíveis e informações mais detalhadas sobre a primeira 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))
A resposta será semelhante a esta:
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"
}
A lista de intervalos de dados corresponde ao que vimos antes na descrição do conjunto de dados. É possível ver que esse conjunto de dados tem dados de números inteiros de 16 bits no sistema de coordenadas EPSG:32610, ou UTM Zone 10N. A primeira banda tem o ID B1
e uma resolução de 60 metros por pixel. A origem da imagem está na posição (499980,4200000) nesse sistema de coordenadas.
O valor negativo de affineTransform.scaleY
indica que a origem está no canto noroeste da imagem, como geralmente acontece: o aumento dos índices de pixels y
corresponde à diminuição das coordenadas espaciais y
(indo para o sul).
Buscando valores de pixel
Vamos emitir uma consulta projects.assets.getPixels para buscar alguns dados das bandas de alta resolução dessa imagem. A página de descrição do conjunto de dados diz que as bandas B2
, B3
, B4
e B8
têm uma resolução de 10 metros por pixel. Esse script busca o bloco de 256 x 256 pixels no canto superior esquerdo dos dados dessas quatro bandas. Carregar os dados no formato numpy
NPY facilita a decodificação da resposta em uma matriz de dados do 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)
O resultado será semelhante a este:
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)]]
Para selecionar um conjunto diferente de pixels dessa imagem, basta especificar o affineTransform
de acordo. Lembre-se de que o affineTransform
é especificado no sistema de referência de coordenadas espaciais da imagem. Se quiser ajustar a localização da origem em coordenadas de pixel, use esta fórmula simples:
request_origin = image_origin + pixel_scale * offset_in_pixels
Gerar uma imagem de miniatura
Podemos usar um mecanismo semelhante para gerar uma miniatura RGB dessa imagem. Em vez de solicitar dados na resolução nativa, vamos especificar uma região e dimensões de imagem explicitamente. Para receber uma miniatura da imagem inteira, podemos usar a geometria da área de cobertura da imagem como a região da solicitação. Por fim, especificando as bandas de imagem vermelha, verde e azul e um intervalo adequado de valores de dados, podemos obter uma miniatura RGB atraente.
Juntando tudo isso, o snippet do Python fica assim (usando o widget de exibição de imagens IPython
do 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)
Confira a imagem em miniatura resultante:
