Quickstart

این راهنما توضیح می‌دهد که چگونه می‌توانید به‌سرعت بااستفاده از Google Colab، پُرسمان‌ها را از Python به Earth Engine REST API ارسال کنید. همین مفاهیم برای دسترسی به API از زبان‌ها و محیط‌های دیگر نیز اعمال می‌شود.

توجه: REST API حاوی ویژگی‌های جدید و پیشرفته‌ای است که ممکن است برای همه کاربران مناسب نباشد. اگر تازه با Earth Engine آشنا شده‌اید، لطفاً با راهنمای جاوا اسکریپت شروع کنید.

قبل‌از شروع

این دستورالعمل‌ها را برای انجام کارهای زیر دنبال کنید:

راه‌اندازی کردن دفتر Colab

اگر این شروع سریع را از ابتدا شروع می‌کنید، می‌توانید با کلیک کردن روی دفتر یادداشت جدید از صفحه شروع Colab، یک دفتر یادداشت Colab جدید ایجاد کنید و نمونه کدهای زیر را در یک سلول کد جدید وارد کنید. Colab ازقبل کیت توسعه نرم‌افزار Cloud را نصب کرده است. این شامل ابزار خط فرمان gcloud است که می‌توانید از آن برای مدیریت سرویس‌های Cloud استفاده کنید. یا دفترچه نمایشی را از دکمه ابتدای این صفحه اجرا کنید.

اصالت‌سنجی در 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، بارگیری در ماشین مجازی دفترچه:

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

انتخاب مجموعه داده

می‌توانید بااستفاده از ویرایشگر کد Earth Engine در code.earthengine.google.com، مجموعه‌داده‌های دردسترس را جستجو و کاوش کنید. بیایید برخی‌از داده‌های Sentinel 2 را جستجو کنیم. (اگر اولین‌بار است که از «ویرایشگر کد» استفاده می‌کنید، هنگام ورود به سیستم از شما خواسته می‌شود به آن اجازه دهید ازجانب شما به Earth Engine دسترسی داشته باشد.) در «ویرایشگر کد»، عبارت «sentinel» را در چارگوش جستجو در بالا جستجو کنید. چندین مجموعه داده شطرنجی نشان داده می‌شود:

روی «Sentinel-2: MultiSpectral Instrument (MSI), Level-1C» کلیک کنید:

صفحه‌های شرح مجموعه داده مانند این صفحه شامل اطلاعات مهمی است که برای استفاده از هر مجموعه داده در «کاتالوگ داده‌های عمومی Earth Engine» نیاز دارید، ازجمله شرح مختصری از مجموعه داده، پیوندهایی به ارائه‌دهنده داده برای دریافت جزئیات بیشتر، اطلاعاتی درباره هرگونه محدودیت استفاده که ممکن است برای مجموعه داده اعمال شود، و شناسه دارایی Earth Engine مجموعه داده.

در این مورد، در سمت راست پنجره می‌بینیم که این دارایی مجموعه تصویر است که مسیر آن COPERNICUS/S2_HARMONIZED است.

پرسمان برای تصاویر خاص

این مجموعه داده Sentinel-2 شامل بیش‌از دو میلیون تصویر است که جهان را از سال ۲۰۱۵ تا کنون پوشش می‌دهد. بیایید یک پُرسمان projects.assets.listImages را در مجموعه تصاویر اجرا کنیم تا داده‌هایی از آوریل ۲۰۱۷ با پوشش ابری کم پیدا کنیم که شامل نقطه‌ای خاص در مانتین ویو، کالیفرنیا باشد.

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

این اسکریپت مجموعه را برای تصاویر منطبق جستجو می‌کند، پاسخ JSON حاصل را رمزگشایی می‌کند، و شناسه دارایی و پوشش ابری را برای هر دارایی تصویر منطبق چاپ می‌کند. برونداد باید شبیه این باشد:

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

ظاهراً دو تصویر از این نقطه وجود دارد که در این ماه گرفته شده‌اند و پوشش ابری کمی دارند.

بازرسی تصویر خاص

به‌نظر می‌رسد یکی از موارد منطبق اساساً پوشش ابری ندارد. بیایید نگاهی دقیق‌تر به آن دارایی با شناسه COPERNICUS/S2_HARMONIZED/20170430T190351_20170430T190351_T10SEG بیندازیم. توجه داشته باشید که همه دارایی‌های کاتالوگ عمومی به پروژه earthengine-public تعلق دارند. در اینجا یک قطعه کد Python آورده شده است که یک پُرسمان projects.assets.get را برای واکشی جزئیات آن دارایی خاص براساس شناسه صادر می‌کند، باندهای داده موجود را چاپ می‌کند، و اطلاعات دقیق‌تری درباره باند اول چاپ می‌کند:

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

برونداد باید چیزی شبیه به این باشد:

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 است. این باند اول دارای شناسه B1 و وضوح ۶۰ متر در هر پیکسل است. مبدأ تصویر در موقعیت (۴۹۹۹۸۰،۴۲۰۰۰۰۰) در این سیستم مختصات است.

مقدار منفی affineTransform.scaleY نشان می‌دهد که مبدأ در گوشه شمال غربی تصویر قرار دارد، همان‌طور که معمولاً این‌گونه است: افزایش شاخص‌های پیکسل y با کاهش مختصات فضایی y (به‌سمت جنوب) مطابقت دارد.

درحال واکشی مقادیر پیکسل

بیایید یک پُرسمان projects.assets.getPixels صادر کنیم تا برخی داده‌ها را از باندهای با وضوح بالای این تصویر واکشی کنیم. صفحه شرح مجموعه داده می‌گوید که باندهای B2، B3، B4، و B8 وضوح ۱۰ متر در هر پیکسل دارند. این اسکریپت کاشی ۲۵۶×۲۵۶ پیکسلی بالا سمت راست داده‌ها را از آن چهار باند واکشی می‌کند. بار کردن داده‌ها در قالب 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)

تصویر ریزعکس حاصل در اینجا آمده است: