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 avançados novos 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
- Criar uma conta de serviço
Configurar o notebook 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 Cloud instalado. Isso inclui a ferramenta de linha de comando gcloud, que pode ser usada para gerenciar os serviços do Cloud. Como alternativa, execute o notebook de demonstração usando o botão no início desta página.
Autenticar no Google Cloud
A primeira coisa a fazer é o login para que você possa fazer solicitações autenticadas ao Google Cloud.
No Colab, você pode executar:
PROJECT = 'my-project' !gcloud auth login --project {PROJECT}
(Ou, se você estiver executando localmente, em uma linha de comando, supondo que o SDK Cloud esteja instalado:)
PROJECT='my-project' gcloud auth login --project $PROJECT
Aceite a opção de fazer login usando sua conta de usuário do Google e conclua o processo de login.
Gerar um arquivo de chave privada para sua conta de serviço
Antes de usar a conta de serviço para autenticação, 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, como alternativa, 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 para fazer solicitações HTTP. Insira isso em uma nova célula de código do 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 vai produzir 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 sua primeira vez usando o Editor de Código, você precisará 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 rasterizados aparecem:

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

As páginas de descrição de conjuntos de dados como esta incluem as informações essenciais para usar qualquer conjunto de dados no Data Catalog 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 as restrições de uso que podem ser aplicadas ao conjunto de dados e o código do recurso do Earth Engine do conjunto de dados.
Nesse caso, vemos no lado direito da janela que esse é um recurso de coleção de imagens com o caminho COPERNICUS/S2_HARMONIZED.
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 inclua um ponto específico em Mountain View, Califórnia.
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))
Esse script consulta a coleção em busca de imagens correspondentes, decodifica a resposta JSON resultante e imprime o código do recurso e a cobertura de nuvens de cada recurso de imagem correspondente. O resultado será semelhante a isso:
COPERNICUS/S2_HARMONIZED/20170420T184921_20170420T190203_T10SEG : 4.3166
COPERNICUS/S2_HARMONIZED/20170430T190351_20170430T190351_T10SEG : 0
Evidentemente, há duas imagens sobre esse ponto que foram tiradas neste mês e têm baixa cobertura de nuvens.
Inspecionar uma imagem específica
Parece que uma das correspondências tem essencialmente zero cobertura de nuvens. Vamos analisar esse recurso, que tem o ID COPERNICUS/S2_HARMONIZED/20170430T190351_20170430T190351_T10SEG. Todos os recursos do catálogo público pertencem ao projeto earthengine-public. Confira um snippet em Python que emite uma consulta projects.assets.get para buscar os detalhes desse recurso específico por ID, exibir as bandas de dados disponíveis e mostrar informações mais detalhadas sobre a primeira banda:
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))
A saída 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 bandas de dados corresponde ao que vimos anteriormente na descrição do conjunto de dados. Podemos ver que esse conjunto de dados tem dados inteiros de 16 bits no sistema de coordenadas EPSG:32610, ou UTM Zone 10N. Essa 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 pixel y corresponde à diminuição das coordenadas espaciais y (em direção ao 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 informa que as bandas B2, B3, B4 e B8 têm uma resolução de 10 metros por pixel. Esse script busca o bloco de dados de 256 x 256 pixels no canto superior esquerdo dessas quatro bandas. Carregar os dados no formato NPY numpy 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 você quiser ajustar o local da origem em coordenadas de pixel, use esta fórmula simples:
request_origin = image_origin + pixel_scale * offset_in_pixels
Como gerar uma imagem em 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 as dimensões da imagem de forma explícita. Para conseguir uma miniatura da imagem inteira, podemos usar a geometria de pegada da imagem como a região da solicitação. Por fim, ao especificar as bandas de imagem vermelha, verde e azul e um intervalo apropriado de valores de dados, podemos obter uma imagem em miniatura RGB atraente.
Juntando tudo isso, o snippet em 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)
Esta é a imagem de miniatura resultante:
Executar no Google Colab
Ver código-fonte no GitHub