Изображения, составляющие ImageCollection
можно визуализировать либо как анимацию, либо как серию миниатюр, называемых «диафильмом». Эти методы обеспечивают быструю оценку содержимого ImageCollection
и эффективную среду для наблюдения за пространственно-временными изменениями (рис. 1).
-
getVideoThumbURL()
создает серию анимированных изображений. -
getFilmstripThumbURL()
создает серию миниатюр изображений.
В следующих разделах описывается, как подготовить ImageCollection
к визуализации, приводятся примеры кода для каждого метода визуализации коллекции и рассматриваются несколько продвинутых методов анимации.
Рисунок 1. Анимация, показывающая трехдневное развитие ураганов в Атлантике в сентябре 2017 года.
Подготовка коллекции
Фильтруйте, комбинируйте, сортируйте и стилизуйте изображения в коллекции, чтобы отображать только те, которые представляют интерес или подчеркивать явление. Любая 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 для Африки. Один из вариантов — просто отфильтровать 16-дневную коллекцию NDVI MODIS, чтобы включить все наблюдения за 2018 год.
Редактор кода (JavaScript)
var ndviCol = ee.ImageCollection('MODIS/006/MOD13A2') .filterDate('2018-01-01', '2019-01-01') .select('NDVI');
Межгодовой композит по фильтру и сокращению
Визуализация приведенной выше коллекции показывает значительный шум в лесных районах с сильной облачностью (рис. 2а). Лучшего представления можно добиться, уменьшив диапазоны серийных дат по медиане по всем годам в коллекции 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);
Анимация, полученная в результате этой коллекции, менее зашумлена, поскольку каждое изображение представляет собой медиану 16-дневного композита NDVI для данных за более чем 20 лет (рис. 1b). См. этот урок для получения дополнительной информации об этой анимации.
Рисунок 2а. Годовой NDVI без межгодового композитинга. | Рисунок 2б. Годовой NDVI с межгодовым композитингом. |
Внутригодовой сводный результат по фильтру и сокращению
В предыдущем примере применяется межгодовая композиция. Также может быть полезно объединить ряд внутригодовых наблюдений. Например, данные Landsat собираются каждые шестнадцать дней для определенной сцены с каждого датчика, но часто некоторая часть изображений скрыта облаками. Маскирование облаков и объединение нескольких изображений одного и того же сезона могут создать более свободное от облаков изображение. Рассмотрим следующий пример, где изображения Landsat 5 за июль и август составлены с использованием медианы для каждого года с 1985 по 2011 год.
Редактор кода (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 на одном и том же пути, и ваша цель — отобразить мозаику изображений из двух изображений для каждой орбиты Landsat 8 в 2017 и 2018 годах. Здесь, после фильтрации коллекции по пути и строке, используется операция объединения для составления мозаики изображений 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);
Визуализация изображений
Визуализация изображений преобразует числа в цвета. Существует три способа управления представлением данных изображения в виде цвета в методах визуализации коллекции:
- Предоставьте аргументы визуализации непосредственно в
getVideoThumbURL
иgetFilmstripThumbURL
. - Сопоставьте метод
visualize
изображения с коллекцией изображений до примененияgetVideoThumbURL
иgetFilmstripThumbURL
. - Сопоставьте метод изображения
sldStyle
с коллекцией изображений до примененияgetVideoThumbURL
иgetFilmstripThumbURL
. Дополнительную информацию см. в разделе «Дескриптор стилизованного слоя» .
В примерах в этом руководстве используются варианты 1 и 2, где визуализация достигается путем сопоставления трех полос многоканального изображения с цветовыми каналами красного, зеленого и синего или значений градации одной полосы линейно вдоль цветовой палитры. Параметры визуализации включают в себя:
Параметр | Описание | Тип |
---|---|---|
группы | Список из трех названий полос, разделенных запятыми, которые будут сопоставлены с RGB. | список |
мин | Значения для сопоставления с 0 | номер или список из трех номеров, по одному на каждый диапазон |
Макс | Значения для сопоставления с 255 | номер или список из трех номеров, по одному на каждый диапазон |
прирост | Значения, на которые умножается значение каждого пикселя | номер или список из трех номеров, по одному на каждый диапазон |
предвзятость | Значения, добавляемые к каждому DN | номер или список из трех номеров, по одному на каждый диапазон |
гамма | Гамма-поправочный коэффициент(ы) | номер или список из трех номеров, по одному на каждый диапазон |
палитра | Список цветовых строк в стиле CSS (только для однополосных изображений) | список шестнадцатеричных строк, разделенных запятыми |
непрозрачность | Непрозрачность слоя (0,0 — полностью прозрачный, 1,0 — полностью непрозрачный). | число |
Используйте bands
, чтобы выбрать полосы, которые вы хотите визуализировать. Предоставьте список из одного или трех названий групп. Что касается многоканальных изображений, то по умолчанию выбираются первые три канала. Порядок названий полос определяет назначение цветов; первая, вторая и третья полосы в списке отображаются на красный, зеленый и синий цвета соответственно.
Масштабирование диапазона данных является важным фактором при визуализации изображений. По умолчанию значения данных с плавающей запятой от 0 до 1 (включительно) масштабируются от 0 до 255 (включительно). Значения вне этого диапазона принудительно присваиваются значениям 0 и 255 в зависимости от того, меньше они 0 или больше 1 соответственно. Что касается целочисленных данных, полная емкость, определяемая их типом, масштабируется от 0 до 255 (например, 16-битные данные со знаком имеют диапазон от -32 768 до 32 767, который по умолчанию масштабируется до [0, 255]). Принятие значений по умолчанию часто может привести к визуализации практически без контраста между элементами изображения. Используйте min
и max
, чтобы улучшить контраст и подчеркнуть определенный диапазон данных. Хорошее практическое правило — устанавливать значения min
и max
, которые представляют 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
). Используйте параметры min
и max
, чтобы определить диапазон значений для линейного масштабирования от 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. Обратите внимание, что в обоих примерах используются параметры min
и max
для управления тем, какие значения растягиваются до пределов 8-битных данных RGB.
Видео большой палец
Функция getVideoThumbURL()
генерирует анимацию из всех изображений в ImageCollection
, где каждое изображение представляет кадр. Общий процесс создания анимации выглядит следующим образом:
- Определите
Geometry
, границы которой определяют региональную протяженность анимации. - Определите
ImageCollection
. - Рассмотрите возможность визуализации изображений: либо сопоставьте функцию визуализации изображения с коллекцией, либо добавьте аргументы визуализации изображения в набор аргументов анимации.
- Определите аргументы анимации и вызовите метод
getVideoThumbURL
.
Результатом getVideoThumbURL
является URL-адрес. Распечатайте URL-адрес на консоли и щелкните его, чтобы запустить серверы Earth Engine, генерирующие анимацию «на лету» в новой вкладке браузера. Альтернативно просмотрите анимацию в консоли редактора кода, вызвав функцию ui.Thumbnail
для коллекции и соответствующие ей аргументы анимации. После рендеринга анимацию можно загрузить, щелкнув по ней правой кнопкой мыши и выбрав соответствующие параметры в контекстном меню.
В следующем примере показано создание анимации, отображающей глобальные температуры за 24 часа. Обратите внимание, что этот пример включает аргументы визуализации вместе с аргументами анимации, в отличие от первого сопоставления функции визуализации с ImageCollection
. После запуска этого сценария в консоли редактора кода должна появиться анимация, подобная рис. 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
является URL-адрес. Распечатайте URL-адрес на консоли и щелкните его, чтобы запустить серверы Earth Engine, генерирующие изображение «на лету» в новой вкладке браузера. После рендеринга изображение доступно для загрузки, щелкнув по нему правой кнопкой мыши и выбрав соответствующие параметры в контекстном меню.
В следующем фрагменте кода используется та же коллекция, что и в примере миниатюр видео выше. После запуска этого сценария в консоли редактора кода должен появиться диафильм, подобный рисунку 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). Границы между сушей и океаном несколько различимы, но их можно сделать явными, добавив наложение стран в виде многоугольников.
Векторные данные ( Features
) рисуются на изображениях с помощью метода paint
. Объекты можно нарисовать на существующем изображении, но лучше всего нарисовать их на пустом изображении, стилизовать его, а затем смешать результат с другими слоями стилизованного изображения. Независимая обработка каждого слоя стека визуализации обеспечивает больший контроль над стилем.
В следующем примере демонстрируется рисование границ стран Южной Америки на пустом 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()); });
Мерцание
Поскольку в коллекции всего два изображения, как в данном случае, мерцание является представлением по умолчанию при анимации коллекции. Настройте аргумент 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:00 по Гринвичу для северного и зимнего солнцестояния.
Тускнеть
Переход между двумя слоями достигается путем одновременного уменьшения непрозрачности одного слоя и увеличения непрозрачности другого с помощью последовательности приращений непрозрачности от почти 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:00 по Гринвичу для летнего и зимнего солнцестояния.
Слайдер
Переход ползунка постепенно показывает и скрывает нижний слой изображения. Это достигается путем итеративной настройки непрозрачности вышележащего изображения в диапазоне долгот (рис. 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:00 по Гринвичу для летнего и зимнего солнцестояния.