Hình ảnh trực quan hoá ImageCollection

Bạn có thể hình dung các hình ảnh tạo nên ImageCollection dưới dạng ảnh động hoặc một loạt hình thu nhỏ được gọi là "dải phim". Các phương thức này giúp đánh giá nhanh nội dung của ImageCollection và là phương tiện hiệu quả để chứng kiến sự thay đổi về không gian và thời gian (Hình 1).

Các phần sau đây mô tả cách chuẩn bị ImageCollection để tạo hình ảnh trực quan, cung cấp mã ví dụ cho từng phương thức tạo hình ảnh trực quan của bộ sưu tập và trình bày một số kỹ thuật ảnh động nâng cao.


Hình 1. Ảnh động cho thấy tiến trình của các cơn bão Đại Tây Dương trong 3 ngày vào tháng 9 năm 2017.

Chuẩn bị thu thập

Lọc, kết hợp, sắp xếp và tạo kiểu hình ảnh trong một bộ sưu tập để chỉ hiển thị những hình ảnh bạn quan tâm hoặc làm nổi bật một hiện tượng. Bạn có thể cung cấp bất kỳ ImageCollection nào làm dữ liệu đầu vào cho các hàm trực quan hoá, nhưng một bộ sưu tập được tuyển chọn có tính đến phạm vi ngày giữa và trong năm, khoảng thời gian quan sát, phạm vi theo khu vực, chất lượng và cách trình bày có thể đạt được kết quả tốt hơn.

Lọc

Lọc một bộ sưu tập hình ảnh để chỉ bao gồm dữ liệu có liên quan hỗ trợ mục đích của hình ảnh trực quan. Hãy cân nhắc ngày, phạm vi không gian, chất lượng và các thuộc tính khác dành riêng cho một tập dữ liệu nhất định.

Ví dụ: lọc một tập hợp dữ liệu phản xạ bề mặt Sentinel-2 theo:

một phạm vi ngày duy nhất,

Trình soạn thảo mã (JavaScript)

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

một dải ngày trong năm theo tuần tự,

Trình soạn thảo mã (JavaScript)

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

một khu vực quan tâm,

Trình soạn thảo mã (JavaScript)

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

hoặc thuộc tính hình ảnh.

Trình soạn thảo mã (JavaScript)

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

Lồng ghép nhiều bộ lọc.

Trình soạn thảo mã (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');

Kết hợp

Kết hợp các phạm vi ngày trong và giữa các năm để giảm số lượng hình ảnh trong một bộ sưu tập và cải thiện chất lượng. Ví dụ: giả sử bạn muốn tạo một hình ảnh trực quan về NDVI hằng năm cho Châu Phi. Bạn chỉ cần lọc một tập hợp NDVI 16 ngày của MODIS để bao gồm tất cả các quan sát trong năm 2018.

Trình soạn thảo mã (JavaScript)

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

Tổng hợp giữa các năm theo bộ lọc và giảm

Hình ảnh trực quan của tập hợp trên cho thấy nhiễu đáng kể ở các khu vực có rừng rậm, nơi có nhiều mây che phủ (Hình 2a). Bạn có thể đạt được kết quả trình bày tốt hơn bằng cách giảm phạm vi ngày nối tiếp theo trung bình trên tất cả các năm trong tập hợp MODIS.

Trình soạn thảo mã (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);

Ảnh động thu được từ bộ sưu tập này ít nhiễu hơn, vì mỗi hình ảnh đại diện cho giá trị trung bình của một NDVI tổng hợp 16 ngày trong hơn 20 năm dữ liệu (Hình 1b). Hãy xem hướng dẫn này để biết thêm thông tin về ảnh động này.

Hình 2a. NDVI hằng năm không có dữ liệu tổng hợp giữa các năm. Hình 2b. NDVI hằng năm với tính năng kết hợp giữa các năm.

Tổng hợp trong năm theo bộ lọc và giảm

Ví dụ trước áp dụng tính năng kết hợp giữa các năm. Bạn cũng có thể kết hợp một loạt các quan sát trong năm. Ví dụ: dữ liệu Landsat được thu thập 16 ngày một lần cho một cảnh nhất định trên mỗi cảm biến, nhưng thường thì một số phần của hình ảnh bị mây che khuất. Việc che đi các đám mây và kết hợp nhiều hình ảnh trong cùng một mùa có thể tạo ra hình ảnh đại diện không có mây hơn. Hãy xem xét ví dụ sau đây, trong đó hình ảnh Landsat 5 từ tháng 7 và tháng 8 được tổng hợp bằng cách sử dụng giá trị trung vị cho mỗi năm từ năm 1985 đến năm 2011.

Trình soạn thảo mã (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);

Tổng hợp trong năm bằng cách kết hợp và giảm

Xin lưu ý rằng hai phương thức kết hợp trước đó liên kết trên một List ngày và năm để xác định dần các ngày mới để lọc và kết hợp. Áp dụng một phép nối là một phương thức khác để thực hiện thao tác này. Trong đoạn mã sau, một bộ sưu tập năm duy nhất được xác định, sau đó một phép nối saveAll được áp dụng để xác định tất cả hình ảnh tương ứng với một năm nhất định. Hình ảnh thuộc một năm nhất định được nhóm thành một đối tượng List. Đối tượng này được lưu trữ dưới dạng thuộc tính của đại diện năm tương ứng trong tập hợp năm riêng biệt. Các thành phần kết hợp hằng năm được tạo từ các danh sách này bằng cách giảm ImageCollections do các danh sách này xác định trong một hàm được liên kết với tập hợp năm riêng biệt.

Trình soạn thảo mã (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);

Kết hợp cùng ngày bằng cách kết hợp và giảm

Một trường hợp khác để kết hợp là tạo ảnh ghép hình ảnh liền kề về không gian. Giả sử khu vực bạn quan tâm trải dài trên hai hàng Landsat trong cùng một đường dẫn và mục tiêu của bạn là hiển thị một ảnh ghép của hai hình ảnh cho mỗi quỹ đạo Landsat 8 trong năm 2017 và 2018. Ở đây, sau khi lọc bộ sưu tập theo đường dẫn và hàng, một phép toán hợp nhất được dùng để tạo ảnh ghép từ các hình ảnh Landsat của cùng một bản tin tử vong, được xác định theo ngày thu thập.

Trình soạn thảo mã (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();
}));

Sắp xếp

Sắp xếp một bộ sưu tập theo thời gian để đảm bảo trình tự theo đúng thứ tự thời gian hoặc thứ tự theo một thuộc tính mà bạn chọn. Theo mặc định, chuỗi khung hình trực quan được sắp xếp theo thứ tự tự nhiên của bộ sưu tập. Bạn có thể thay đổi thứ tự sắp xếp của chuỗi bằng cách sử dụng phương thức thu thập sort, trong đó một thuộc tính Image được chọn để sắp xếp theo thứ tự tăng dần hoặc giảm dần. Ví dụ: để sắp xếp theo thời gian quan sát, hãy sử dụng thuộc tính system:time_start phổ biến.

Trình soạn thảo mã (JavaScript)

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

Hoặc có thể thứ tự được xác định bằng cách tăng độ che phủ của mây, như trong trường hợp hình ảnh Sentinel-2 này.

Trình soạn thảo mã (JavaScript)

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

Thứ tự cũng có thể được xác định bằng một thuộc tính phái sinh, chẳng hạn như NDVI trung bình theo khu vực. Tại đây, NDVI theo khu vực được thêm dưới dạng một thuộc tính vào mỗi hình ảnh trong một hàm được liên kết, theo sau là một lượt sắp xếp trên thuộc tính mới.

Trình soạn thảo mã (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);

Hình ảnh trực quan

Hình ảnh trực quan hoá biến các con số thành màu sắc. Có 3 cách để kiểm soát cách dữ liệu hình ảnh được biểu thị dưới dạng màu trong các phương thức trực quan hoá tập hợp:

  1. Cung cấp trực tiếp các đối số trực quan cho getVideoThumbURLgetFilmstripThumbURL.
  2. Ánh xạ phương thức hình ảnh visualize trên bộ sưu tập hình ảnh trước khi áp dụng getVideoThumbURLgetFilmstripThumbURL.
  3. Ánh xạ phương thức hình ảnh sldStyle trên bộ sưu tập hình ảnh trước khi áp dụng getVideoThumbURLgetFilmstripThumbURL. Hãy xem phần Trình mô tả lớp được tạo kiểu để biết thêm thông tin.

Các ví dụ trong hướng dẫn này sử dụng tuỳ chọn 1 và 2, trong đó hình ảnh được tạo bằng cách liên kết ba dải hình ảnh của hình ảnh nhiều dải với các kênh màu đỏ, xanh lục và xanh lam hoặc các giá trị phân loại của một dải theo tuyến tính dọc theo bảng màu. Các tham số trực quan hoá bao gồm:

Thông số trực quan
Thông số Mô tả Loại
dải tần số Danh sách được phân tách bằng dấu phẩy gồm 3 tên dải tần số cần liên kết với RGB danh sách
phút (Các) giá trị ánh xạ đến 0 số hoặc danh sách gồm 3 số, mỗi số tương ứng với một dải tần
max (Các) giá trị liên kết đến 255 số hoặc danh sách gồm 3 số, mỗi số tương ứng với một dải tần
gain (Các) giá trị để nhân với từng giá trị pixel số hoặc danh sách gồm 3 số, mỗi số tương ứng với một dải tần
thiên vị (Các) giá trị cần thêm vào mỗi DN số hoặc danh sách gồm 3 số, mỗi số tương ứng với một dải tần
gamma (Các) hệ số hiệu chỉnh gamma số hoặc danh sách gồm 3 số, mỗi số tương ứng với một dải tần
palette Danh sách chuỗi màu theo kiểu CSS (chỉ dành cho hình ảnh đơn băng tần) danh sách các chuỗi hex được phân tách bằng dấu phẩy
độ mờ Độ mờ của lớp (0.0 là hoàn toàn trong suốt và 1.0 là hoàn toàn mờ) số

Sử dụng đối số bands để chọn(các) dải tần mà bạn muốn trực quan hoá. Cung cấp danh sách gồm một hoặc ba tên ban nhạc. Đối với hình ảnh đa băng tần, ba băng tần đầu tiên được chọn theo mặc định. Thứ tự tên ban nhạc xác định việc gán màu; các ban nhạc được liệt kê đầu tiên, thứ hai và thứ ba được liên kết với màu đỏ, xanh lục và xanh dương tương ứng.

Điều quan trọng cần cân nhắc khi trực quan hoá hình ảnh là việc điều chỉnh theo tỷ lệ phạm vi dữ liệu. Theo mặc định, các giá trị dữ liệu dấu phẩy động từ 0 đến 1 (bao gồm cả 0 và 1) được điều chỉnh theo tỷ lệ từ 0 đến 255 (bao gồm cả 0 và 255). Các giá trị nằm ngoài phạm vi này sẽ bị buộc thành 0 và 255 tuỳ thuộc vào việc giá trị đó nhỏ hơn 0 hay lớn hơn 1. Đối với dữ liệu số nguyên, dung lượng đầy đủ do loại dữ liệu xác định được điều chỉnh theo tỷ lệ từ 0 đến 255 (ví dụ: dữ liệu 16 bit đã ký có phạm vi từ –32.768 đến 32.767, theo mặc định sẽ điều chỉnh theo tỷ lệ [0, 255]). Việc chấp nhận các giá trị mặc định thường có thể dẫn đến hình ảnh trực quan có độ tương phản thấp hoặc không có độ tương phản giữa các đặc điểm hình ảnh. Sử dụng minmax để cải thiện độ tương phản và làm nổi bật một dải dữ liệu cụ thể. Nguyên tắc chung là đặt minmax thành các giá trị đại diện cho phân vị thứ 2 và thứ 98 của dữ liệu trong khu vực mà bạn quan tâm. Hãy xem ví dụ sau đây về cách tính các giá trị này cho mô hình độ cao kỹ thuật số.

Trình soạn thảo mã (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());

Tham số palette xác định màu sắc để biểu thị hình ảnh trực quan 8 bit. Phương thức này chỉ áp dụng cho các bản trình bày đơn băng tần; việc chỉ định phương thức này bằng hình ảnh nhiều băng tần sẽ dẫn đến lỗi. Nếu dữ liệu là băng đơn hoặc bạn muốn trực quan hoá một băng từ hình ảnh nhiều băng, hãy đặt thông số forceRgbOutput thành true (không cần thiết nếu bạn cung cấp đối số palette). Sử dụng các tham số minmax để xác định phạm vi giá trị để điều chỉnh theo tỷ lệ tuyến tính từ 0 đến 255.

Sau đây là ví dụ về cách ánh xạ hàm trực quan hoá trên một tập hợp hình ảnh đơn băng tần. Một tập hợp MODIS NDVI được nhập, các đối số hình ảnh trực quan cho phương thức visualization được đặt và một hàm chuyển đổi các giá trị thành bản trình bày hình ảnh RGB được liên kết trên tập hợp NDVI.

Trình soạn thảo mã (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);

Dưới đây là ví dụ về cách ánh xạ hàm trực quan hoá trên một tập hợp hình ảnh nhiều băng tần:

Trình soạn thảo mã (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);

Trong trường hợp này, không có đối số bảng màu nào được cung cấp vì 3 dải được cung cấp, xác định cường độ cho mỗi lớp RGB. Xin lưu ý rằng cả hai ví dụ đều sử dụng các tham số minmax để kiểm soát những giá trị được kéo giãn đến giới hạn của dữ liệu RGB 8 bit.

Hình thu nhỏ video

Hàm getVideoThumbURL() tạo ảnh động từ tất cả hình ảnh trong ImageCollection, trong đó mỗi hình ảnh đại diện cho một khung. Quy trình công việc chung để tạo ảnh động như sau:

  1. Xác định một Geometry có giới hạn xác định phạm vi khu vực của ảnh động.
  2. Xác định ImageCollection.
  3. Hãy cân nhắc việc trực quan hoá hình ảnh: ánh xạ một hàm trực quan hoá hình ảnh trên tập hợp hoặc thêm đối số trực quan hoá hình ảnh vào tập hợp đối số ảnh động.
  4. Xác định đối số ảnh động và gọi phương thức getVideoThumbURL.

Kết quả của getVideoThumbURL là một URL. In URL vào bảng điều khiển rồi nhấp vào URL đó để bắt đầu các máy chủ Earth Engine tạo ảnh động ngay lập tức trong một thẻ trình duyệt mới. Ngoài ra, bạn có thể xem ảnh động trong bảng điều khiển của Trình chỉnh sửa mã bằng cách gọi hàm ui.Thumbnail trên tập hợp và các đối số ảnh động tương ứng. Sau khi kết xuất, bạn có thể tải ảnh động xuống bằng cách nhấp chuột phải vào ảnh động đó rồi chọn các tuỳ chọn thích hợp trong trình đơn theo bối cảnh.

Ví dụ sau đây minh hoạ cách tạo ảnh động mô tả nhiệt độ trên toàn cầu trong vòng 24 giờ. Xin lưu ý rằng ví dụ này bao gồm các đối số trực quan cùng với các đối số ảnh động, thay vì trước tiên ánh xạ một hàm trực quan trên ImageCollection. Khi chạy tập lệnh này, một ảnh động tương tự như Hình 3 sẽ xuất hiện trong bảng điều khiển của Trình soạn thảo mã.

Trình soạn thảo mã (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));


Hình 3. Nhiệt độ bề mặt theo giờ vào ngày đông chí ở Bắc bán cầu được thể hiện dưới dạng ảnh GIF động.

Cuộn phim

Hàm getFilmstripThumbUrl tạo một hình ảnh tĩnh duy nhất đại diện cho việc nối tất cả hình ảnh trong ImageCollection thành một chuỗi bắc-nam. Trình tự của các khung hình trong băng chuyền phim tuân theo thứ tự tự nhiên của bộ sưu tập.

Kết quả của getFilmstripThumbUrl là một URL. In URL vào bảng điều khiển rồi nhấp vào URL đó để bắt đầu các máy chủ Earth Engine tạo hình ảnh ngay trong một thẻ trình duyệt mới. Sau khi kết xuất, bạn có thể tải hình ảnh xuống bằng cách nhấp chuột phải vào hình ảnh đó rồi chọn các tuỳ chọn thích hợp trong trình đơn theo bối cảnh.

Đoạn mã sau đây sử dụng cùng một bộ sưu tập như ví dụ về hình thu nhỏ video ở trên. Sau khi chạy tập lệnh này, một dải phim tương tự như Hình 4 sẽ xuất hiện trong bảng điều khiển của Trình soạn thảo mã.

Trình soạn thảo mã (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));


Hình 4. Nhiệt độ bề mặt hằng giờ vào ngày đông chí ở Bắc bán cầu được biểu thị dưới dạng hình ảnh PNG dạng băng chuyền. Xin lưu ý rằng băng hình đã được chia thành bốn phần để hiển thị; kết quả của getFilmstripThumbURL là một loạt hình ảnh sưu tập được nối từ bắc xuống nam.

Kỹ thuật nâng cao

Các phần sau đây mô tả cách sử dụng tính năng cắt, độ mờ và kết hợp lớp để nâng cao hình ảnh bằng cách thêm đường viền đa giác, làm nổi bật các khu vực quan tâm và so sánh hình ảnh trong một bộ sưu tập.

Xin lưu ý rằng tất cả các ví dụ sau đây trong phần này đều sử dụng cùng một ImageCollection cơ sở được xác định tại đây:

Trình soạn thảo mã (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});

Lớp phủ

Bạn có thể phủ nhiều hình ảnh bằng phương thức blend Image, trong đó các pixel chồng chéo từ hai hình ảnh được kết hợp dựa trên mặt nạ (độ mờ) của các hình ảnh đó.

Lớp phủ vectơ

Việc thêm đa giác ranh giới hành chính và các hình học khác vào hình ảnh có thể cung cấp ngữ cảnh không gian có giá trị. Hãy xem xét ảnh động nhiệt độ bề mặt hằng ngày trên toàn cầu ở trên (Hình 3). Ranh giới giữa đất liền và đại dương có thể phân biệt được, nhưng bạn có thể làm rõ ranh giới bằng cách thêm lớp phủ đa giác của các quốc gia.

Dữ liệu vectơ (Features) được vẽ vào hình ảnh bằng cách áp dụng phương thức paint. Bạn có thể vẽ các đặc điểm lên một hình ảnh hiện có, nhưng tốt hơn là vẽ các đặc điểm lên một hình ảnh trống, tạo kiểu cho hình ảnh đó, sau đó kết hợp kết quả với các lớp hình ảnh được tạo kiểu khác. Việc xử lý độc lập từng lớp của ngăn xếp hình ảnh sẽ giúp bạn có nhiều quyền kiểm soát hơn đối với kiểu.

Ví dụ sau đây minh hoạ cách vẽ đường biên giới của các quốc gia ở Nam Mỹ vào một Image trống và kết hợp kết quả với từng Image của tập hợp nhiệt độ hằng ngày trên toàn cầu (Hình 5). Ranh giới quốc gia được phủ lên phân biệt đất liền với vùng nước và cung cấp bối cảnh cho các kiểu nhiệt độ.

Trình soạn thảo mã (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));


Hình 5. Thêm lớp phủ vectơ vào hình ảnh trong một bộ sưu tập để cung cấp bối cảnh không gian.

Lớp phủ hình ảnh

Bạn có thể phủ nhiều hình ảnh lên nhau để đạt được kiểu mong muốn. Giả sử bạn muốn nhấn mạnh một khu vực quan tâm. Bạn có thể tạo một bản sao bị tắt tiếng của hình ảnh trực quan dưới dạng lớp cơ sở, sau đó phủ lên một phiên bản đã cắt của hình ảnh trực quan ban đầu. Dựa trên ví dụ trước, tập lệnh sau đây sẽ tạo ra Hình 6.

Trình soạn thảo mã (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));


Hình 6. Nhấn mạnh một khu vực mà bạn quan tâm bằng cách cắt hình ảnh và phủ hình ảnh đó lên một bản sao đã tắt tiếng.

Bạn cũng có thể kết hợp dữ liệu hình ảnh với lớp cơ sở đổ bóng theo hướng đồi để chỉ báo địa hình và tạo chiều sâu cho hình ảnh trực quan (Hình 7).

Trình soạn thảo mã (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));


Hình 7. Hiển thị địa hình bằng cách phủ dữ liệu hình ảnh có độ trong suốt một phần trên lớp phủ bóng đổ.

Kiểu chuyển cảnh

Tuỳ chỉnh một bộ sưu tập hình ảnh để tạo ảnh động cho thấy sự khác biệt giữa hai hình ảnh trong một bộ sưu tập bằng cách sử dụng hiệu ứng chuyển đổi làm mờ, nhấp nháy và trượt. Mỗi ví dụ sau đây đều sử dụng cùng một hình ảnh trực quan cơ sở do tập lệnh sau tạo:

Trình soạn thảo mã (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

Với chỉ hai hình ảnh trong một bộ sưu tập, như trường hợp ở đây, hiện tượng nhấp nháy là hình ảnh mặc định khi tạo ảnh động cho bộ sưu tập. Điều chỉnh đối số ảnh động framesPerSecond để tăng tốc hoặc làm chậm tốc độ nhấp nháy. Các đối số trực quan sau đây được áp dụng cho tập hợp ở trên sẽ tạo ra Hình 8.

Trình soạn thảo mã (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));


Hình 8. Ví dụ về hiện tượng nhấp nháy giữa nhiệt độ bề mặt lúc 12 giờ trưa theo giờ GMT đối với ngày chí điểm mùa đông và mùa đông.

Làm mờ

Bạn có thể thực hiện hiệu ứng chuyển đổi mờ giữa hai lớp bằng cách đồng thời giảm độ mờ của một lớp trong khi tăng độ mờ của lớp còn lại theo một trình tự tăng dần độ mờ từ gần 0 đến 1 (Hình 9).

Trình soạn thảo mã (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));


Hình 9. Ví dụ về độ mờ giữa nhiệt độ bề mặt lúc 12 giờ trưa theo giờ GMT vào ngày hạ chí và ngày đông chí.

Thanh trượt

Hiệu ứng chuyển đổi thanh trượt hiển thị và ẩn dần lớp hình ảnh cơ bản. Điều này được thực hiện bằng cách lặp lại việc điều chỉnh độ mờ của hình ảnh phủ lên trên trên một dải kinh độ (Hình 10).

Trình soạn thảo mã (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));


Hình 10. Ví dụ về quá trình chuyển đổi trượt giữa nhiệt độ bề mặt lúc 12 giờ trưa theo giờ GMT vào ngày chí ngày hè và ngày chí ngày đông.