画像マニフェストのアップロード

コードエディタ UI や 「earthengine」コマンドライン ツールの upload コマンドよりも柔軟に Google Earth Engine(EE)に画像をアップロードする必要がある場合は、「マニフェスト」と呼ばれる JSON ファイルを使用して画像のアップロードを記述し、コマンドライン ツールの upload image --manifest コマンドを使用します。

マニフェストを使用して画像タイルを単一のアセットとしてアップロードする方法を示すこちらの Colab ノートブックで、実証済みの例をご覧ください。

1 回限りの設定

  1. マニフェストのアップロードは、Google Cloud Storage にあるファイルでのみ機能します。Google Cloud Storage の使用を開始するには、Google Cloud プロジェクトを作成します(まだ作成していない場合)。設定には、請求用のクレジット カードを指定する必要があります。現時点では、EE 自体は課金されませんが、ファイルを EE にアップロードする前に Google Cloud Storage に転送すると、少額の費用が発生します。一般的なアップロード データサイズ(数十または数百ギガバイト)の場合、費用は非常に低くなります。
  2. プロジェクト内で、Cloud Storage API を有効にしてバケットを作成します。
  3. Earth Engine Python クライアントをインストールします。これには、データのアップロードに使用する earthengine コマンドライン ツールが含まれています。
  4. 自動アップロードの場合は、プロジェクトに関連付けられた Google Cloud サービス アカウントを使用することをおすすめします。テストにサービス アカウントは必要ありませんが、時間があるときにサービス アカウントの使用に慣れておくことをおすすめします。

非常に大きなソースファイル(100 GB 以上)は、複数のタイルに分割すると、アップロードが高速になる場合があります。

アセット ID と名前

Cloud プロジェクトが所有するアセットの場合は、アセット名に projects/some-project-id/assets/some-asset-id という規則を使用します。

以前のプロジェクトとユーザー所有のアセットのアセット名について

古いレガシー プロジェクトの場合、マニフェストのアセット名は、Earth Engine の他の場所で表示されるアセット ID と少し異なる必要があります。アセット ID が users/some_user または projects/some_project で始まるアセットをアップロードするには、マニフェストのアセット名の ID の前に文字列 projects/earthengine-legacy/assets/ を付ける必要があります。たとえば、EE アセット ID users/username/my_geotiff は、projects/earthengine-legacy/assets/users/username/my_geotiff という名前を使用してアップロードする必要があります。

はい。これは、projects/some_projects/some_asset のような ID が、projects が 2 回言及される名前(projects/earthengine-legacy/assets/projects/some_projects/some_asset)に変換されることを意味します。これは混乱を招く可能性がありますが、Google Cloud API 標準に準拠するために必要です。

マニフェストの使用

次のコードブロックに、基本的なマニフェストを示します。gs://earthengine-test という名前の Google Cloud Storage バケットから small.tif という名前のファイルをアップロードします。

{
  "name": "projects/some-project-id/assets/some-asset-id",
  "tilesets": [
    {
      "sources": [
        {
          "uris": [
            "gs://earthengine-test/small.tif"
          ]
        }
      ]
    }
  ]
}

これを使用するには、manifest.json という名前のファイルに保存して、次のコマンドを実行します。

earthengine upload image --manifest /path/to/manifest.json

(ファイル gs://earthengine-test/small.tif は存在し、一般公開されているため、テストに使用できます)。

タイルセット

JSON のやや複雑なマニフェスト構造は、アップロードに関する一般的な課題(複数のソースファイルのピクセルを 1 つのアセットに結合するすべての方法を記述する方法)に対処するのに十分な柔軟性を備えるために必要です。具体的には、ファイルをグループ化する方法は 2 つあります。

  • モザイク。複数のファイルが複数のタイルを表すこともあります(たとえば、各タイルが 1x1 度の正方形の場合)。このようなファイルは、EE アセットの同じバンドにモザイク化(統合)する必要があります。
  • バンドは別売りです。複数のファイルが複数のバンドを表すこともあります。このようなファイルは、EE アセットのバンドとしてスタックする必要があります。

(両方の方法を同時に使用しなければならない場合もありますが、そのような状況はまれです)。

これらのオプションを記述するために、マニフェストではタイルセットの概念が導入されています。1 つのタイルセットは 1 つの GDAL ソースに対応します。 このため、1 つのタイルセット内のすべてのソースは、同じ GDAL 構造(バンドの数とタイプ、投影、変換、欠損値)を持つ必要があります。GDAL ソースには複数のバンドを含めることができるため、1 つのタイルセットに複数の EE バンドのデータが含まれる場合があります。

モザイク取り込みの場合、マニフェストは次のようになります。

{
  "name": "projects/some-project-id/assets/some-asset-id",
  "tilesets": [
    {
      "sources": [
        {
          "uris": [
            "gs://bucket/N30W22.tif"
          ]
        },
        {
          "uris": [
            "gs://bucket/N31W22.tif"
          ]
        }
      ]
    }
  ]
}

別々のバンドの場合、マニフェストは次のようになります(後述のように、bands セクションも追加する必要があります)。

{
  "name": "projects/some-project-id/assets/some-asset-id",
  "bands": ...,
  "tilesets": [
    {
      "id": "tileset_for_band1",
      "sources": [
        {
          "uris": [
            "gs://bucket/band1.tif"
          ]
        }
      ]
    },
    {
      "id": "tileset_for_band2",
      "sources": [
        {
          "uris": [
            "gs://bucket/band2.tif"
          ]
        }
      ]
    }
  ]
}

バンドが別々の場合は、明確にするために記すと、各タイルセットに異なるタイルセット ID を指定する必要があります。タイルセット ID には任意の文字列を使用できます。これらの文字列は、アップロードされたアセットには保持されません。タイルセット ID は、取り込み時に積み重ねられたタイルセットを区別するためにのみ使用されます。

バンド

2 つ目の重要なコンセプトは、ソースファイルを EE アセットバンドに一致させることです。これは、マニフェストの bands セクションを使用して行います。

bands セクションは省略できます。省略した場合、バンドは最初に最初のタイルセットのファイルから作成され、次に次のタイルセットから作成されます。デフォルトでは、バンドには「b1」、「b2」などの名前が付けられます。デフォルトのバンド名をオーバーライドするには、次のように、最後に「bands」セクションを追加します。

{
  "name": "projects/earthengine-legacy/assets/users/username/some_folder/some_id",
  "tilesets": [
    {
      "sources": [
        {
          "uris": [
            "gs://bucket/rgb.tif"
          ]
        }
      ]
    }
  ],
  "bands": [
    {
      "id": "R",
      "tilesetBandIndex": 0
    },
    {
      "id": "G",
      "tilesetBandIndex": 1
    },
    {
      "id": "B",
      "tilesetBandIndex": 2
    }
  ]
}

EE バンドの数は、すべてのタイルセットのバンドの合計数と同じにする必要があります。

ファイルからすべてのバンドを取り込む必要がない場合は、tilesetBandIndex フィールドを使用して、取り込む GDAL バンドを指定できます。最初のバンドの tilesetBandIndex は 0 です。

例:

ソースファイルに「tmin」、「tmin_error」、「tmax」、「tmax_error」の 4 つのバンドがあるとします。「tmin」と「tmax」のみを取り込みます。関連するマニフェスト セクションは次のようになります。

{
  "name": "projects/earthengine-legacy/assets/users/username/some_folder/some_id",
  "tilesets": [
    {
      "id": "temperature",
      "sources": [
        {
          "uris": [
            "gs://bucket/temperature.tif"
          ]
        }
      ]
    }
  ],
  "bands": [
    {
      "id": "tmin",
      "tilesetBandIndex": 0,
      "tilesetId": "temperature"
    },
    {
      "id": "tmax",
      "tilesetBandIndex": 2,
      "tilesetId": "temperature"
    }
  ]
}

マスクバンド

バンド マスキングは、マニフェストの maskBands コンポーネントによって制御されます。 3 つのマスク構成がサポートされています(ただし、マスクバンドは常に特定のファイルの最後のバンドと見なされます)。

  1. 同じファイル内のすべてのデータバンドのマスク。
  2. 他のすべてのファイルから取得されるすべてのデータバンドのマスク。
  3. 一部のデータバンドのマスク。

1. 最も一般的なケースは、最後のバンドが他のバンドのマスクとして使用される単一の GeoTIFF です。これは、Byte タイプの GeoTIFF でのみ機能します。次のマニフェストを使用します。

{
  "name": "projects/earthengine-legacy/assets/users/username/some_folder/some_id",
  "tilesets": [
    {
      "id": "data_tileset",
      "sources": [
        {
          "uris": [
            "gs://bucket/data_file.tif"
          ]
        }
      ]
    }
  ],
  "bands": [
    {
      "id": "data_band",
      "tilesetId": "data_tileset"
    },
    {
      "id": "qa_band",
      "tilesetId": "data_tileset"
    }
  ],
  "maskBands": [
    {
      "tilesetId": "data_tileset"
    }
  ]
}

2. マスク GeoTIFF を別の GeoTIFF のすべてのバンドのマスクとして使用するには、次のマニフェストを使用します。

{
  "name": "projects/earthengine-legacy/assets/users/username/some_folder/some_id",
  "tilesets": [
    {
      "id": "data_tileset",
      "sources": [
        {
          "uris": [
            "gs://bucket/data_file.tif"
          ]
        }
      ]
    },
    {
      "id": "mask_tileset",
      "sources": [
        {
          "uris": [
            "gs://bucket/mask_file.tif"
          ]
        }
      ]
    }
  ],
  "bands": [
    {
      "id": "data_band",
      "tilesetId": "data_tileset"
    },
    {
      "id": "qa_band",
      "tilesetId": "data_tileset"
    }
  ],
  "maskBands": [
    {
      "tilesetId": "mask_tileset"
    }
  ]
}

3. GeoTIFF を別のファイルの特定のバンドのマスクとして使用するには、次のマニフェストを使用します(前のケースとの違いは、maskBands の bandIds フィールドが設定されていることです)。

{
  "name": "projects/earthengine-legacy/assets/users/username/some_folder/some_id",
  "tilesets": [
    {
      "id": "data_tileset",
      "sources": [
        {
          "uris": [
            "gs://bucket/data_file.tif"
          ]
        }
      ]
    },
    {
      "id": "mask_tileset",
      "sources": [
        {
          "uris": [
            "gs://bucket/mask_file.tif"
          ]
        }
      ]
    }
  ],
  "bands": [
    {
      "id": "data_band",
      "tilesetId": "data_tileset"
    },
    {
      "id": "qa_band",
      "tilesetId": "data_tileset"
    }
  ],
  "maskBands": [
    {
      "tilesetId": "mask_tileset",
      "bandIds": ["data_band"]
    }
  ]
}

最後の例では、data_tileset タイルセットの 2 つのバンドを操作していますが、マスクは 1 つのバンド(data_band)にのみ適用しています。これは、指定された唯一の maskBands リスト オブジェクトの bandIds フィールドで指定されています。

maskBands で指定されたタイルセットの最後のバンドのみがマスクバンドとして使用されます。

ピラミッディング ポリシー

Earth Engine が取り込み中に画像ピラミッドを構築するときは、2x2 ピクセルのグリッドを 1 つのピクセルに繰り返し縮小し、ピクセル値を何らかの方法で変換する必要があります。デフォルトでは、ピクセル値が平均化されます。これは、ラスターバンドがほぼ連続したデータを表す場合に、ほとんどのケースで適切な処理です。ただし、デフォルトに依存すると誤った結果が生成される状況が 2 つあります。その場合、バンド定義の pyramidingPolicy フィールドを設定する必要があります(設定されていない場合、その値はデフォルトで「MEAN」と見なされます)。

ラスター画像の分類(土地被覆分類など)の場合、ピクセルをピラミッド化する最も論理的な方法は、4 つの値の大部分を取得して次の値を生成することです。これは、「MODE」ピラミッド ポリシーを使用して行われます。

{
  "name": "projects/earthengine-legacy/assets/users/username/some_folder/some_id",
  "tilesets": [
    {
      "sources": [
        {
          "uris": [
            "gs://bucket/landcover.tif"
          ]
        }
      ]
    }
  ],
  "bands": [
    {
      "id": "landcover",
      "pyramidingPolicy": "MODE"
    }
  ]
}

「MEAN」も「MODE」も意味をなさないラスターバンド(ビットパックされたピクセルなど)の場合は、「SAMPLE」ピラミッド ポリシーを使用する必要があります。「SAMPLE」は常に、各 2x2 グリッドの左上のピクセルの値を取得します。次の例では、連続変数(「NDVI」)を表すバンドに「MEAN」ピラミッド ポリシーを割り当て、データの「QA」バンドに「SAMPLE」を割り当てています。

{
  "name": "projects/earthengine-legacy/assets/users/username/some_folder/some_id",
  "tilesets": [
    {
      "sources": [
        {
          "uris": [
            "gs://bucket/ndvi.tif"
          ]
        }
      ]
    }
  ],
  "bands": [
    {
      "id": "NDVI",
      "tilesetBandIndex": 0,
      "pyramidingPolicy": "MEAN"
    },
    {
      "id": "QA",
      "tilesetBandIndex": 1,
      "pyramidingPolicy": "SAMPLE"
    }
  ]
}

開始時刻と終了時刻

すべてのアセットで、データにコンテキストを付加するために開始時間と終了時間を指定する必要があります。特に、アセットがコレクションに含まれている場合は、この指定が重要になります。これらのフィールドは必須ではありませんが、可能な限り使用することを強くおすすめします。

通常、開始時間と終了時間は、ソースファイルが作成された時間ではなく、観測時間を意味します。

わかりやすくするために、終了時間は排他的な境界として扱われます。たとえば、ちょうど 1 日にわたるアセットの場合、開始時刻と終了時刻に 2 日連続の深夜 0 時(1980-01-31T00:00:00 と 1980-02-01T00:00:00 など)を使用します。アセットに期間がない場合は、終了時刻を開始時刻と同じに設定します。 マニフェスト内の時刻は ISO 8601 文字列として表します。日付値を簡素化するために、終了時間は含まれない(たとえば、日単位のアセットの場合は翌日の午前 0 時)と想定することをおすすめします。

例:

{
  "name": "projects/some-project-id/assets/some-asset-id",
  "tilesets": [
    {
      "sources": [
        {
          "uris": [
            "gs://bucket/img_20190612.tif"
          ]
        }
      ]
    }
  ],
  "startTime": "1980-01-31T00:00:00Z",
  "endTime": "1980-02-01T00:00:00Z"
}

マニフェスト構造のリファレンス

次の JSON 構造には、使用可能なすべての画像アップロード マニフェスト フィールドが含まれています。フィールドの定義については、後述のマニフェスト フィールドの定義セクションをご覧ください。

{
  "name": <string>,
  "tilesets": [
    {
      "dataType": <string>,
      "id": <string>,
      "crs": <string>,
      "sources": [
        {
          "uris": [
            <stringn>>
          ],
          "affineTransform": {
            "scaleX": <double>,
            "shearX": <double>,
            "translateX": <double>,
            "shearY": <double>,
            "scaleY": <double>,
            "translateY": <double>
          }
        }
      ]
    }
  ],
  "bands": [
    {
      "id": <string>,
      "tilesetId": <string>,
      "tilesetBandIndex": <int32>,
      "missingData": {
        "values": [<doublen>>]
      },
      "pyramindingPolicy": <string>
    }
  ],
  "maskBands": [
    {
      "tilesetId": <string>,
      "bandIds": [
        <stringn>>
      ]
    }
  ],
  "footprint": {
    "points": [
      {
        "x": <double>,
        "y": <doublen>>
      }
    ],
    "bandId": <string>
  },
  "missingData": {
     "values": [<double>]
  },
  "pyramidingPolicy": <string>,
  "uriPrefix": <string>,
  "startTime": {
    "seconds": <integer>
  },
  "endTime": {
    "seconds": <integer>
  },
  "properties": {
    <unspecified>
  }
}

マニフェスト フィールドの定義

name

string

作成するアセットの名前。 name は「projects/*/assets/**」の形式です(例: 「projects/earthengine-legacy/assets/users/USER/ASSET」)。

tilesets

list

タイルセットのプロパティを定義する辞書のリスト。 詳細については、次の tilesets 辞書要素フィールドをご覧ください。

tilesets[i].dataType

string

データの数値データ型を指定します。デフォルトは GDAL が報告するタイプです。この場合、定義する必要はありません。

データ型 値
指定なし "DATA_TYPE_UNSPECIFIED"
8 ビットの符号付き整数 "INT8"
8 ビット符号なし整数 "UINT8"
16 ビット符号付き整数 "INT16"
16 ビット符号なし整数 "UINT16"
32 ビット符号付き整数 "INT32"
32 ビット符号なし整数 "UINT32"
32 ビット浮動小数点 "FLOAT32"
64 ビット浮動小数点 "FLOAT64"

tilesets[i].id

string

タイルセットの ID。アセット マニフェストで指定されたタイルセット間で一意である必要があります。この ID は処理ステップ中に破棄されます。タイルセットをバンドにリンクするためにのみ使用されます。空の文字列は有効な ID です。

tilesets[i].crs

string

ピクセルグリッドの座標参照系。可能な場合は標準コード(EPSG コードなど)として指定し、それ以外の場合は WKT 形式で指定します。

tilesets[i].sources

list

画像ファイルとそのサイドカーのプロパティを定義する辞書のリスト。詳細については、次の sources 辞書要素フィールドをご覧ください。

tilesets[i].sources[j].uris

list

取り込むデータの URI のリスト。Google Cloud Storage URI のみがサポートされています。各 URI は、gs://bucket-id/object-id の形式で指定する必要があります。プライマリ オブジェクトはリストの最初の要素にする必要があります。サイドカーは、その後にリストします。各 URI の先頭には、設定されている場合、ImageManifest.uriPrefix が付加されます。

tilesets[i].sources[j].affineTransform

dictionary

オプションのアフィン変換。uris のデータ(サイドカーを含む)がピクセルを配置するのに十分でない場合にのみ指定する必要があります。次のキーを持つ辞書として提供されます。 "scaleX"、"shearX"、"translateX"、"shearY"、"scaleY"、"translateY"。 詳細については、こちらのリファレンスをご覧ください。

キーと値の例:

{
  "scaleX": 0.1,
  "shearX": 0.0,
  "translateX": -180.0,
  "shearY": 0.0,
  "scaleY": -0.1,
  "translateY": 90.0
}

ベルト

list

タイルセットから取得された単一のバンドのプロパティを定義する辞書のリスト。 アセットのバンド順序は bands の順序と同じです。 詳細については、次の bands 辞書要素フィールドをご覧ください。

bands[i].id

string

バンドの ID(名前)。

bands[i].tilesetId

string

バンドに対応するタイルセットの ID。

bands[i].tilesetBandIndex

int32

バンドに対応するタイルセットのゼロベースのバンド インデックス。

bands[i].missingData.values

list

バンドにデータがないことを表す値(double 型)のリスト。

bands[i].pyramidingPolicy

string

ピラミッド販売に関するポリシー。詳しくは、こちらのリンクをご覧ください。次のオプションがあります。

  • 「MEAN」(デフォルト)
  • "MODE"
  • "SAMPLE"

maskBands

list

タイルセットから取得された単一のマスクバンドのプロパティを定義する辞書のリスト。 指定できるマスクバンドは 1 つまでです。 詳細については、次の maskBands 辞書要素フィールドをご覧ください。

maskBands[i].tilesetId

string

マスクバンドに対応するタイルセットの ID。タイルセットの最後のバンドは、常にマスクバンドとして使用されます。

maskBands[i].bandIds

list of strings

マスクバンドが適用されるバンドの ID のリスト。空の場合、マスクバンドはアセット内のすべてのバンドに適用されます。各バンドに対応するマスクバンドは 1 つだけです。

フットプリント

dictionary

画像内のすべての有効なピクセルのフットプリントのプロパティを定義する辞書。空の場合、デフォルトのフットプリントは画像全体になります。詳細については、次の footprint 辞書要素フィールドをご覧ください。

footprint.points

list

画像内のすべての有効なピクセルのフットプリントを定義するポイントのリスト。点は、浮動小数点値を持つ「x」キーと「y」キーを含む辞書で定義されます。ポイントのリストは、画像のすべての有効なピクセルの中心を含む単純なポリゴンの外側を形成するリングを記述するためのものです。これはリニアリングである必要があります。最後のポイントは最初のポイントと同じである必要があります。座標は、bandId で指定されたバンドの投影にあります。

注: 各ピクセルの中心など、整数以外の座標を使用します。これは、ピクセル(1x1 の長方形)がフットプリントと交差する場合、footprint はピクセルを含むと見なされるためです。隣接するピクセルを誤って選択しないように、整数値の座標は使用しないでください。整数値の座標はピクセル間の境界です。ピクセル中心に沿ってフットプリントを描画すると、意図しないピクセルが含まれなくなります。意図したピクセルが、日付変更線や極などの地図の境界に接している場合、エラーが発生する可能性があります。

たとえば、4 つの有効なピクセルすべてを含む 2x2 の画像の場合、次のリングが考えられます。

[
  {
    "x": 0.5,
    "y": 0.5
  },
  {
    "x": 0.5,
    "y": 1.5
  },
  {
    "x": 1.5,
    "y": 1.5
  },
  {
    "x": 1.5,
    "y": 0.5
  },
  {
    "x": 0.5,
    "y": 0.5
  }
]

footprint.bandId

string

CRS がフットプリントの座標を定義するバンドの ID。 空の場合、最初のバンドが使用されます。

missingData.values

list

画像のすべてのバンドにデータがないことを表す値(double 型)のリスト。独自の missingData を指定していないすべてのバンドに適用されます。

pyramidingPolicy

string

ピラミッド販売に関するポリシー。指定しない場合、デフォルトでポリシー「MEAN」が適用されます。独自のバンドを指定していないすべてのバンドに適用されます。 詳しくは、こちらのリンクをご覧ください。次のオプションがあります。

  • 「MEAN」(デフォルト)
  • "MODE"
  • "SAMPLE"

uriPrefix

string

マニフェストで定義されているすべての uris の先頭に追加されるオプションの接頭辞。

startTime

integer

アセットに関連付けられているタイムスタンプ(存在する場合)。これは通常、衛星画像が撮影された時刻に対応します。1 か月または 1 年間の平均値など、一定期間に対応するアセットの場合、このタイムスタンプはその期間の開始に対応します。エポック(1970-01-01)からの秒数と(必要に応じて)ナノ秒数で指定します。UTC タイムゾーンであると想定されます。

endTime

integer

1 か月または 1 年間の平均値など、一定期間に対応するアセットの場合、このタイムスタンプはその期間の終了(排他的)に対応します。エポック(1970-01-01)からの秒数と(必要に応じて)ナノ秒数で指定します。UTC タイムゾーンであると想定されます。

プロパティ

dictionary

Key-Value ペアの任意のフラットな辞書。キーは文字列にする必要があります。値は数値または文字列にできます。ユーザーがアップロードしたアセットでは、リスト値はまだサポートされていません。

制限事項

JSON マニフェストのサイズ

JSON マニフェスト ファイルのサイズ上限は 10 MB です。アップロードするファイルが多数ある場合は、データセットを記述するために必要な文字数を減らす方法を検討してください。たとえば、uriPrefix フィールドを使用すると、uris リストの各 URI に Google Cloud バケットパスを指定する必要がなくなります。さらにサイズを縮小する必要がある場合は、ファイル名を短くしてみてください。

画像ファイル形式

各画像ファイルは TIFF 画像である必要があります。マニフェストで CRS が指定されていない場合、ファイルは CRS が埋め込まれた GeoTIFF である必要があります。

TIFF ファイルは、DEFLATE、JPEG-XL/JXL、LERC、LERC_DEFLATE、LERC_ZSTD、LZMA、LZW、WEBP、ZSTD で圧縮できます。

大容量ファイルをアップロードする際のおすすめの方法は次のとおりです。

  • 最適な選択肢: ZSTD は、速度と圧縮のバランスに優れています。
  • 避けるべきこと: LZMA は圧縮率は高いものの、非常に時間がかかることがあります。
  • 非圧縮ファイル: ファイルサイズが大きくなり、アップロード時間が長くなります。
  • 非可逆圧縮(JPEG など): ピクセル値が変更される可能性があります。データへの潜在的な影響を理解していない限り、可逆圧縮(DEFLATE、LZMA、LZW、ZSTD など)を使用してください。