ثبت دارایی‌های Cloud Optimized GeoTIFF (COG)

Earth Engine از دارایی‌های پشتیبانی‌شده توسط Cloud Optimized GeoTIFFs (COGs) ذخیره‌شده در Google Cloud Storage (GCS) پشتیبانی می‌کند.

وقتی دارایی COG-backed را ثبت می‌کنید، Earth Engine فیلدهای فضایی و فراداده تصویر را در زمان ایجاد نمایه می‌کند. این کار باعث می‌شود تصویر هنگام استفاده در مجموعه‌ها عملکرد خوبی داشته باشد و عملکرد آن با دارایی‌های استاندارد واردشده قابل‌مقایسه باشد (نمای کلی Cloud Optimized GeoTIFF (COG) را ببینید).

این راهنما شامل آماده‌سازی فایل‌ها، نوشتن مانیفست، ارسال درخواست ثبت، پیکربندی اجازه‌ها، و به‌روزرسانی یا حذف دارایی‌های ثبت‌شده است.

قبل‌از شروع

پیش‌از ثبت COG، باید منابع فضای ذخیره‌سازی ابری خود را به‌درستی راه‌اندازی کنید.

مکان سطل

برای اینکه Earth Engine به سطل Cloud Storage شما دسترسی داشته باشد، سطل باید در یکی از مناطق یا چندمناطق مرکز داده زیر قرار داشته باشد:

  • چندمنطقه‌ای us
  • هر منطقه دوگانه ایالات متحده که شامل us-central1 باشد
  • منطقه us-central1

اگر دسته شما در هر مرکز داده منطقه‌ای دیگری (مانند us-east4 یا europe-west1) قرار داشته باشد، Earth Engine درخواست‌های ثبت و خواندن را رد خواهد کرد. مکان‌های پشتیبانی‌شده Cloud Storage bucket را ببینید.

کلاس فضای ذخیره‌سازی و صورت‌حساب

  • توصیه می‌کنیم از کلاس فضای ذخیره‌سازی استاندارد استفاده کنید. فضای ذخیره‌سازی استاندارد هیچ قانون حداقل مدت ذخیره‌سازی ندارد، که از جریمه‌های صورت‌حساب حذف زودهنگام درصورت به‌روزرسانی یا جایگزینی فایل‌های موقت جلوگیری می‌کند.
  • درحالی‌که حلقه‌های محاسباتی Earth Engine مشمول اضافه‌بهای بازیابی داده‌های Cloud Storage نمی‌شوند، دسترسی به ردیف‌های ذخیره‌سازی غیر«استاندارد» ازطریق ابزارهای خارجی (مانند نرم‌افزار GIS رایانه) مشمول هزینه‌های بازیابی گران‌قیمت می‌شود.
  • برای استفاده از Cloud Storage، باید صورت‌حساب را در پروژه Google Cloud خود فعال کرده باشید. برای شروع، شروع سریع Cloud Storage را ببینید.

آماده کردن COG

Earth Engine COGها را مستقیماً از Cloud Storage می‌خواند و فقط سرصفحه و کاشی‌هایی را که محاسبات نیاز دارد واکشی می‌کند، بنابراین چیدمان فایل مهم است. TIFF باید:

  • کاشی‌کاری‌شده، با ابعاد کاشی مربع توان ۲ از ۱۶×۱۶ تا ۲۰۴۸×۲۰۴۸. برای بهترین عملکرد، ۵۱۲×۵۱۲ را توصیه می‌کنیم.
  • به‌گونه‌ای مرتب شده‌اند که همه «فهرست‌های فایل تصویری» (IFD) در ابتدا قرار دارند.
  • نمای کلی توان ۲، درصورت وجود، اضافه شود. نمای کلی الزامی نیست، اما برای تصاویر بزرگ‌تر از یک کاشی توصیه می‌شود.
  • از درهم‌گذاری BAND یا PIXEL استفاده کنید (برای موازنه‌ها، فایل‌های تک‌باندی درمقابل چندباندی را ببینید).

برای تبدیل تصویر، از درایور COG GDAL استفاده کنید که چیدمان موردنیاز (کاشی‌کاری، نمای کلی، و جای‌گذاری سرصفحه) را در یک مرحله تولید می‌کند. OVERVIEW_RESAMPLING=NEAREST را برای داده‌های دسته‌ای اضافه کنید؛ پیش‌فرض CUBIC است. برای توصیه‌های فشرده‌سازی، نمای کلی، و چیدمان، روال‌های مطلوب برای آماده‌سازی COG خارجی را ببینید.

GDAL 3.11+ CLI

gdal raster convert in.tif out.tif \
  -f COG \
  --co BIGTIFF=YES \
  --co BLOCKSIZE=512 \
  --co INTERLEAVE=BAND \
  --co OVERVIEWS=IGNORE_EXISTING \
  --co COMPRESS=ZSTD \
  --co LEVEL=16 \
  --co PREDICTOR=YES \
  --co NUM_THREADS=ALL_CPUS

Classic CLI

INTERLEAVE=BAND را در نسخه‌های GDAL قدیمی‌تر از ۳.۱۱ حذف کنید.

gdal_translate in.tif out.tif \
  -of COG \
  -co BIGTIFF=YES \
  -co BLOCKSIZE=512 \
  -co INTERLEAVE=BAND \
  -co OVERVIEWS=IGNORE_EXISTING \
  -co COMPRESS=ZSTD \
  -co LEVEL=16 \
  -co PREDICTOR=YES \
  -co NUM_THREADS=ALL_CPUS

ساختن مانیفست

چه COG را بااستفاده از کتابخانه کارخواه Earth Engine Python، ابزار خط فرمان earthengine، یا Earth Engine REST API ثبت کنید، باید مانیفست بارگذاری تصویری را تعریف کنید که مقصد دارایی، URIهای Cloud Storage، و فراداده‌های اختیاری باند را مشخص کند. میانای برنامه‌سازی کاربردی و ابزار خط فرمان به دارایی‌های COG-backed به‌عنوان تصاویر خارجی (ee.data.startExternalImageIngestion()، earthengine upload external_image، projects.image.importExternal) اشاره می‌کنند.

مثال: COG تکی که از همه باندها پشتیبانی می‌کند اگر COG شما حاوی همه باندها (مثلاً RGB) باشد، مانیفست فقط به یک مجموعه کاشی نیاز دارد:

{
  "name": "projects/my-project/assets/my_cog_asset",
  "tilesets": [
    {
      "id": "default_tileset",
      "sources": [
        {
          "uris": [
            "gs://google-sample-bucket/my_optimized_image.tif"
          ]
        }
      ]
    }
  ]
}

مثال: چند COG (یک COG برای هر باند) اگر فایل‌های جداگانه‌ای برای باندهای مختلف دارید (برای مثال، قرمز، سبز، و آبی در فایل‌های جداگانه):

{
  "name": "projects/my-project/assets/my_multi_band_cog",
  "tilesets": [
    {
      "id": "red_tileset",
      "sources": [ { "uris": [ "gs://google-sample-bucket/band_red.tif" ] } ]
    },
    {
      "id": "green_tileset",
      "sources": [ { "uris": [ "gs://google-sample-bucket/band_green.tif" ] } ]
    }
  ],
  "bands": [
    { "id": "R", "tilesetId": "red_tileset", "tilesetBandIndex": 0 },
    { "id": "G", "tilesetId": "green_tileset", "tilesetBandIndex": 0 }
  ]
}

محدودیت‌های مانیفست

مانیفیست‌های دارایی‌های COG-backed محدودیت‌هایی دارند که برای مانیفیست‌های استاندارد دریافت اعمال نمی‌شوند:

  • یک سطل: همه شناسه‌های منبع یکسان در مانیفست باید در یک سطل Cloud Storage قرار داشته باشند.
  • یک URI برای هر منبع: هر ImageSource باید دقیقاً شامل یک URI باشد. نمی‌توانید چند فایل را باهم در یک منبع مجموعه کاشی موزاییک کنید. برای موزاییک کردن چند صحنه COG، هر COG را به‌عنوان دارایی ثبت کنید و آن‌ها را بااستفاده از .mosaic() در یک ee.ImageCollection ترکیب کنید.
  • نه mask_bands: از فیلد سطح بالای mask_bands پشتیبانی نمی‌شود. از missingData در مانیفست استفاده کنید یا مطمئن شوید TIFF شما مقدار nodata داخلی دارد.
  • data_type در مجموعه کاشی وجود ندارد: data_type را در بخش tilesets مشخص نکنید؛ به‌طور خودکار شناسایی می‌شود.
  • dimensions در منبع وجود ندارد: dimensions را در ImageSource مشخص نکنید.
  • نه subdataset_prefix / subdataset_suffix.
  • min_tile_area_ratio یا skip_metadata_read وجود ندارد.

ارسال درخواست ثبت‌نام

می‌توانید مانیفست خود را بااستفاده از کتابخانه کارخواه Earth Engine Python، ابزار خط فرمان earthengine، یا Earth Engine REST API به Earth Engine ارسال کنید. روشی را انتخاب کنید که بیشترین تناسب را با گردش کارتان دارد.

کتابخانه کارخواه Python

در اسکریپت Python یا دفترچه Jupyter، پس‌از مقداردهی اولیه پروژه، از کتابخانه کارخواه Earth Engine Python (ee.data) استفاده کنید:

import ee

# 1. Authenticate and initialize
ee.Authenticate()
ee.Initialize(project='your-project-id')

# 2. Define the manifest as a Python dictionary
manifest = {
  "name": "projects/your-project-id/assets/my_cog_asset",
  "tilesets": [
    {
      "id": "default_tileset",
      "sources": [
        {
          "uris": [
            "gs://google-sample-bucket/my_optimized_image.tif"
          ]
        }
      ]
    }
  ]
}

# 3. Register the asset
result = ee.data.startExternalImageIngestion(manifest)
print(f"Asset registered: {result['name']}")

رابط خط فرمان

در پایانه‌تان، مانیفست را در فایلی با نام manifest.json ذخیره کنید و فرمان بارگذاری earthengine را اجرا کنید:

# 1. Verify your environment is authenticated
earthengine authenticate

# 2. Register the asset
earthengine --project your-project-id \
  upload external_image \
  --manifest manifest.json

REST API

برای گردش‌های کاری خودکار بدون کتابخانه کارخواه، یک درخواست مجاز POST را مستقیماً به نقطه پایانی Earth Engine REST API ارسال کنید projects.image.importExternal (در اینجا بااستفاده از Python نشان داده شده است):

import json
from pprint import pprint
import ee
from google.auth.transport.requests import AuthorizedSession

# 1. Authenticate and start an authorized HTTP session
ee.Authenticate()
ee_project = 'your-project-id'
session = AuthorizedSession(
    ee.data.get_persistent_credentials().with_quota_project(ee_project)
)

# 2. Define the REST request body wrapping the manifest
request = {
  'imageManifest': {
    'name': f'projects/{ee_project}/assets/my_cog_asset',
    'tilesets': [
      {
        'id': 'default_tileset',
        'sources': [
          {
            'uris': [
              'gs://google-sample-bucket/my_optimized_image.tif'
            ]
          }
        ]
      }
    ]
  }
}

# 3. Send the POST request
url = (
    'https://earthengine.googleapis.com/v1alpha/'
    f'projects/{ee_project}/image:importExternal'
)
response = session.post(url=url, data=json.dumps(request))
pprint(json.loads(response.content))

پس‌از ارسال، درخواست ثبت‌نام یک عملیات نمایه‌سازی فراداده سبک را آغاز می‌کند. چون ثبت COG داده‌های پیکسل را کپی نمی‌کند، این عملیات معمولاً ظرف چند ثانیه تکمیل می‌شود.

پیکربندی اجازه‌ها

برخلاف دارایی‌های استاندارد Earth Engine، داده‌های پیکسل COG در Cloud Storage باقی می‌ماند. هنگام هم‌رسانی دارایی COG-backed با دیگران، باید به آن‌ها دسترسی خواندن به دارایی Earth Engine و فایل‌های Cloud Storage را اعطا کنید.

اعطای اجازه‌های سطل Cloud Storage

مشارکت‌کنندگان برای خواندن فایل‌ها از Cloud Storage به اجازه نیاز دارند.

اجازه‌های لازم:

  • storage.buckets.get (برای بازیابی فراداده و مکان دسته)
  • storage.objects.get (برای خواندن داده‌های پیکسل)

می‌توانید این اجازه‌ها را بااستفاده از نقش‌های استاندارد Cloud Storage زیر اعطا کنید:

  • Storage Bucket Viewer (storage.buckets.get را برای خواندن فراداده و مکان دسته فراهم می‌کند)
  • Storage Object Viewer (storage.objects.get را برای خواندن داده‌های پیکسل ارائه می‌دهد)

مراحل پیکربندی در Google Cloud Console:

  1. به مرورگر Cloud Storage بروید.
  2. روی نام bucket خود کلیک کنید.
  3. برگه اجازه‌ها را انتخاب کنید.
  4. روی اعطای دسترسی کلیک کنید.
  5. نشانی ایمیل همکارانتان (یا «گروه Google»، یا allUsers برای دسترسی عمومی) را اضافه کنید.
  6. نقش‌های Storage Bucket Viewer و Storage Object Viewer را واگذار کنید.
  7. روی ذخیره کلیک کنید.

هم‌رسانی کردن دارایی Earth Engine

خود دارایی را بااستفاده از «مدیر دارایی Earth Engine» یا CLI هم‌رسانی کنید. برای جزئیات، به راهنمای مدیریت دارایی مراجعه کنید.

به‌روزرسانی، جایگزینی، و حذف دارایی‌های COG-backed

دارایی COG-backed اشاره‌گری به نسخه خاصی از فایل در Cloud Storage است، به‌علاوه فراداده (ردپا، طرح، باندها، و طرح‌بندی نمای کلی) که Earth Engine هنگام ثبت آن نمایه کرده است. Earth Engine نسخه فایل را سنجاق می‌کند تا این فراداده از همگام‌سازی با پیکسل‌ها خارج نشود، که این همان چیزی است که به‌روزرسانی دارایی‌های COG-backed را از به‌روزرسانی دارایی‌های استاندارد متمایز می‌کند.

تولید شیء

وقتی COG ثبت می‌کنید، Earth Engine نسل شیء Cloud Storage (شماره نسخه آن) را در کنار URI ثبت می‌کند. می‌توانید نسل سنجاق‌شده را در فراداده دارایی ببینید؛ این نسل به‌صورت پسوند #<generation> در شناسه منبع یکسان (URI) نشان داده می‌شود:

Python

asset = ee.data.getAsset('projects/your-project-id/assets/my_cog_asset')
print(asset['tilesets'][0]['sources'][0]['uris'])
# ['gs://google-sample-bucket/my_optimized_image.tif#1750427474244728']

همچنین می‌توانید نسخه خاصی را خودتان با گنجاندن پسوند #<generation> در شناسه منبع یکسان مانیفست هنگام ثبت (یا ثبت مجدد) دارایی سنجاق کنید. بدون آن، Earth Engine شیء فعلی را می‌خواند و هر نسلی را که پیدا کند سنجاق می‌کند. سنجاق کردن صریح برای برگشتن به نسخه قبلی که یک دسته با نسخه‌بندی شیء حفظ کرده است مفید است.

اگر فایل را در Cloud Storage رونویسی کنید، نسل جدیدی دریافت می‌کند و اگر آن را حذف کنید، نسل سنجاق‌شده ازبین می‌رود. در هر دو حالت، خواندن پیکسل‌های دارایی ناموفق خواهد بود، مگراینکه نسخه‌بندی شیء در سطل، نسل قدیمی را حفظ کند که در این صورت Earth Engine به خواندن پیکسل‌های قدیمی ادامه می‌دهد. عملیات فراداده که از سابقه نمایه‌شده استفاده می‌کند (مثل ee.data.getAsset()، bandNames()، و فیلتر کردن مجموعه) در هر دو حالت به کار خود ادامه می‌دهد.

به‌روزرسانی دارایی پس‌از تغییر فایل آن

برای اشاره کردن دارایی موجود به نسخه جدید فایل آن، آن را با همان نام دارایی و با فعال کردن رونویسی دوباره ثبت کنید. Earth Engine سرصفحه GeoTIFF را دوباره می‌خواند، فراداده را دوباره نمایه‌سازی می‌کند، و نسل جدید را در یک فراخوانی همگام پین می‌کند. اجازه‌های موجود دارایی حفظ می‌شود، اما ویژگی‌ها، محدوده زمانی، و نام‌های باند آن از مانیفست جدید می‌آید، بنابراین هرچیزی را که قبلاً با ee.data.updateAsset() تنظیم کرده‌اید شامل می‌شود.

  • پایتون: ee.data.startExternalImageIngestion(manifest, allow_overwrite=True)
  • خط فرمان: earthengine upload external_image --force --manifest manifest.json
  • REST API: "overwrite": true را به‌عنوان فیلد سطح بالا درکنار "imageManifest" در projects.image.importExternal بدنه درخواست اضافه کنید.

لازم نیست ابتدا دارایی را حذف کنید و حذف آن نتیجه معکوس دارد: یک دارایی مستقل اجازه‌های خود را ازدست می‌دهد و یک تصویر در مجموعه به‌طور خلاصه از مجموعه ناپدید می‌شود. توجه داشته باشید که ee.data.updateAsset() (projects.assets.patch) فقط می‌تواند ویژگی‌ها، محدوده زمانی، و نام‌های باند را تغییر دهد؛ نمی‌تواند فایلی را که دارایی به آن اشاره می‌کند تغییر دهد.

چرخه‌های حیات مستقل

دارایی‌های Earth Engine و اشیای Cloud Storage به‌طور جداگانه مدیریت می‌شوند:

  • با حذف دارایی Earth Engine (earthengine rm یا ee.data.deleteAsset())، فقط سابقه دارایی برداشته می‌شود. فایل‌هایتان در فضای ابری دست‌نخورده باقی می‌مانند.
  • حذف فایل در Cloud Storage دارایی را برنمی‌دارد؛ دارایی همچنان در فهرستگان‌ها و در مجموعه‌اش نشان داده می‌شود (به نسل‌های شیء مراجعه کنید).

کار کردن با مجموعه‌های بزرگ

در Earth Engine API، حذف دسته‌ای یا بازگشتی وجود ندارد: هر دارایی باید به‌صورت جداگانه حذف شود و مجموعه باید خالی باشد تا بتوان آن را حذف کرد. earthengine rm -r این کار را برای شما انجام می‌دهد اما حذف‌ها را یکی‌یکی صادر می‌کند، بنابراین حذف مجموعه‌ای با ده‌ها هزار تصویر ممکن است ساعت‌ها طول بکشد.

  • برای جایگزین کردن تصاویر مجموعه، به‌جای حذف کردن، آن‌ها را بازنویسی کنید. هر تصویر را با نام و با فعال کردن بازنویسی دوباره ثبت کنید (به بالا مراجعه کنید). این به یک درخواست برای هر تصویر به‌جای دو درخواست نیاز دارد، مجموعه را در سراسر پر نگه می‌دارد، و از حذف و بازآفرینی خود مجموعه که اجازه‌های آن در آنجا قرار دارد جلوگیری می‌کند. فقط تصاویری را که در مجموعه جدید نیستند حذف کنید.
  • برای حذف دارایی‌های متعدد، از یک اسکریپت موازی‌سازی کنید. دارایی‌ها را با ee.data.listAssets() فهرست کنید (بااستفاده از نمای BASIC که فقط نام‌ها و نوع‌ها را به‌جای فراداده کامل برای هر تصویر برمی‌گرداند) و آن‌ها را از استخر رشته کوچک حذف کنید. درخواست‌های دارایی محدودیت‌های نرخ در سطح پروژه را هم‌رسانی می‌کنند، بنابراین هم‌زمانی را در حد متوسط (حدود ۱۰ کارگر) نگه دارید و اجازه دهید تلاش‌های مجدد داخلی کتابخانه کارخواه هرگونه پاسخ 429 Too Many Requests را مدیریت کند:

    Python

    import concurrent.futures
    import ee
    
    ee.Initialize(project='your-project-id')
    collection = 'projects/your-project-id/assets/my_collection'
    
    listing = ee.data.listAssets({'parent': collection, 'view': 'BASIC'})
    asset_ids = [a['name'] for a in listing['assets']]
    
    def delete(asset_id):
      try:
        ee.data.deleteAsset(asset_id)
      except ee.EEException as e:
        return f'{asset_id}: {e}'
    
    with concurrent.futures.ThreadPoolExecutor(max_workers=10) as executor:
      failures = [f for f in executor.map(delete, asset_ids) if f]
    
    if failures:
      print('\n'.join(failures))
    else:
      ee.data.deleteAsset(collection)
    

    مجموعه فقط درصورتی حذف می‌شود که همه تصاویر حذف شده باشند، بنابراین درصورت ناموفق بودن حذف برخی‌از تصاویر، مجموعه برای اجرای مجدد باقی می‌ماند.

    همین الگو برای ثبت چندین تصویر اعمال می‌شود: ee.data.deleteAsset(asset_id) را در کمک‌کننده با ee.data.startExternalImageIngestion(manifest, allow_overwrite=True) جایگزین کنید و آن را روی فهرست مانیفست‌هایتان نگاشت کنید. ارسال allow_overwrite=True حتی در اولین اجرا باعث می‌شود که دسته پس‌از خرابی جزئی برای اجرای مجدد ایمن باشد، زیرا هر دارایی که قبلاً ایجاد شده است به‌جای ایجاد خطا جایگزین می‌شود.

استفاده از دارایی‌های ثبت‌شده

پس‌از ثبت، به دارایی COG-backed در اسکریپت‌های Earth Engine دسترسی پیدا می‌کنید، درست مانند هر دارایی تصویر استاندارد واردشده:

JavaScript

var image = ee.Image('projects/your-project-id/assets/my_cog_asset');

Python

image = ee.Image('projects/your-project-id/assets/my_cog_asset')

برای دریافت پاسخ پرسش‌های متداول درباره اجازه‌ها، به‌روزرسانی فایل‌ها، و مدیریت مجموعه‌های بزرگ، بخش COG در پرسشگان را ببینید.