Compilación y mosaico

En general, la composición se refiere al proceso de combinar imágenes superpuestas espacialmente en una sola imagen según una función de agregación. El mosaico hace referencia al proceso de ensamblar conjuntos de datos de imágenes de forma espacial para producir una imagen espacialmente continua. En Earth Engine, estos términos se usan indistintamente, aunque se admiten tanto la compaginación como la creación de mosaicos. Por ejemplo, considera la tarea de combinar varias imágenes en la misma ubicación. Por ejemplo, con un cuadrángulo digital ortográfico (DOQQ) del Programa Nacional de Imágenes Agrícolas (NAIP) en diferentes momentos, el siguiente ejemplo muestra cómo crear un compuesto de valor máximo:

// Load three NAIP quarter quads in the same location, different times.
var naip2004_2012 = ee.ImageCollection('USDA/NAIP/DOQQ')
  .filterBounds(ee.Geometry.Point(-71.08841, 42.39823))
  .filterDate('2004-07-01', '2012-12-31')
  .select(['R', 'G', 'B']);

// Temporally composite the images with a maximum value function.
var composite = naip2004_2012.max();
Map.setCenter(-71.12532, 42.3712, 12);
Map.addLayer(composite, {}, 'max value composite');

Consulta la página Entorno de Python para obtener información sobre la API de Python y el uso de geemap para el desarrollo interactivo.

import ee
import geemap.core as geemap
# Load three NAIP quarter quads in the same location, different times.
naip_2004_2012 = (
    ee.ImageCollection('USDA/NAIP/DOQQ')
    .filterBounds(ee.Geometry.Point(-71.08841, 42.39823))
    .filterDate('2004-07-01', '2012-12-31')
    .select(['R', 'G', 'B'])
)

# Temporally composite the images with a maximum value function.
composite = naip_2004_2012.max()
m.set_center(-71.12532, 42.3712, 12)
m.add_layer(composite, {}, 'max value composite')
m

Ten en cuenta la necesidad de crear un mosaico de cuatro DOQQ diferentes al mismo tiempo, pero en ubicaciones diferentes. En el siguiente ejemplo, se muestra que, con imageCollection.mosaic(), se puede hacer lo siguiente:

// Load four 2012 NAIP quarter quads, different locations.
var naip2012 = ee.ImageCollection('USDA/NAIP/DOQQ')
  .filterBounds(ee.Geometry.Rectangle(-71.17965, 42.35125, -71.08824, 42.40584))
  .filterDate('2012-01-01', '2012-12-31');

// Spatially mosaic the images in the collection and display.
var mosaic = naip2012.mosaic();
Map.setCenter(-71.12532, 42.3712, 12);
Map.addLayer(mosaic, {}, 'spatial mosaic');

Consulta la página Entorno de Python para obtener información sobre la API de Python y el uso de geemap para el desarrollo interactivo.

import ee
import geemap.core as geemap
# Load four 2012 NAIP quarter quads, different locations.
naip_2012 = (
    ee.ImageCollection('USDA/NAIP/DOQQ')
    .filterBounds(
        ee.Geometry.Rectangle(-71.17965, 42.35125, -71.08824, 42.40584)
    )
    .filterDate('2012-01-01', '2012-12-31')
)

# Spatially mosaic the images in the collection and display.
mosaic = naip_2012.mosaic()
m = geemap.Map()
m.set_center(-71.12532, 42.3712, 12)
m.add_layer(mosaic, {}, 'spatial mosaic')

Ten en cuenta que hay cierta superposición en los DOQQ del ejemplo anterior. El método mosaic() combina imágenes superpuestas según su orden en la colección (la última en la parte superior). Para controlar la fuente de píxeles en un mosaico (o un compuesto), usa máscaras de imagen. Por ejemplo, el siguiente comando usa umbrales en los índices espectrales para enmascarar los datos de imagen en un mosaico:

// Load a NAIP quarter quad, display.
var naip = ee.Image('USDA/NAIP/DOQQ/m_4207148_nw_19_1_20120710');
Map.setCenter(-71.0915, 42.3443, 14);
Map.addLayer(naip, {}, 'NAIP DOQQ');

// Create the NDVI and NDWI spectral indices.
var ndvi = naip.normalizedDifference(['N', 'R']);
var ndwi = naip.normalizedDifference(['G', 'N']);

// Create some binary images from thresholds on the indices.
// This threshold is designed to detect bare land.
var bare1 = ndvi.lt(0.2).and(ndwi.lt(0.3));
// This detects bare land with lower sensitivity. It also detects shadows.
var bare2 = ndvi.lt(0.2).and(ndwi.lt(0.8));

// Define visualization parameters for the spectral indices.
var ndviViz = {min: -1, max: 1, palette: ['FF0000', '00FF00']};
var ndwiViz = {min: 0.5, max: 1, palette: ['00FFFF', '0000FF']};

// Mask and mosaic visualization images.  The last layer is on top.
var mosaic = ee.ImageCollection([
  // NDWI > 0.5 is water.  Visualize it with a blue palette.
  ndwi.updateMask(ndwi.gte(0.5)).visualize(ndwiViz),
  // NDVI > 0.2 is vegetation.  Visualize it with a green palette.
  ndvi.updateMask(ndvi.gte(0.2)).visualize(ndviViz),
  // Visualize bare areas with shadow (bare2 but not bare1) as gray.
  bare2.updateMask(bare2.and(bare1.not())).visualize({palette: ['AAAAAA']}),
  // Visualize the other bare areas as white.
  bare1.updateMask(bare1).visualize({palette: ['FFFFFF']}),
]).mosaic();
Map.addLayer(mosaic, {}, 'Visualization mosaic');

Consulta la página Entorno de Python para obtener información sobre la API de Python y el uso de geemap para el desarrollo interactivo.

import ee
import geemap.core as geemap
# Load a NAIP quarter quad, display.
naip = ee.Image('USDA/NAIP/DOQQ/m_4207148_nw_19_1_20120710')
m = geemap.Map()
m.set_center(-71.0915, 42.3443, 14)
m.add_layer(naip, {}, 'NAIP DOQQ')

# Create the NDVI and NDWI spectral indices.
ndvi = naip.normalizedDifference(['N', 'R'])
ndwi = naip.normalizedDifference(['G', 'N'])

# Create some binary images from thresholds on the indices.
# This threshold is designed to detect bare land.
bare_1 = ndvi.lt(0.2).And(ndwi.lt(0.3))
# This detects bare land with lower sensitivity. It also detects shadows.
bare_2 = ndvi.lt(0.2).And(ndwi.lt(0.8))

# Mask and mosaic visualization images. The last layer is on top.
mosaic = ee.ImageCollection([
    # NDWI > 0.5 is water. Visualize it with a blue palette.
    ndwi.updateMask(ndwi.gte(0.5)).visualize(
        min=0.5, max=1, palette=['00FFFF', '0000FF']
    ),
    # NDVI > 0.2 is vegetation. Visualize it with a green palette.
    ndvi.updateMask(ndvi.gte(0.2)).visualize(
        min=-1, max=1, palette=['FF0000', '00FF00']
    ),
    # Visualize bare areas with shadow (bare_2 but not bare_1) as gray.
    bare_2.updateMask(bare_2.And(bare_1.Not())).visualize(palette=['AAAAAA']),
    # Visualize the other bare areas as white.
    bare_1.updateMask(bare_1).visualize(palette=['FFFFFF']),
]).mosaic()
m.add_layer(mosaic, {}, 'Visualization mosaic')
m

Para crear un compuesto que maximice una banda arbitraria en la entrada, usa imageCollection.qualityMosaic(). El método qualityMosaic() establece cada píxel en el compuesto según qué imagen de la colección tiene un valor máximo para la banda especificada. Por ejemplo, el siguiente código muestra cómo crear un compuesto de píxeles más verde y un compuesto de valor reciente:

// Define a function that scales and masks Landsat 8 surface reflectance images.
function prepSrL8(image) {
  // Develop masks for unwanted pixels (fill, cloud, 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 getFactorImg = function(factorNames) {
    var factorList = image.toDictionary().select(factorNames).values();
    return ee.Image.constant(factorList);
  };
  var scaleImg = getFactorImg([
    'REFLECTANCE_MULT_BAND_.|TEMPERATURE_MULT_BAND_ST_B10']);
  var offsetImg = getFactorImg([
    'REFLECTANCE_ADD_BAND_.|TEMPERATURE_ADD_BAND_ST_B10']);
  var scaled = image.select('SR_B.|ST_B10').multiply(scaleImg).add(offsetImg);

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

// This function masks clouds and adds quality bands to Landsat 8 images.
var addQualityBands = function(image) {
  // Normalized difference vegetation index.
  var ndvi = image.normalizedDifference(['SR_B5', 'SR_B4']);
  // Image timestamp as milliseconds since Unix epoch.
  var millis = ee.Image(image.getNumber('system:time_start'))
                   .rename('millis').toFloat();
  return prepSrL8(image).addBands([ndvi, millis]);
};

// Load a 2014 Landsat 8 ImageCollection.
// Map the cloud masking and quality band function over the collection.
var collection = ee.ImageCollection('LANDSAT/LC08/C02/T1_L2')
  .filterDate('2014-06-01', '2014-12-31')
  .map(addQualityBands);

// Create a cloud-free, most recent value composite.
var recentValueComposite = collection.qualityMosaic('millis');

// Create a greenest pixel composite.
var greenestPixelComposite = collection.qualityMosaic('nd');

// Display the results.
Map.setCenter(-122.374, 37.8239, 12); // San Francisco Bay
var vizParams = {bands: ['SR_B5', 'SR_B4', 'SR_B3'], min: 0, max: 0.4};
Map.addLayer(recentValueComposite, vizParams, 'Recent value composite');
Map.addLayer(greenestPixelComposite, vizParams, 'Greenest pixel composite');

// Compare to a cloudy image in the collection.
var cloudy = ee.Image('LANDSAT/LC08/C02/T1_TOA/LC08_044034_20140825');
Map.addLayer(cloudy, {bands: ['B5', 'B4', 'B3'], min: 0, max: 0.4}, 'Cloudy');

Consulta la página Entorno de Python para obtener información sobre la API de Python y el uso de geemap para el desarrollo interactivo.

import ee
import geemap.core as geemap
# Define a function that scales and masks Landsat 8 surface reflectance images.
def prep_sr_l8(image):
  # Develop masks for unwanted pixels (fill, cloud, cloud shadow).
  qa_mask = image.select('QA_PIXEL').bitwiseAnd(int('11111', 2)).eq(0)
  saturation_mask = image.select('QA_RADSAT').eq(0)

  # Helper function to create image from scaling factors.
  def get_factor_img(factor_names):
    factor_list = image.toDictionary().select(factor_names).values()
    return ee.Image.constant(factor_list)

  # Apply the scaling factors to the appropriate bands.
  scale_img = get_factor_img(
      ['REFLECTANCE_MULT_BAND_.|TEMPERATURE_MULT_BAND_ST_B10']
  )
  offset_img = get_factor_img(
      ['REFLECTANCE_ADD_BAND_.|TEMPERATURE_ADD_BAND_ST_B10']
  )
  scaled = image.select('SR_B.|ST_B10').multiply(scale_img).add(offset_img)

  # Replace original bands with scaled bands and apply masks.
  return (
      image.addBands(scaled, None, True)
      .updateMask(qa_mask)
      .updateMask(saturation_mask)
  )


# This function masks clouds and adds quality bands to Landsat 8 images.
def add_quality_bands(image):
  # Normalized difference vegetation index.
  ndvi = image.normalizedDifference(['SR_B5', 'SR_B4'])
  # Image timestamp as milliseconds since Unix epoch.
  millis = (
      ee.Image(image.getNumber('system:time_start')).rename('millis').toFloat()
  )
  return prep_sr_l8(image).addBands([ndvi, millis])


# Load a 2014 Landsat 8 ImageCollection.
# Map the cloud masking and quality band function over the collection.
collection = (
    ee.ImageCollection('LANDSAT/LC08/C02/T1_L2')
    .filterDate('2014-06-01', '2014-12-31')
    .map(add_quality_bands)
)

# Create a cloud-free, most recent value composite.
recent_value_composite = collection.qualityMosaic('millis')

# Create a greenest pixel composite.
greenest_pixel_composite = collection.qualityMosaic('nd')

# Display the results.
m = geemap.Map()
m.set_center(-122.374, 37.8239, 12)  # San Francisco Bay
viz_params = {'bands': ['SR_B5', 'SR_B4', 'SR_B3'], 'min': 0, 'max': 0.4}
m.add_layer(recent_value_composite, viz_params, 'Recent value composite')
m.add_layer(greenest_pixel_composite, viz_params, 'Greenest pixel composite')

# Compare to a cloudy image in the collection.
cloudy = ee.Image('LANDSAT/LC08/C02/T1_TOA/LC08_044034_20140825')
m.add_layer(
    cloudy, {'bands': ['B5', 'B4', 'B3'], 'min': 0, 'max': 0.4}, 'Cloudy'
)
m

Usa la herramienta de inspector para verificar los valores de píxeles en diferentes ubicaciones de los compuestos. Observa que la banda millis (marca de tiempo) varía según la ubicación, lo que indica que los píxeles diferentes provienen de diferentes momentos.