Visualização da ImageCollection

As imagens que compõem um ImageCollection podem ser visualizadas como uma animação ou uma série de miniaturas, também chamada de "tira de filme". Esses métodos fornecem uma avaliação rápida do conteúdo de um ImageCollection e um meio eficaz para testemunhar mudanças espaciais e temporais (Figura 1).

As seções a seguir descrevem como preparar um ImageCollection para visualização, fornecem um exemplo de código para cada método de visualização de coleção e abordam várias técnicas de animação avançadas.


Figura 1. Animação mostrando a progressão de três dias de furacões no Atlântico em setembro de 2017.

Preparação para a coleta

Filtrar, compor, classificar e estilizar imagens em uma coleção para mostrar apenas aquelas de interesse ou enfatizar um fenômeno. Qualquer ImageCollection pode ser fornecido como entrada para as funções de visualização, mas uma coleção selecionada com consideração de intervalos de datas inter e intra-anuais, intervalo de observação, extensão regional, qualidade e representação pode alcançar melhores resultados.

Filtragem

Filtre uma coleção de imagens para incluir apenas dados relevantes que apoiem o objetivo da visualização. Considere datas, extensão espacial, qualidade e outras propriedades específicas de um determinado conjunto de dados.

Por exemplo, filtre uma coleção de refletância de superfície do Sentinel-2:

um único período

Editor de código (JavaScript)

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

um intervalo de dias do ano em série,

Editor de código (JavaScript)

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

uma região de interesse,

Editor de código (JavaScript)

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

ou uma propriedade de imagem.

Editor de código (JavaScript)

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

Encadear vários filtros.

Editor de código (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');

Composição

Composto de períodos de datas intra e interanuais para reduzir o número de imagens em uma coleção e melhorar a qualidade. Por exemplo, suponha que você criou uma visualização do NDVI anual para a África. Uma opção é simplesmente filtrar uma coleção NDVI de 16 dias do MODIS para incluir todas as observações de 2018.

Editor de código (JavaScript)

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

Composto inter-anual por filtro e redução

A visualização da coleção acima mostra ruído considerável nas regiões florestais em que a cobertura de nuvens é intensa (Figura 2a). É possível conseguir uma representação melhor reduzindo os intervalos de datas seriais pela mediana em todos os anos na coleção MODIS.

Editor de código (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);

A animação resultante dessa coleção é menos ruidosa, já que cada imagem representa a mediana de um composto de NDVI de 16 dias para mais de 20 anos de dados (Figura 1b). Consulte este tutorial para mais informações sobre essa animação.

Figura 2a. NDVI anual sem composição inter-anual. Figura 2b. NDVI anual com composição inter-anual.

Composto intra-anual por filtro e redução

O exemplo anterior aplica a composição inter-anual. Também pode ser útil compor uma série de observações intra-anuais. Por exemplo, os dados da Landsat são coletados a cada 16 dias para uma determinada cena por sensor, mas, muitas vezes, parte das imagens fica obscurecida por nuvens. O mascaramento das nuvens e a composição de várias imagens da mesma estação podem produzir uma representação mais livre de nuvens. Considere o exemplo a seguir em que as imagens do Landsat 5 de julho e agosto são compostas usando a mediana para cada ano de 1985 a 2011.

Editor de código (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);

Composto intra-anual por união e redução

Os dois métodos de composição anteriores mapeiam um List de dias e anos para definir de forma incremental novas datas a serem filtradas e compostas. Aplicar uma mesclagem é outro método para realizar essa operação. No snippet abaixo, uma coleção de anos exclusiva é definida e uma mesclagem saveAll é aplicada para identificar todas as imagens que correspondem a um determinado ano. As imagens pertencentes a um determinado ano são agrupadas em um objeto List, que é armazenado como uma propriedade do representante do ano na coleção de anos diferentes. Os compostos anuais são gerados a partir dessas listas, reduzindo ImageCollections definido por elas em uma função mapeada sobre a coleção de anos diferentes.

Editor de código (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);

Composição no mesmo dia por mesclagem e redução

Outro caso de composição é criar mosaicos de imagens espacialmente contíguos. Suponha que sua região de interesse abranja duas linhas do Landsat no mesmo caminho e que seu objetivo seja mostrar um mosaico de imagens das duas imagens para cada órbita do Landsat 8 em 2017 e 2018. Aqui, depois de filtrar a coleção por caminho e linha, uma operação de mesclagem é usada para mesclar imagens do Landsat do mesmo período, definido pela data de aquisição.

Editor de código (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();
}));

Classificação

Classifique uma coleção por tempo para garantir a sequência cronológica adequada ou ordene por uma propriedade de sua escolha. Por padrão, a série de visualização é classificada na ordem natural da coleção. A disposição da série pode ser alterada usando o método de coleta sort, em que uma propriedade Image é selecionada para classificação em ordem crescente ou decrescente. Por exemplo, para ordenar por tempo de observação, use a propriedade system:time_start onipresente.

Editor de código (JavaScript)

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

Ou talvez a ordem seja definida por aumento da cobertura de nuvens, como neste caso das imagens do Sentinel-2.

Editor de código (JavaScript)

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

A ordem também pode ser definida por uma propriedade derivada, como a NDVI regional média. Aqui, o NDVI regional é adicionado como uma propriedade a cada imagem em uma função mapeada, seguida por uma classificação na nova propriedade.

Editor de código (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);

Visualização de imagens

A visualização de imagens transforma números em cores. Há três maneiras de controlar como os dados de imagem são representados como cores nos métodos de visualização de coletâneas:

  1. Forneça argumentos de visualização diretamente para getVideoThumbURL e getFilmstripThumbURL.
  2. Mapeie o método de imagem visualize sobre a coleção de imagens antes da aplicação de getVideoThumbURL e getFilmstripThumbURL.
  3. Mapeie o método de imagem sldStyle sobre a coleção de imagens antes da aplicação de getVideoThumbURL e getFilmstripThumbURL. Consulte Descritor de camada estilizada para mais informações.

Os exemplos neste guia usam as opções 1 e 2, em que a visualização é feita mapeando três bandas de uma imagem multibanda para canais de cores vermelho, verde e azul ou valores de gradação de uma única banda linearmente em uma paleta de cores. Os parâmetros de visualização incluem:

Parâmetros de visualização
Parâmetro Descrição Tipo
bandas Lista delimitada por vírgulas de três nomes de faixas a serem mapeadas para RGB list
min Valores a serem mapeados para 0 número ou lista de três números, um para cada faixa
max Valores a serem mapeados para 255 número ou lista de três números, um para cada faixa
ganho Valores para multiplicar cada valor de pixel número ou lista de três números, um para cada faixa
viés Valores a serem adicionados a cada DN número ou lista de três números, um para cada faixa
gama Fatores de correção de gama número ou lista de três números, um para cada faixa
palette Lista de strings de cores no estilo CSS (somente imagens de banda única) lista separada por vírgulas de strings hexadecimais
opacidade A opacidade da camada (0,0 é totalmente transparente e 1,0 é totalmente opaco) número

Use o argumento bands para selecionar as faixas que você quer visualizar. Forneça uma lista de um ou três nomes de bandas. Em relação a imagens de várias bandas, as três primeiras bandas são selecionadas por padrão. A ordem do nome da faixa determina a atribuição de cores. As faixas 1, 2 e 3 listadas são mapeadas para vermelho, verde e azul, respectivamente.

A escala de intervalo de dados é uma consideração importante ao visualizar imagens. Por padrão, os valores de dados de ponto flutuante entre 0 e 1 (inclusive) são dimensionados entre 0 e 255 (inclusive). Os valores fora desse intervalo são forçados a 0 e 255, dependendo se são menores que 0 ou maiores que 1, respectivamente. Em relação aos dados inteiros, a capacidade total definida pelo tipo é dimensionada entre 0 e 255. Por exemplo, dados assinados de 16 bits têm um intervalo de −32.768 a 32.767, que é dimensionado para [0, 255] por padrão. Aceitar os padrões muitas vezes pode resultar em visualizações com pouco ou nenhum contraste entre os recursos da imagem. Use min e max para melhorar o contraste e enfatizar um intervalo de dados específico. Uma boa regra é definir min e max como valores que representam o segundo e o 98º percentil dos dados na sua área de interesse. Confira o exemplo a seguir de cálculo desses valores para um modelo de elevação digital.

Editor de código (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());

O parâmetro palette define as cores para representar a imagem de visualização de 8 bits. Ele se aplica apenas a representações de banda única. Especificá-lo com uma imagem de várias bandas resulta em um erro. Se os dados forem de banda única ou se você quiser visualizar uma única banda de uma imagem de várias bandas, defina o parâmetro forceRgbOutput como true (não é necessário se o argumento palette for fornecido). Use os parâmetros min e max para definir o intervalo de valores para dimensionar linearmente entre 0 e 255.

Confira a seguir um exemplo de mapeamento de uma função de visualização em uma coleção de imagens de uma única banda. Uma coleção NDVI do MODIS é importada, os argumentos de visualização para o método visualization são definidos e uma função que transforma valores em representações de imagens RGB é mapeada sobre a coleção NDVI.

Editor de código (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);

Confira um exemplo de mapeamento de uma função de visualização em uma coleção de imagens multibanda:

Editor de código (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);

Nesse caso, nenhum argumento de paleta é fornecido porque três bandas são fornecidas, que definem a intensidade de cada camada RGB. Ambos os exemplos usam os parâmetros min e max para controlar quais valores são esticados até os limites dos dados RGB de 8 bits.

Miniatura do vídeo

A função getVideoThumbURL() gera uma animação de todas as imagens em um ImageCollection, em que cada imagem representa um frame. O fluxo de trabalho geral para produzir uma animação é o seguinte:

  1. Defina um Geometry cujos limites determinam a extensão regional da animação.
  2. Defina um ImageCollection.
  3. Considere a visualização de imagens: mapeie uma função de visualização de imagens sobre a coleção ou adicione argumentos de visualização de imagens ao conjunto de argumentos de animação.
  4. Defina argumentos de animação e chame o método getVideoThumbURL.

O resultado de getVideoThumbURL é um URL. Imprima o URL no console e clique nele para iniciar os servidores do Earth Engine que geram a animação em tempo real em uma nova guia do navegador. Como alternativa, para conferir a animação no console do Editor de código, chame a função ui.Thumbnail na coleção e nos argumentos de animação correspondentes. Após a renderização, a animação fica disponível para download. Para fazer isso, clique com o botão direito do mouse nela e selecione as opções adequadas no menu de contexto.

O exemplo a seguir ilustra a geração de uma animação que mostra as temperaturas globais ao longo de 24 horas. Observe que este exemplo inclui argumentos de visualização e de animação, em vez de mapear primeiro uma função de visualização no ImageCollection. Ao executar esse script, uma animação semelhante à Figura 3 vai aparecer no console do editor de código.

Editor de código (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));


Figura 3. Temperatura da superfície por hora para o solstício de inverno do hemisfério norte, representada como uma imagem GIF animada.

Trecho

A função getFilmstripThumbUrl gera uma única imagem estática que representa a concatenação de todas as imagens em um ImageCollection em uma série norte-sul. A sequência de frames da tira de filme segue a ordem natural da coleção.

O resultado de getFilmstripThumbUrl é um URL. Mostre o URL no console e clique nele para iniciar os servidores do Earth Engine que geram a imagem em tempo real em uma nova guia do navegador. Após a renderização, a imagem fica disponível para download. Clique com o botão direito do mouse nela e selecione as opções adequadas no menu de contexto.

O snippet de código abaixo usa a mesma coleção do exemplo de miniatura de vídeo acima. Ao executar esse script, uma tira de filme semelhante à Figura 4 vai aparecer no console do editor de código.

Editor de código (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));


Figura 4. Temperatura da superfície por hora para o solstício de inverno do hemisfério norte, representada como uma imagem PNG de filme. A tira de filme foi dividida em quatro seções para exibição. O resultado de getFilmstripThumbURL é uma única série de imagens da coleção unidas de norte a sul.

Técnicas avançadas

As seções a seguir descrevem como usar recorte, opacidade e composição de camadas para melhorar as visualizações adicionando bordas de polígono, enfatizando regiões de interesse e comparando imagens em uma coleção.

Todos os exemplos a seguir nesta seção usam a mesma base ImageCollection definida aqui:

Editor de código (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});

Sobreposições

Várias imagens podem ser sobrepostas usando o método blend Image, em que os pixels sobrepostos de duas imagens são mesclados com base nas máscaras (opacidade).

Sobreposição de vetor

Adicionar polígonos de limite administrativo e outras geometrias a uma imagem pode fornecer um contexto espacial valioso. Considere a animação da temperatura da superfície diária global acima (Figura 3). Os limites entre terra e oceano são um pouco discerníveis, mas podem ser explicitados adicionando uma sobreposição de polígonos de países.

Os dados vetoriais (Features) são desenhados em imagens aplicando o método paint. Os recursos podem ser pintados em uma imagem existente, mas a melhor prática é pintar em uma imagem em branco, estilizar e mesclar o resultado com outras camadas de imagem estilizadas. O tratamento de cada camada de uma pilha de visualização de forma independente permite mais controle sobre o estilo.

O exemplo a seguir demonstra como pintar as fronteiras dos países da América do Sul em uma Image em branco e mesclar o resultado com cada Image da coleção de temperatura diária global (Figura 5). Os limites dos países sobrepostos diferenciam a terra da água e fornecem contexto para os padrões de temperatura.

Editor de código (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));


Figura 5. Adicione sobreposições de vetor a imagens em uma coleção para fornecer contexto espacial.

Imagem sobreposta

Várias imagens podem ser sobrepostas para alcançar o estilo desejado. Suponha que você queira destacar uma região de interesse. Você pode criar uma cópia silenciada de uma visualização de imagem como uma camada de base e, em seguida, sobrepor uma versão cortada da visualização original. Com base no exemplo anterior, o script a seguir produz a Figura 6.

Editor de código (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));


Figura 6. Destaque uma área de interesse recortando a imagem e sobrepondo-a em uma cópia sem som.

Também é possível mesclar dados de imagem com uma camada de base de sombreamento de colinas para indicar o terreno e dar profundidade à visualização (Figura 7).

Editor de código (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));


Figura 7. Mostre o terreno sobrepondo dados de imagem parcialmente transparentes em uma camada de sombreamento de terreno.

Transições

Personalize uma coleção de imagens para produzir animações que revelem diferenças entre duas imagens em uma coleção usando transições de desbotamento, cintilação e deslize. Cada um dos exemplos a seguir usa a mesma visualização de base gerada pelo seguinte script:

Editor de código (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

Com apenas duas imagens em uma coleção, como é o caso aqui, o flicker é a representação padrão na animação da coleção. Ajuste o argumento de animação framesPerSecond para acelerar ou desacelerar a taxa de oscilação. Os argumentos de visualização a seguir aplicados à coleção acima produzem a Figura 8.

Editor de código (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));


Figura 8. Exemplo de oscilação entre a temperatura da superfície às 12h GMT para o solstício de inverno e de verão.

Esmaecer

Uma transição de desbotamento entre duas camadas é alcançada diminuindo simultaneamente a opacidade de uma camada e aumentando a opacidade da outra em uma sequência de incrementos de opacidade de quase 0 a 1 (Figura 9).

Editor de código (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));


Figura 9. Exemplo de desvanecimento entre a temperatura da superfície às 12h GMT no verão e no solstício de inverno.

Controle deslizante

Uma transição de controle deslizante mostra e oculta progressivamente a camada de imagem. Isso é feito ajustando iterativamente a opacidade da imagem sobreposta em uma faixa de longitudes (Figura 10).

Editor de código (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));


Figura 10. Exemplo de transição deslizante entre a temperatura da superfície às 12h GMT para o solstício de verão e de inverno.