คู่มือนี้อธิบายวิธีเริ่มต้นใช้งานการออกคําค้นหาไปยัง Earth Engine REST API จาก Python โดยใช้ Google Colab อย่างรวดเร็ว แนวคิดเดียวกันนี้ใช้ได้กับการเข้าถึง API จากภาษาและสภาพแวดล้อมอื่นๆ ด้วย
หมายเหตุ: REST API มีฟีเจอร์ใหม่และขั้นสูงที่อาจไม่เหมาะกับผู้ใช้บางราย หากคุณเพิ่งเริ่มใช้ Earth Engine โปรดเริ่มต้นด้วยคู่มือ JavaScript
ก่อนเริ่มต้น
ทำตามวิธีการเหล่านี้เพื่อ
ตั้งค่า Colab Notebook
หากคุณเริ่มต้นคู่มือฉบับย่อนี้ตั้งแต่ต้น คุณสามารถสร้างสมุดบันทึก Colab ใหม่ได้โดยคลิกสมุดบันทึกใหม่จากหน้าเริ่มต้นของ Colab แล้วป้อนตัวอย่างโค้ดด้านล่างลงในโค้ดเซลล์ใหม่ Colab ติดตั้ง Cloud SDK ไว้แล้ว ซึ่งรวมถึง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 Notebook ได้ (หากใช้บรรทัดคำสั่ง คุณจะต้องตรวจสอบว่าได้ติดตั้งไลบรารีที่จำเป็นแล้ว)
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'}
เลือกชุดข้อมูล
คุณค้นหาและสำรวจชุดข้อมูลที่มีอยู่ได้โดยใช้ Earth Engine Code Editor ที่ code.earthengine.google.com มาดูข้อมูล Sentinel 2 กัน (หากใช้โปรแกรมแก้ไขโค้ดเป็นครั้งแรก ระบบจะแจ้งให้คุณให้สิทธิ์เข้าถึง Earth Engine ในนามของคุณเมื่อคุณลงชื่อเข้าใช้) ในเครื่องมือแก้ไขโค้ด ให้ค้นหา "sentinel" ในช่องค้นหาที่ด้านบน ชุดข้อมูลแรสเตอร์หลายชุดจะปรากฏขึ้น

คลิก "Sentinel-2: MultiSpectral Instrument (MSI), Level-1C"

หน้าคำอธิบายชุดข้อมูลเช่นหน้านี้มีข้อมูลสำคัญที่คุณต้องใช้เพื่อใช้ชุดข้อมูลในแคตตาล็อกข้อมูลสาธารณะของ Earth Engine ซึ่งรวมถึงคำอธิบายสั้นๆ ของชุดข้อมูล ลิงก์ไปยังผู้ให้บริการข้อมูลเพื่อดูรายละเอียดเพิ่มเติม ข้อมูลเกี่ยวกับการจำกัดการใช้งานที่อาจมีผลกับชุดข้อมูล และรหัสชิ้นงาน Earth Engine ของชุดข้อมูล
ในกรณีนี้ เราจะเห็นทางด้านขวาของหน้าต่างว่านี่คือชิ้นงานคอลเล็กชันรูปภาพที่มีเส้นทางเป็น COPERNICUS/S2
ค้นหารูปภาพที่เฉพาะเจาะจง
ชุดข้อมูล Sentinel-2 มีรูปภาพกว่า 2 ล้านรูปที่ครอบคลุมทั่วโลกตั้งแต่ปี 2015 จนถึงปัจจุบัน มาออกคำค้นหา projects.assets.listImages กับคอลเล็กชันรูปภาพเพื่อค้นหาข้อมูลบางอย่างจากเดือนเมษายน 2017 ที่มีเมฆปกคลุมต่ำซึ่งรวมถึงจุดหนึ่งในเมาน์เทนวิว แคลิฟอร์เนีย
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 ที่ได้ และพิมพ์รหัสชิ้นงานและปริมาณเมฆปกคลุมสำหรับชิ้นงานรูปภาพที่ตรงกันแต่ละรายการ เอาต์พุตควรมีลักษณะดังนี้
COPERNICUS/S2/20170420T184921_20170420T190203_T10SEG : 4.3166
COPERNICUS/S2/20170430T190351_20170430T190351_T10SEG : 0
เห็นได้ชัดว่ามีรูปภาพ 2 รูปเหนือจุดนี้ซึ่งถ่ายในเดือนนี้และมีเมฆปกคลุมต่ำ
ตรวจสอบรูปภาพที่เฉพาะเจาะจง
ดูเหมือนว่าการจับคู่รายการหนึ่งจะไม่มีเมฆปกคลุมเลย มาดูรายละเอียดเนื้อหาที่มีรหัส COPERNICUS/S2/20170430T190351_20170430T190351_T10SEG
กัน โปรดทราบว่าชิ้นงานแคตตาล็อกสาธารณะทั้งหมดเป็นของโปรเจ็กต์ earthengine-public
ต่อไปนี้คือข้อมูลโค้ด Python ที่จะออกคําค้นหา projects.assets.get เพื่อดึงรายละเอียดของชิ้นงานนั้นๆ ตามรหัส พิมพ์แถบข้อมูลที่มี และพิมพ์ข้อมูลโดยละเอียดเพิ่มเติมเกี่ยวกับแถบแรก
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"
}
รายการแถบข้อมูลสอดคล้องกับสิ่งที่เราเห็นก่อนหน้านี้ในคำอธิบายชุดข้อมูล เราจะเห็นว่าชุดข้อมูลนี้มีข้อมูลจำนวนเต็ม 16 บิตในระบบพิกัด EPSG:32610 หรือ UTM Zone 10N แถบแรกมีรหัส B1
และความละเอียด 60 เมตรต่อพิกเซล ต้นทางของรูปภาพอยู่ที่ตำแหน่ง (499980,4200000) ในระบบพิกัดนี้
ค่าลบของ affineTransform.scaleY
แสดงว่าจุดเริ่มต้นอยู่ที่มุมซ้ายบนของรูปภาพ ซึ่งมักจะเป็นเช่นนั้น โดยการเพิ่มดัชนีพิกเซล y
จะสอดคล้องกับการลดพิกัดเชิงพื้นที่ y
(มุ่งหน้าไปทางใต้)
การดึงค่าพิกเซล
มาส่งคำค้นหา projects.assets.getPixels เพื่อดึงข้อมูลบางอย่างจากแถบความละเอียดสูงของรูปภาพนี้กัน หน้าคำอธิบายชุดข้อมูลระบุว่าแถบความถี่ B2
, B3
, B4
และ B8
มีความละเอียด 10 เมตรต่อพิกเซล สคริปต์นี้จะดึงข้อมูลไทล์ขนาด 256x256 พิกเซลที่ด้านซ้ายบนจากแถบทั้ง 4 แถบ การโหลดข้อมูลในรูปแบบ 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 จะมีลักษณะดังนี้ (ใช้เครื่องมือแสดงรูปภาพ IPython
ของ 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)
นี่คือภาพขนาดย่อที่ได้
