ImageCollection 視覺化

組成 ImageCollection 的圖片可視為動畫或一系列縮圖,稱為「膠片帶」。這些方法可快速評估 ImageCollection 的內容,並提供有效的媒介,讓您觀察時空變化 (圖 1)。

以下各節將說明如何為圖像製作 ImageCollection、提供每個集合圖像製作方法的程式碼範例,以及介紹幾種進階動畫技巧。


圖 1. 動畫:顯示 2017 年 9 月大西洋颶風的三天進展。

收集資料

您可以篩選、組合、排序及設定集合內圖片的樣式,只顯示感興趣的圖片或強調某種現象。任何 ImageCollection 都可以做為視覺化函式的輸入內容,但經過精心挑選的收集資料,考量了年內和年際日期範圍、觀測間隔、區域範圍、品質和表示方式,可以獲得更好的結果。

篩選

篩選圖片集合,只納入可支援視覺化呈現目的的相關資料。請考量日期、空間範圍、品質和其他特定資料集的屬性。

舉例來說,您可以依據下列方式篩選 Sentinel-2 地表反射率集合:

單一日期範圍

程式碼編輯器 (JavaScript)

var s2col = ee.ImageCollection('COPERNICUS/S2_SR')
  .filterDate('2018-01-01', '2019-01-01');

序列化的年內日期範圍

程式碼編輯器 (JavaScript)

var s2col = ee.ImageCollection('COPERNICUS/S2_SR')
  .filter(ee.Filter.calendarRange(171, 242, 'day_of_year'));

感興趣的區域

程式碼編輯器 (JavaScript)

var s2col = ee.ImageCollection('COPERNICUS/S2_SR')
  .filterBounds(ee.Geometry.Point(-122.1, 37.2));

或圖片屬性。

程式碼編輯器 (JavaScript)

var s2col = ee.ImageCollection('COPERNICUS/S2_SR')
  .filter(ee.Filter.lt('CLOUDY_PIXEL_PERCENTAGE', 50));

鏈結多個篩選器。

程式碼編輯器 (JavaScript)

var s2col = ee.ImageCollection('COPERNICUS/S2_SR')
  .filterDate('2018-01-01', '2019-01-01')
  .filterBounds(ee.Geometry.Point(-122.1, 37.2))
  .filter('CLOUDY_PIXEL_PERCENTAGE < 50');

合成

將年度內和年度間的日期範圍組合,以減少集合中的圖片數量並提升品質。舉例來說,假設您要建立非洲地區的年度 NDVI 圖表,其中一個方法是篩選 MODIS 16 天 NDVI 集合,納入所有 2018 年觀測資料。

程式碼編輯器 (JavaScript)

var ndviCol = ee.ImageCollection('MODIS/006/MOD13A2')
  .filterDate('2018-01-01', '2019-01-01')
  .select('NDVI');

依篩選器和減少值繪製跨年複合圖

上述集合的視覺化結果顯示,在雲層覆蓋率高的森林區域中,雜訊相當明顯 (圖 2a)。您可以根據 MODIS 集合中所有年份的中位數,縮短序列日期範圍,以便更準確地呈現資料。

程式碼編輯器 (JavaScript)

// Make a day-of-year sequence from 1 to 365 with a 16-day step.
var doyList = ee.List.sequence(1, 365, 16);

// Import a MODIS NDVI collection.
var ndviCol = ee.ImageCollection('MODIS/006/MOD13A2').select('NDVI');

// Map over the list of days to build a list of image composites.
var ndviCompList = doyList.map(function(startDoy) {
  // Ensure that startDoy is a number.
  startDoy = ee.Number(startDoy);

  // Filter images by date range; starting with the current startDate and
  // ending 15 days later. Reduce the resulting image collection by median.
  return ndviCol
    .filter(ee.Filter.calendarRange(startDoy, startDoy.add(15), 'day_of_year'))
    .reduce(ee.Reducer.median());
});

// Convert the image List to an ImageCollection.
var ndviCompCol = ee.ImageCollection.fromImages(ndviCompList);

由於每張圖片都代表 20 多年資料的 16 天 NDVI 合成圖的中位數 (圖 1b),因此這個集合產生的動畫雜訊較少。如要進一步瞭解這項動畫,請參閱這個教學課程

圖 2a. 年度 NDVI 不含跨年合成。 圖 2b. 年度 NDVI 年度間合成。

依篩選器和減少值計算年度內的複合值

上一個範例會套用跨年合成的功能。您也可以將一系列年度內觀測資料合成。舉例來說,每個感應器每 16 天就會收集一次 Landsat 資料,針對特定場景,但圖像的某些部分經常會被雲遮蔽。遮蔽雲朵並合成同一季節的多張圖片,可以產生更無雲的圖像。請參考以下範例,其中 1985 年至 2011 年各年的 Landsat 5 圖像,是使用中位數進行合成。

程式碼編輯器 (JavaScript)

// Assemble a collection of Landsat surface reflectance images for a given
// region and day-of-year range.
var lsCol = ee.ImageCollection('LANDSAT/LT05/C02/T1_L2')
  .filterBounds(ee.Geometry.Point(-122.9, 43.6))
  .filter(ee.Filter.dayOfYear(182, 243))
  // Add the observation year as a property to each image.
  .map(function(img) {
    return img.set('year', ee.Image(img).date().get('year'));
  });


// Define a function to scale the data and mask unwanted pixels.
function maskL457sr(image) {
  // Bit 0 - Fill
  // Bit 1 - Dilated Cloud
  // Bit 2 - Unused
  // Bit 3 - Cloud
  // Bit 4 - Cloud Shadow
  var qaMask = image.select('QA_PIXEL').bitwiseAnd(parseInt('11111', 2)).eq(0);
  var saturationMask = image.select('QA_RADSAT').eq(0);

  // Apply the scaling factors to the appropriate bands.
  var opticalBands = image.select('SR_B.').multiply(0.0000275).add(-0.2);
  var thermalBand = image.select('ST_B6').multiply(0.00341802).add(149.0);

  // Replace the original bands with the scaled ones and apply the masks.
  return image.addBands(opticalBands, null, true)
      .addBands(thermalBand, null, true)
      .updateMask(qaMask)
      .updateMask(saturationMask);
}

// Define a list of unique observation years from the image collection.
var years = ee.List(lsCol.aggregate_array('year')).distinct().sort();

// Map over the list of years to build a list of annual image composites.
var lsCompList = years.map(function(year) {
  return lsCol
    // Filter image collection by year.
    .filterMetadata('year', 'equals', year)
    // Apply cloud mask.
    .map(maskL457sr)
    // Reduce image collection by median.
    .reduce(ee.Reducer.median())
    // Set composite year as an image property.
    .set('year', year);
});

// Convert the image List to an ImageCollection.
var lsCompCol = ee.ImageCollection.fromImages(lsCompList);

透過彙整和減少作業進行年度內組合

請注意,前兩種合成方法會對日期和年份的 List 進行對應,以逐步定義要篩選和合成的日期。應用彙整是另一種執行此作業的方法。在以下程式碼片段中,我們定義了一個不重複的年份集合,然後套用 saveAll 彙整作業,找出與特定年份相對應的所有圖片。屬於特定年份的圖片會歸入 List 物件,並儲存為不同年份集合中相應年份代表的屬性。這些年度綜合圖表是從這些清單產生,方法是減少這些清單在映射至不同年份集合的函式中定義的 ImageCollections

程式碼編輯器 (JavaScript)

// Assemble a collection of Landsat surface reflectance images for a given
// region and day-of-year range.
var lsCol = ee.ImageCollection('LANDSAT/LT05/C02/T1_L2')
  .filterBounds(ee.Geometry.Point(-122.9, 43.6))
  .filter(ee.Filter.dayOfYear(182, 243))
  // Add the observation year as a property to each image.
  .map(function(img) {
    return img.set('year', ee.Image(img).date().get('year'));
  });

// Make a distinct year collection; one image representative per year.
var distinctYears = lsCol.distinct('year').sort('year');

// Define a join filter; one-to-many join on ‘year’ property.
var filter = ee.Filter.equals({leftField: 'year', rightField: 'year'});

// Define a join.
var join = ee.Join.saveAll('year_match');

// Apply the join; results in 'year_match' property being added to each distinct
// year representative image. The list includes all images in the collection
// belonging to the respective year.
var joinCol = join.apply(distinctYears, lsCol, filter);

// Define a function to scale the data and mask unwanted pixels.
function maskL457sr(image) {
  // Bit 0 - Fill
  // Bit 1 - Dilated Cloud
  // Bit 2 - Unused
  // Bit 3 - Cloud
  // Bit 4 - Cloud Shadow
  var qaMask = image.select('QA_PIXEL').bitwiseAnd(parseInt('11111', 2)).eq(0);
  var saturationMask = image.select('QA_RADSAT').eq(0);

  // Apply the scaling factors to the appropriate bands.
  var opticalBands = image.select('SR_B.').multiply(0.0000275).add(-0.2);
  var thermalBand = image.select('ST_B6').multiply(0.00341802).add(149.0);

  // Replace the original bands with the scaled ones and apply the masks.
  return image.addBands(opticalBands, null, true)
      .addBands(thermalBand, null, true)
      .updateMask(qaMask)
      .updateMask(saturationMask);
}

// Map over the distinct years collection to build a list of annual image
// composites.
var lsCompList = joinCol.map(function(img) {
  // Get the list of images belonging to the given year.
  return ee.ImageCollection.fromImages(img.get('year_match'))
    // Apply cloud mask.
    .map(maskL457sr)
    // Reduce image collection by median.
    .reduce(ee.Reducer.median())
    // Set composite year as an image property.
    .copyProperties(img, ['year']);
});

// Convert the image List to an ImageCollection.
var lsCompCol = ee.ImageCollection(lsCompList);

透過彙整和減少作業進行同日組合

另一種合成的情況是建立空間連續的圖片馬賽克。假設您感興趣的區域橫跨同一路徑內的兩個 Landsat 資料列,且您的目標是針對 2017 年和 2018 年每個 Landsat 8 軌道,顯示兩張圖片的圖像馬賽克。在這裡,在依路徑和資料列篩選集合後,會使用彙整作業,將根據擷取日期定義的同一軌道 Landsat 圖片拼接在一起。

程式碼編輯器 (JavaScript)

var lsCol = ee.ImageCollection('LANDSAT/LC08/C02/T1_L2')
  .filterDate('2017-01-01', '2019-01-01')
  .filter('WRS_PATH == 38 && (WRS_ROW == 28 || WRS_ROW == 29)')
  .map(function(img) {
    var date = img.date().format('yyyy-MM-dd');
    return img.set('date', date);
  });

var distinctDates = lsCol.distinct('date').sort('date');
var filter = ee.Filter.equals({leftField: 'date', rightField: 'date'});
var join = ee.Join.saveAll('date_match');
var joinCol = join.apply(distinctDates, lsCol, filter);

var lsColMos = ee.ImageCollection(joinCol.map(function(col) {
  return ee.ImageCollection.fromImages(col.get('date_match')).mosaic();
}));

排序

您可以依時間排序,確保正確的時間順序,也可以依所選屬性排序。根據預設,視覺化框架序列會依照集合的自然順序排序。您可以使用 sort 集合方法變更系列的排列方式,藉此選取 Image 屬性,以遞增或遞減順序排序。舉例來說,如要依觀察時間排序,請使用無所不在的 system:time_start 屬性。

程式碼編輯器 (JavaScript)

var s2col = ee.ImageCollection('COPERNICUS/S2_SR')
  .filterBounds(ee.Geometry.Point(-122.1, 37.2))
  .sort('system:time_start');

或者,您也可以依據雲量增加的程度來定義順序,例如 Sentinel-2 圖像的情況。

程式碼編輯器 (JavaScript)

var s2col = ee.ImageCollection('COPERNICUS/S2_SR')
  .filterBounds(ee.Geometry.Point(-122.1, 37.2))
  .sort('CLOUDY_PIXEL_PERCENTAGE');

順序也可以由衍生屬性 (例如區域平均 NDVI) 定義。在這裡,區域 NDVI 會新增為已對應函式中的每張圖片的屬性,接著對新屬性進行排序。

程式碼編輯器 (JavaScript)

// Define an area of interest geometry.
var aoi = ee.Geometry.Point(-122.1, 37.2).buffer(1e4);

// Filter MODIS NDVI image collection by a date range.
var ndviCol = ee.ImageCollection('MODIS/061/MOD13A1')
  .filterDate('2018-01-01', '2019-01-01')
  .select('NDVI')
  // Map over the image collection to calculate regional mean NDVI and add
  // the result to each image as a property.
  .map(function(img) {
    var meanNdvi = img.reduceRegion({
      reducer: ee.Reducer.mean(), geometry: aoi, scale: 500});
    return img.set('meanNdvi', meanNdvi.get('NDVI'));
  })
  // Sort the collection by descending regional mean NDVI.
  .sort('meanNdvi', false);

圖像視覺化

圖像視覺化功能會將數字轉換為顏色。您可以透過三種方式,控制在收藏品視覺化方法中,圖片資料以顏色呈現的方式:

  1. 直接將視覺化引數提供給 getVideoThumbURLgetFilmstripThumbURL
  2. 在套用 getVideoThumbURLgetFilmstripThumbURL 之前,先將 visualize 圖片方法對應至圖片集合。
  3. 在套用 getVideoThumbURLgetFilmstripThumbURL 之前,先將 sldStyle 圖片方法對應至圖片集合。詳情請參閱「樣式圖層描述元」。

本指南的範例使用了選項 1 和 2,其中視覺化效果是透過將多頻帶圖像的三個圖像頻帶對應至紅、綠和藍色色彩管道,或將單一頻帶的評分值沿著色板線性化,視覺化參數包括:

視覺化參數
參數 說明 類型
bands 以半形逗號分隔的清單,列出三個要對應至 RGB 的頻帶名稱 list
min 要對應至 0 的值 三個數字的數字或清單,每個頻帶一個
max 要對應至 255 的值 三個數字的數字或清單,每個頻帶一個
gain 用來乘上每個像素值的值 三個數字的數字或清單,每個頻帶一個
偏見 要新增至每個 DN 的值 三個數字的數字或清單,每個頻帶一個
gamma Gamma 校正因數 三個數字的數字或清單,每個頻帶一個
palette CSS 樣式顏色字串清單 (僅限單頻帶圖像) 以半形逗號分隔的十六進制字串清單
opacity 圖層的不透明度 (0.0 表示完全透明,1.0 表示完全不透明) 數字

使用 bands 引數選取要視覺化的頻帶。請提供一或三個樂團名稱的清單。對於多頻帶影像,系統預設會選取前三個頻帶。頻帶名稱順序會決定顏色指派方式;列出的第 1、第 2 和第 3 個頻帶分別對應至紅色、綠色和藍色。

在以圖表呈現圖像時,資料範圍縮放是重要的考量因素。根據預設,介於 0 和 1 (含) 之間的浮點資料值會縮放至介於 0 和 255 (含) 之間。系統會將超出範圍的值強制設為 0 和 255,具體取決於值是否小於 0 或大於 1。就整數資料而言,其類型定義的完整容量會縮放至 0 到 255 之間 (例如,帶符號的 16 位元資料範圍為 −32,768 到 32,767,預設會縮放至 [0, 255])。接受預設值通常會導致視覺呈現的圖像特徵之間幾乎沒有對比。使用 minmax 可改善對比度,並強調特定資料範圍。建議您將 minmax 設為代表您感興趣的領域中資料的第 2 和第 98 百分位數的值。請參考以下範例,瞭解如何計算數位高程模型的這些值。

程式碼編輯器 (JavaScript)

// Import SRTM global elevation model.
var demImg = ee.Image('USGS/SRTMGL1_003');

// Define a rectangular area of interest.
var aoi = ee.Geometry.Polygon(
  [[
    [-103.84153083119054, 49.083004219142886],
    [-103.84153083119054, 25.06838270664608],
    [-85.64817145619054, 25.06838270664608],
    [-85.64817145619054, 49.083004219142886]
  ]],
  null, false);

// Calculate the 2nd and 98th percentile elevation values from rescaled (to
// 500m) pixels intersecting the area of interest. A Dictionary is returned.
var percentClip = demImg.reduceRegion({
  reducer: ee.Reducer.percentile([2, 98]),
  geometry: aoi,
  scale: 500,
  maxPixels: 3e7
});

// Print the regional 2nd and 98th percentile elevation values. Get the
// dictionary keys and use them to get the values for each percentile summary.
var keys = percentClip.keys();
print('Set vis min to:', ee.Number(percentClip.get(keys.get(0))).round());
print('Set vis max to:', ee.Number(percentClip.get(keys.get(1))).round());

palette 參數會定義用來代表 8 位元圖像可視化的顏色。這項屬性僅適用於單頻帶表示法;如果使用多頻帶圖片指定這項屬性,會導致發生錯誤。如果資料是單一頻帶,或是您想要從多頻帶圖像中以視覺化方式呈現單一頻帶,請將 forceRgbOutput 參數設為 true (如果提供 palette 引數,則不必設定)。使用 minmax 參數定義值範圍,以便在 0 到 255 之間線性縮放。

以下是將視覺化函式對應至單一頻帶圖像集合的範例。匯入 MODIS NDVI 集合、設定 visualization 方法的示意圖引數,並將將值轉換為 RGB 圖像表示法的函式對應至 NDVI 集合。

程式碼編輯器 (JavaScript)

// Filter MODIS NDVI image collection by a date range.
var ndviCol = ee.ImageCollection('MODIS/061/MOD13A1')
  .filterDate('2018-01-01', '2019-01-01')
  .select('NDVI');

// Define visualization arguments.
var visArgs = {
  min: 0,
  max: 9000,
  palette: [
    'FFFFFF', 'CE7E45', 'DF923D', 'F1B555', 'FCD163', '99B718', '74A901',
    '66A000', '529400', '3E8601', '207401', '056201', '004C00', '023B01',
    '012E01', '011D01', '011301'
  ]
};

// Define a function to convert an image to an RGB visualization image and copy
// properties from the original image to the RGB image.
var visFun = function(img) {
  return img.visualize(visArgs).copyProperties(img, img.propertyNames());
};

// Map over the image collection to convert each image to an RGB visualization
// using the previously defined visualization function.
var ndviColVis = ndviCol.map(visFun);

以下是將視覺化函式對應至多頻圖像集合的範例:

程式碼編輯器 (JavaScript)

// Assemble a collection of Sentinel-2 surface reflectance images for a given
// region and date range.
var s2col = ee.ImageCollection('COPERNICUS/S2_SR')
  .filterBounds(ee.Geometry.Point(-96.9037, 48.0395))
  .filterDate('2019-06-01', '2019-10-01');

// Define visualization arguments.
var visArgs = {bands: ['B11', 'B8', 'B3'], min: 300, max: 3500};

// Define a function to convert an image to an RGB visualization image and copy
// properties from the original image to the RGB image.
var visFun = function(img) {
  return img.visualize(visArgs).copyProperties(img, img.propertyNames());
};

// Map over the image collection to convert each image to an RGB visualization
// using the previously defined visualization function.
var s2colVis = s2col.map(visFun);

在這種情況下,系統會提供三個頻帶,用於定義每個 RGB 圖層的強度,因此不會提供色版引數。請注意,兩個範例都使用 minmax 參數,用來控制哪些值會拉伸至 8 位元 RGB 資料的極限。

影片縮圖

getVideoThumbURL() 函式會根據 ImageCollection 中的所有圖片產生動畫,其中每張圖片代表一個影格。製作動畫的一般工作流程如下:

  1. 定義 Geometry,其邊界會決定動畫的區域範圍。
  2. 定義 ImageCollection
  3. 考慮圖像示意圖:在集合上對應圖像示意圖函式,或將圖像示意圖引數新增至動畫引數集合。
  4. 定義動畫引數並呼叫 getVideoThumbURL 方法。

getVideoThumbURL 的結果是網址。將網址輸出至控制台,然後按一下該網址,即可啟動 Earth Engine 伺服器,在新的瀏覽器分頁中即時產生動畫。或者,您也可以在 Code Editor 主控台中查看動畫,方法是對集合和其對應的動畫引數呼叫 ui.Thumbnail 函式。在算繪完成後,您可以按一下動畫的滑鼠右鍵,然後從內容選單中選取適當的選項,即可下載動畫。

以下範例說明如何產生動畫,呈現全球 24 小時的溫度變化。請注意,這個範例包含了可視化引數和動畫引數,而非先在 ImageCollection 上對應可視化函式。執行此指令碼後,Code Editor 主控台應會顯示類似圖 3 的動畫。

程式碼編輯器 (JavaScript)

// Define an area of interest geometry with a global non-polar extent.
var aoi = ee.Geometry.Polygon(
  [[[-179.0, 78.0], [-179.0, -58.0], [179.0, -58.0], [179.0, 78.0]]], null,
  false);

// Import hourly predicted temperature image collection for northern winter
// solstice. Note that predictions extend for 384 hours; limit the collection
// to the first 24 hours.
var tempCol = ee.ImageCollection('NOAA/GFS0P25')
  .filterDate('2018-12-22', '2018-12-23')
  .limit(24)
  .select('temperature_2m_above_ground');

// Define arguments for animation function parameters.
var videoArgs = {
  dimensions: 768,
  region: aoi,
  framesPerSecond: 7,
  crs: 'EPSG:3857',
  min: -40.0,
  max: 35.0,
  palette: ['blue', 'purple', 'cyan', 'green', 'yellow', 'red']
};

// Print the animation to the console as a ui.Thumbnail using the above defined
// arguments. Note that ui.Thumbnail produces an animation when the first input
// is an ee.ImageCollection instead of an ee.Image.
print(ui.Thumbnail(tempCol, videoArgs));

// Alternatively, print a URL that will produce the animation when accessed.
print(tempCol.getVideoThumbURL(videoArgs));


圖 3. 北半球冬至的每小時地表溫度,以 GIF 動畫圖片呈現。

剪輯畫面

getFilmstripThumbUrl 函式會產生單一靜態圖片,代表將 ImageCollection 中的所有圖片連結為南北系列。幻燈片影格序列會依照集合的自然順序排列。

getFilmstripThumbUrl 的結果是網址。將網址輸出至控制台,然後按一下該網址,即可啟動 Earth Engine 伺服器,在新瀏覽器分頁中即時產生圖像。在算繪完成後,只要在圖片上按一下滑鼠右鍵,然後從內容選單中選取適當的選項,即可下載圖片。

以下程式碼片段與上方影片縮圖示例使用相同的集合。執行這個指令碼後,Code Editor 主控台應會顯示類似圖 4 的膠卷。

程式碼編輯器 (JavaScript)

// Define an area of interest geometry with a global non-polar extent.
var aoi = ee.Geometry.Polygon(
  [[[-179.0, 78.0], [-179.0, -58.0], [179.0, -58.0], [179.0, 78.0]]], null,
  false);

// Import hourly predicted temperature image collection for northern winter
// solstice. Note that predictions extend for 384 hours; limit the collection
// to the first 24 hours.
var tempCol = ee.ImageCollection('NOAA/GFS0P25')
  .filterDate('2018-12-22', '2018-12-23')
  .limit(24)
  .select('temperature_2m_above_ground');

// Define arguments for the getFilmstripThumbURL function parameters.
var filmArgs = {
  dimensions: 128,
  region: aoi,
  crs: 'EPSG:3857',
  min: -40.0,
  max: 35.0,
  palette: ['blue', 'purple', 'cyan', 'green', 'yellow', 'red']
};

// Print a URL that will produce the filmstrip when accessed.
print(tempCol.getFilmstripThumbURL(filmArgs));


圖 4. 北半球冬至的每小時地表溫度,以膠卷 PNG 圖片呈現。請注意,電影膠片已分成四個部分供顯示;getFilmstripThumbURL 的結果是一系列收集的圖片,以南北方向相連。

進階技巧

以下各節將說明如何使用裁剪、不透明度和圖層合成功能,藉由新增多邊形邊框、強調感興趣的區域,以及比較集合內的圖片,來強化視覺化效果。

請注意,本節中所有後續範例都會使用此處定義的相同基礎 ImageCollection

程式碼編輯器 (JavaScript)

// Import hourly predicted temperature image collection for northern winter
// solstice. Note that predictions extend for 384 hours; limit the collection
// to the first 24 hours.
var tempCol = ee.ImageCollection('NOAA/GFS0P25')
  .filterDate('2018-12-22', '2018-12-23')
  .limit(24)
  .select('temperature_2m_above_ground');

// Define visualization arguments to control the stretch and color gradient
// of the data.
var visArgs = {
  min: -40.0,
  max: 35.0,
  palette: ['blue', 'purple', 'cyan', 'green', 'yellow', 'red']
};

// Convert each image to an RGB visualization image by mapping the visualize
// function over the image collection using the arguments defined previously.
var tempColVis = tempCol.map(function(img) {
  return img.visualize(visArgs);
});

// Import country features and filter to South American countries.
var southAmCol = ee.FeatureCollection('USDOS/LSIB_SIMPLE/2017')
  .filterMetadata('wld_rgn', 'equals', 'South America');

// Define animation region (South America with buffer).
var southAmAoi = ee.Geometry.Rectangle({
  coords: [-103.6, -58.8, -18.4, 17.4], geodesic: false});

重疊說明

您可以使用 blend Image 方法疊加多張圖片,其中兩張圖片重疊的像素會根據其遮罩 (透明度) 進行混合。

向量重疊

在圖片中加入行政區域邊界多邊形和其他幾何圖形,可以提供寶貴的空間背景資訊。請參考上方的全球每日地表溫度動畫 (圖 3)。陸地和海洋之間的邊界雖然可辨識,但您可以加入國家/地區的多邊形重疊圖,讓邊界更清楚。

透過套用 paint 方法,將向量資料 (Features) 繪製至圖片。您可以將功能繪製至現有圖片,但較佳做法是將功能繪製至空白圖片,並為其設定樣式,然後將結果與其他樣式圖片圖層混合。獨立處理視覺化堆疊的各個圖層,可進一步控制樣式。

以下範例說明如何將南美洲國家邊界繪製到空白的 Image,並將結果與全球每日溫度收集資料集的每個 Image 混合 (圖 5)。疊加的國家/地區邊界可區分陸地和水域,並提供溫度模式的背景資訊。

程式碼編輯器 (JavaScript)

// Define an empty image to paint features to.
var empty = ee.Image().byte();

// Paint country feature edges to the empty image.
var southAmOutline = empty
  .paint({featureCollection: southAmCol, color: 1, width: 1})
  // Convert to an RGB visualization image; set line color to black.
  .visualize({palette: '000000'});

// Map a blend operation over the temperature collection to overlay the country
// border outline image on all collection images.
var tempColOutline = tempColVis.map(function(img) {
  return img.blend(southAmOutline);
});

// Define animation arguments.
var videoArgs = {
  dimensions: 768,
  region: southAmAoi,
  framesPerSecond: 7,
  crs: 'EPSG:3857'
};

// Display the animation.
print(ui.Thumbnail(tempColOutline, videoArgs));


圖 5. 在珍藏內容中的圖片中加入向量疊加圖層,提供空間背景。

圖片重疊

您可以重疊多張圖片,以獲得所需的樣式。假設您想強調感興趣的區域。您可以建立圖像示意圖的靜音副本做為底層,然後疊加原始示意圖的裁剪版本。接續先前的範例,下列指令碼會產生圖 6。

程式碼編輯器 (JavaScript)

// Define an empty image to paint features to.
var empty = ee.Image().byte();

// Paint country feature edges to the empty image.
var southAmOutline = empty
  .paint({featureCollection: southAmCol, color: 1, width: 1})
  // Convert to an RGB visualization image; set line color to black.
  .visualize({palette: '000000'});

// Map a blend operation over the temperature collection to overlay the country
// border outline image on all collection images.
var tempColOutline = tempColVis.map(function(img) {
  return img.blend(southAmOutline);
});

// Define a partially opaque grey RGB image to dull the underlying image when
// blended as an overlay.
var dullLayer = ee.Image.constant(175).visualize({
  opacity: 0.6, min: 0, max: 255, forceRgbOutput: true});

// Map a two-part blending operation over the country outline temperature
// collection for final styling.
var finalVisCol = tempColOutline.map(function(img) {
  return img
    // Blend the dulling layer with the given country outline temperature image.
    .blend(dullLayer)
    // Blend a clipped copy of the country outline temperature image with the
    // dulled background image.
    .blend(img.clipToCollection(southAmCol));
});

// Define animation arguments.
var videoArgs = {
  dimensions: 768,
  region: southAmAoi,
  framesPerSecond: 7,
  crs: 'EPSG:3857'
};

// Display the animation.
print(ui.Thumbnail(finalVisCol, videoArgs));


圖 6. 裁剪圖片並疊加在靜音副本上,強調感興趣的區域。

您也可以將圖片資料與陰影地形基本圖層混合,以便標示地形並為視覺化效果增添深度 (圖 7)。

程式碼編輯器 (JavaScript)

// Define a hillshade layer from SRTM digital elevation model.
var hillshade = ee.Terrain.hillshade(ee.Image('USGS/SRTMGL1_003')
  // Exaggerate the elevation to increase contrast in hillshade.
  .multiply(100))
  // Clip the DEM by South American boundary to clean boundary between
  // land and ocean.
  .clipToCollection(southAmCol);

// Map a blend operation over the temperature collection to overlay a partially
// opaque temperature layer on the hillshade layer.
var finalVisCol = tempColVis.map(function(img) {
  return hillshade
    .blend(img.clipToCollection(southAmCol).visualize({opacity: 0.6}));
});

// Define animation arguments.
var videoArgs = {
  dimensions: 768,
  region: southAmAoi,
  framesPerSecond: 7,
  crs: 'EPSG:3857'
};

// Display the animation.
print(ui.Thumbnail(finalVisCol, videoArgs));


圖 7. 在丘陵陰影圖層上疊加部分透明的圖片資料,以顯示地形。

轉場

自訂圖片集合,使用淡出、閃爍和滑動轉場效果,製作出能顯示集合內兩張圖片之間差異的動畫。以下每個範例都使用由下列指令碼產生的相同基本圖表:

程式碼編輯器 (JavaScript)

// Define an area of interest geometry with a global non-polar extent.
var aoi = ee.Geometry.Polygon(
  [[[-179.0, 78.0], [-179.0, -58.0], [179.0, -58.0], [179.0, 78.0]]], null,
  false);

// Import hourly predicted temperature image collection.
var temp = ee.ImageCollection('NOAA/GFS0P25')

// Define a northern summer solstice temperature image.
var summerSolTemp = temp
  .filterDate('2018-06-21', '2018-06-22')
  .filterMetadata('forecast_hours', 'equals', 12)
  .first()
  .select('temperature_2m_above_ground');

// Define a northern winter solstice temperature image.
var winterSolTemp = temp
  .filterDate('2018-12-22', '2018-12-23')
  .filterMetadata('forecast_hours', 'equals', 12)
  .first()
  .select('temperature_2m_above_ground');

// Combine the solstice images into a collection.
var tempCol = ee.ImageCollection([
  summerSolTemp.set('season', 'summer'),
  winterSolTemp.set('season', 'winter')
]);

// Import international boundaries feature collection.
var countries = ee.FeatureCollection('USDOS/LSIB_SIMPLE/2017');

// Define visualization arguments.
var visArgs = {
  min: -40.0,
  max: 35.0,
  palette: ['blue', 'purple', 'cyan', 'green', 'yellow', 'red']
};

// Convert the image data to RGB visualization images.
// The clip and unmask combination sets ocean pixels to black.
var tempColVis = tempCol.map(function(img) {
  return img
    .visualize(visArgs)
    .clipToCollection(countries)
    .unmask(0)
    .copyProperties(img, img.propertyNames());
});

Flicker

在本例中,集合中只有兩張圖片,因此集合動畫的預設呈現方式為閃爍。調整 framesPerSecond 動畫引數,加快或減慢閃爍率。套用至上述集合的以下圖像化引數會產生圖 8。

程式碼編輯器 (JavaScript)

// Define arguments for animation function parameters.
var videoArgs = {
  dimensions: 768,
  region: aoi,
  framesPerSecond: 2,
  crs: 'EPSG:3857'
};

// Display animation to the Code Editor console.
print(ui.Thumbnail(tempColVis, videoArgs));


圖 8. 格林威治標準時間中午 12 點之間的表面溫度,北半球和冬至的閃爍範例。

淡出

在兩個圖層之間產生淡出轉場效果的方法,是同時降低一個圖層的透明度,同時提高另一個圖層的透明度,並以從 0 到 1 的透明度增量序列進行 (圖 9)。

程式碼編輯器 (JavaScript)

// Define a sequence of decreasing opacity increments. Note that opacity cannot
// be 0, so near 1 and 0 are used. Near 1 is needed because a compliment is
// calculated in a following step that can result in 0 if 1 is an element of the
// list.
var opacityList = ee.List.sequence({start: 0.99999, end: 0.00001, count: 20});

// Filter the summer and winter solstice images from the collection and set as
// image objects.
var summerImg = tempColVis.filter(ee.Filter.eq('season', 'summer')).first();
var winterImg = tempColVis.filter(ee.Filter.eq('season', 'winter')).first();

// Map over the list of opacity increments to iteratively adjust the opacity of
// the two solstice images. Returns a list of images.
var imgList = opacityList.map(function(opacity) {
  var opacityCompliment = ee.Number(1).subtract(ee.Number(opacity));
  var winterImgFade = winterImg.visualize({opacity: opacity});
  var summerImgFade = summerImg.visualize({opacity: opacityCompliment});
  return summerImgFade.blend(winterImgFade).set('opacity', opacity);
});

// Convert the image list to an image collection; the forward phase.
var fadeForward = ee.ImageCollection.fromImages(imgList);

// Make a copy of the collection that is sorted by ascending opacity to
// represent the reverse phase.
var fadeBackward = fadeForward.sort({property: 'opacity'});

// Merge the forward and reverse phase frame collections.
var fadeCol = fadeForward.merge(fadeBackward);

// Define animation arguments.
var videoArgs = {
  dimensions: 768,
  region: aoi,
  framesPerSecond: 25,
  crs: 'EPSG:3857'
};

// Display the animation.
print(ui.Thumbnail(fadeCol, videoArgs));


圖 9. 夏季和冬季夏至的格林威治標準時間中午 12 點之間地表溫度淡出效果示例。

滑桿

滑桿轉場效果會逐步顯示及隱藏底層圖片圖層。這項效果是透過在經度範圍內重複調整覆蓋圖片的不透明度而達成 (圖 10)。

程式碼編輯器 (JavaScript)

// Define a sequence of longitude increments. Start and end are defined by the
// min and max longitude of the feature to be provided to the region parameter
// of the animation arguments dictionary.
var lonSeq = ee.List.sequence({start: -179, end: 179, count: 20});

// Define a longitude image.
var longitude = ee.Image.pixelLonLat().select('longitude');

// Filter the summer and winter solstice images from the collection and set as
// image objects.
var summerImg = tempColVis.filter(ee.Filter.eq('season', 'summer')).first();
var winterImg = tempColVis.filter(ee.Filter.eq('season', 'winter')).first();

// Map over the list of longitude increments to iteratively adjust the mask
// (opacity) of the overlying image layer. Returns a list of images.
var imgList = lonSeq.map(function(lon) {
  lon = ee.Number(lon);
  var mask = longitude.gt(lon);
  return summerImg.blend(winterImg.updateMask(mask)).set('lon', lon);
});

// Convert the image list to an image collection; concealing phase.
var sliderColForward = ee.ImageCollection.fromImages(imgList);

// Make a copy of the collection that is sorted by descending longitude to
// represent the revealing phase.
var sliderColbackward = sliderColForward
  .sort({property: 'lon', ascending: false});

// Merge the forward and backward phase frame collections.
var sliderCol = sliderColForward.merge(sliderColbackward);

// Define animation arguments.
var videoArgs = {
  dimensions: 768,
  region: aoi,
  framesPerSecond: 25,
  crs: 'EPSG:3857'
};

// Display the animation.
print(ui.Thumbnail(sliderCol, videoArgs));


圖 10. 夏季和冬季至點的格林威治標準時間下午 12 點表面溫度之間的滑動轉換範例。