이 가이드에서는 Google Colab을 사용하여 Python에서 Earth Engine REST API에 쿼리를 빠르게 시작하는 방법을 설명합니다. 다른 언어와 환경에서 API에 액세스하는 경우에도 동일한 개념이 적용됩니다.
참고: REST API에는 일부 사용자에게 적합하지 않을 수 있는 새롭고 고급 기능이 포함되어 있습니다. Earth Engine을 처음 사용하는 경우 JavaScript 가이드로 시작하세요.
시작하기 전에
이 안내에 따라 다음 작업을 할 수 있습니다.
Colab 노트북 설정하기
이 빠른 시작을 처음부터 시작하는 경우 Colab 시작 페이지에서 새 노트북을 클릭하여 새 Colab 노트북을 만들고 아래의 코드 샘플을 새 코드 셀에 입력하면 됩니다. Colab에는 Cloud SDK가 이미 설치되어 있습니다. 여기에는 Cloud 서비스를 관리하는 데 사용할 수 있는 gcloud
명령줄 도구가 포함됩니다. 또는 이 페이지 시작 부분에 있는 버튼에서 데모 노트북을 실행합니다.
Google Cloud에 인증
가장 먼저 해야 할 일은 Google Cloud에 인증된 요청을 할 수 있도록 로그인하는 것입니다.
Colab에서는 다음을 실행할 수 있습니다.
PROJECT = 'my-project' !gcloud auth login --project {PROJECT}
(또는 로컬에서 실행하는 경우 Cloud SDK가 설치되어 있다고 가정하고 명령줄에서 실행)
PROJECT='my-project' gcloud auth login --project $PROJECT
Google 사용자 계정을 사용하여 로그인하는 옵션을 수락하고 로그인 절차를 완료합니다.
서비스 계정의 비공개 키 파일 가져오기
서비스 계정을 사용하여 인증하려면 먼저 비공개 키 파일을 다운로드해야 합니다. Colab에서 노트북 VM에 다운로드하려면 다음을 실행하세요.
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}
또는 명령줄에서 다음을 실행합니다.
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
사용자 인증 정보 액세스 및 테스트
이제 Earth Engine API에 첫 번째 쿼리를 보낼 준비가 되었습니다. 비공개 키를 사용하여 사용자 인증 정보를 가져옵니다. 사용자 인증 정보를 사용하여 HTTP 요청을 수행할 승인된 세션을 만듭니다. Colab 노트북의 새 코드 셀에 이를 입력할 수 있습니다. (명령줄을 사용하는 경우 필요한 라이브러리가 설치되어 있는지 확인해야 합니다.)
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))
모든 항목이 올바르게 구성된 경우 이 명령어를 실행하면 다음과 같은 출력이 생성됩니다.
{'id': 'LANDSAT',
'name': 'projects/earthengine-public/assets/LANDSAT',
'type': 'FOLDER'}
데이터 세트 선택
code.earthengine.google.com의 Earth Engine 코드 편집기를 사용하여 사용 가능한 데이터 세트를 검색하고 탐색할 수 있습니다. Sentinel 2 데이터를 찾아보겠습니다. (코드 편집기를 처음 사용하는 경우 로그인할 때 Earth Engine에 액세스할 수 있도록 승인하라는 메시지가 표시됩니다.) 코드 편집기에서 상단의 검색창에 'sentinel'을 검색합니다. 여러 래스터 데이터 세트가 표시됩니다.

'Sentinel-2: MultiSpectral Instrument (MSI), Level-1C'를 클릭합니다.

이 페이지와 같은 데이터 세트 설명 페이지에는 데이터 세트의 간략한 설명, 추가 세부정보를 얻기 위한 데이터 제공업체 링크, 데이터 세트에 적용될 수 있는 사용 제한에 관한 정보, 데이터 세트의 Earth Engine 애셋 ID 등 Earth Engine 공개 데이터 카탈로그에서 데이터 세트를 사용하는 데 필요한 중요한 정보가 포함되어 있습니다.
이 경우 창의 오른쪽에 경로가 COPERNICUS/S2
인 이미지 컬렉션 저작물이 표시됩니다.
특정 이미지 쿼리
이 Sentinel-2 데이터 세트에는 2015년부터 현재까지 전 세계를 대상으로 한 200만 개 이상의 이미지가 포함되어 있습니다. 이미지 컬렉션에 대해 projects.assets.listImages 쿼리를 실행하여 2017년 4월의 데이터 중 캘리포니아주 마운틴뷰의 특정 지점을 포함하고 구름이 적은 데이터를 찾아보겠습니다.
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))
이 스크립트는 컬렉션에서 일치하는 이미지를 쿼리하고, 결과 JSON 응답을 디코딩하고, 일치하는 각 이미지 애셋의 애셋 ID와 운량을 출력합니다. 다음과 같이 출력됩니다.
COPERNICUS/S2/20170420T184921_20170420T190203_T10SEG : 4.3166
COPERNICUS/S2/20170430T190351_20170430T190351_T10SEG : 0
이 지점에는 이번 달에 촬영되었으며 구름이 적은 두 개의 이미지가 있는 것으로 보입니다.
특정 이미지 검사
일치하는 항목 중 하나는 구름이 거의 없는 것으로 보입니다. ID가 COPERNICUS/S2/20170430T190351_20170430T190351_T10SEG
인 애셋을 자세히 살펴보겠습니다. 모든 공개 카탈로그 애셋은 earthengine-public
프로젝트에 속합니다. 다음은 projects.assets.get 쿼리를 실행하여 ID별로 특정 애셋의 세부정보를 가져오고, 사용 가능한 데이터 밴드를 출력하고, 첫 번째 밴드에 관한 자세한 정보를 출력하는 Python 스니펫입니다.
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))
출력은 다음과 같이 표시됩니다.
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"
}
데이터 범위 목록은 앞서 데이터 세트 설명에서 본 내용과 일치합니다. 이 데이터 세트에는 EPSG:32610 좌표계(UTM Zone 10N)의 16비트 정수 데이터가 있습니다. 이 첫 번째 밴드의 ID는 B1
이고 해상도는 픽셀당 60미터입니다. 이미지의 원점은 이 좌표계에서 (499980,4200000) 위치에 있습니다.
affineTransform.scaleY
의 음수 값은 원점이 이미지의 북서쪽 모서리에 있음을 나타냅니다. 이는 일반적으로 그렇습니다. y
픽셀 색인이 증가하면 y
공간 좌표 (남쪽으로 향함)가 감소합니다.
픽셀 값 가져오기
projects.assets.getPixels 쿼리를 실행하여 이 이미지의 고해상도 밴드에서 데이터를 가져옵니다. 데이터 세트 설명 페이지에는 B2
, B3
, B4
, B8
밴드의 해상도가 픽셀당 10미터라고 나와 있습니다. 이 스크립트는 이러한 네 개의 밴드에서 데이터의 왼쪽 상단 256x256 픽셀 타일을 가져옵니다. numpy
NPY 형식으로 데이터를 로드하면 응답을 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)
출력은 다음과 같습니다.
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)]]
이 이미지에서 다른 픽셀 집합을 선택하려면 affineTransform
를 적절하게 지정하면 됩니다. affineTransform
는 이미지의 공간 좌표 참조 시스템에 지정됩니다. 픽셀 좌표에서 원점의 위치를 조정하려면 다음 간단한 공식을 사용하세요.
request_origin = image_origin + pixel_scale * offset_in_pixels
썸네일 이미지 생성
유사한 메커니즘을 사용하여 이 이미지의 RGB 썸네일을 생성할 수 있습니다. 기본 해상도로 데이터를 요청하는 대신 영역과 이미지 크기를 명시적으로 지정합니다. 전체 이미지의 썸네일을 가져오려면 이미지의 설치 공간 형상을 요청 영역으로 사용하면 됩니다. 마지막으로 빨간색, 녹색, 파란색 이미지 밴드와 적절한 데이터 값 범위를 지정하면 보기 좋은 RGB 썸네일 이미지를 얻을 수 있습니다.
이를 종합하면 Python 스니펫은 다음과 같습니다 (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)
결과 썸네일 이미지는 다음과 같습니다.
