🛰️

Google Earth Engine入門②:3つのエラーを乗り越え、衛星画像をダウンロードするまで

に公開

Google Earth Engine入門:3つのエラーを乗り越え、衛星画像をダウンロードするまで

こんにちは、古閑です。
前回のポストに引き続きGoogle Earth Engineについて学んだ記録をブログでアウトプットします。
Udemyのコース「Google Earth Engine Mega Course」を中心に学習中です。

最近、Google Earth Engine(GEE)の学習を始めました。今回のテーマは、画像をフィルターで絞り込み、地図に表示し、そしてついに手元にダウンロードするまでの道のりを共有したいと思います。

演習課題

-過去1ヶ月間に収集された画像に絞り込むこと。

-日付を直接コードに書き込まず、スクリプトを実行するたびに、常に過去1ヶ月間の画像が表示されるようにすること。
-ヒント: ee.Date.advance() 関数を使って、現在の日付の1ヶ月前の日付を計算してください。

想像以上に多くの壁にぶつかりましたが、ひとつずつ解決していく過程は大きな学びになりました。AIのサポートのおかげで演習課題だけでなく応用的な「地図上への表示」や「画像のダウンロード」まで達成できました!
まだGEEの関数や呼び出しに慣れていないなりに、ずいぶん進歩したのではないかと自画自賛しています!

ステップ1:最新の衛星画像を自動で絞り込む

最初の課題は、特定の地点の過去1ヶ月間の衛星画像を、日付を直接書き込まずに取得することでした。これにより、スクリプトをいつ実行しても常に最新のデータが表示されるようになります。

ここで少し試行錯誤しました。

// 1ヶ月前の日付を計算
var now = Date.now();
var now = ee.Date(now);


var aMonthAgo = now.advance(-1, 'month');

// Sentinel-2の画像コレクションをロード
var s2 = ee.ImageCollection('COPERNICUS/S2_SR_HARMONIZED');

// フィルターの適用
var filtered = s2
    .filterDate(aMonthAgo, now) // 過去1ヶ月間の画像でフィルター
    .filter(ee.Filter.lt('CLOUDY_PIXEL_PERCENTAGE', 30)) // 雲量が30%未満の画像でフィルター
    .filter(ee.Filter.bounds(geometry)); // 特定の地理的範囲でフィルター

// 結果を表示
print(filtered);

このコードでフィルターを適用し、画像コレクションを絞り込むことに成功しました。

ステップ2:地図への表示と最初の壁「バンド名のエラー」

次に、絞り込んだ画像を地図上に表示しようとしました。当初、地表面温度(LST)のデータに慣れていたため、バンド名をLST_2012_2021と指定しました。

しかし、実行するとすぐにエラーが発生。
Layer error: Image.select: Band pattern 'LST_2012_2021' did not match any bands.

【原因】
使用していたのはSentinel-2の画像コレクションでした。これにはLSTバンドは含まれておらず、代わりにB4B3B2などのバンドが存在します。

【解決策】
今回は、最も一般的な「トゥルーカラー(自然色)」で画像を表示することにしました。visParamsbands: ['B4', 'B3', 'B2']と指定することで、エラーを解消できました。

ステップ3:画像ダウンロードと2つ目の壁「Export too large」

地図表示に成功し、いよいよダウンロードに挑戦しました。

// --- 画像のダウンロード ---
Export.image.toDrive({
    image: composite.select(['B4', 'B3', 'B2']),
    description: 'Sentinel2_TrueColor_Composite',
    folder: 'GEE_Exports',
    scale: 10 // 解像度(メートル単位、Sentinel-2のネイティブ解像度)
});

このコードで実行すると、タスクが途中で失敗し、以下のエラーが出ました。

Error: Export too large: specified ... pixels (max: 100000000).

【原因】
scale10mという高い解像度に設定したまま、エクスポート範囲(region)を明示的に指定しなかったため、GEEが非常に広い範囲全体をエクスポートしようとしてしまいました。その結果、ピクセル数が上限の1億ピクセルをはるかに超えてしまったようです。

【解決策】
エクスポートする範囲をee.Geometry.Rectangleで定義し、regionパラメータとして明示的に指定することで、総ピクセル数を上限内に収めました。また、scale30mに調整し、ファイルサイズを抑えました。

ステップ4:ダウンロード先の指定と最後の壁

最後に、ダウンロード先のGoogle Driveフォルダを指定する際に、少し戸惑いました。当初、Google DriveのURLアドレスをそのまま指定しようとしましたが、正しくありませんでした。

【原因】
Export.image.toDrive()folderパラメータは、URLアドレスではなく、Google Driveのマイドライブ直下にあるフォルダの名前だけを文字列として指定する必要がありました。

【解決策】
folder: 'GEE_Exports' のように、フォルダ名をシンプルに記述することで、自動的にフォルダが作成され、そこにファイルが保存されることを確認しました。

まとめ:完成版のコード

これまでのすべての学びを反映させた、最終的なコードがこちらです。GeoTIFF形式でダウンロードできるので、QGISなどのGISソフトウェアで開いて利用できます。

// Excecise
// このコードを実行するには、'geometry'変数に分析したい範囲を定義する必要があります。
// 例:米国のサンフランシスコの地点
var geometry = ee.Geometry.Point([-122.4194, 37.7749]);

// エクスポートする範囲(region)を定義
// 緯度経度で小さな矩形を作成します。
var exportRegion = ee.Geometry.Rectangle({
  coords: [-122.425, 37.77, -122.41, 37.78],
  geodesic: false
});

// 1ヶ月前の日付を計算
var now = Date.now();
var now = ee.Date(now);
var aMonthAgo = now.advance(-1, 'month');

// Sentinel-2の画像コレクションをロード
var s2 = ee.ImageCollection('COPERNICUS/S2_SR_HARMONIZED');

// フィルターの適用
var filtered = s2
    .filterDate(aMonthAgo, now) // 過去1ヶ月間の画像でフィルター
    .filter(ee.Filter.lt('CLOUDY_PIXEL_PERCENTAGE', 30)) // 雲量が30%未満の画像でフィルター
    .filter(ee.Filter.bounds(geometry)); // 特定の地理的範囲でフィルター

// --- 地図への表示 ---
// 画像コレクションを1枚の画像に合成(中央値を使用)
var composite = filtered.median();

// 可視化パラメータを定義
// トゥルーカラー(自然色)画像の可視化設定
// バンドをB4(赤), B3(緑), B2(青)に割り当て、表示範囲を調整します
var visParams = {
  bands: ['B4', 'B3', 'B2'],
  min: 0,
  max: 3000,
  gamma: 1.4
};

// 地図にトゥルーカラー画像をレイヤーとして追加
Map.addLayer(composite, visParams, 'True Color Composite');

// 地図の中心を、指定した地点に設定
Map.centerObject(geometry, 10);

// --- 画像のダウンロード ---
// 合成画像をGoogle Driveにエクスポートする設定
// 形式はGeoTIFFで、QGISなどで読み込みやすいです。
Export.image.toDrive({
    image: composite.select(['B4', 'B3', 'B2']),
    description: 'Sentinel2_TrueColor_Composite', // ファイル名
    folder: 'GEE_Exports', // Google Driveの保存先フォルダ名
    scale: 30, // 解像度を30mに設定(デフォルト値)
    region: exportRegion // ここにエクスポートする範囲を追加
});

今回の経験を通じて、エラーを解決しながら進めることが、遠回りなようで実は最も確実な学習方法だと感じています。Google Earth Engine Mega Courseはまだまだ続いています。久しぶりにJaxaのGEEチュートリアルページを見直したら少し理解できるところが増えていました。引き続き、楽しみながら学習を進めていきたいと思います。

Discussion