resolutiongoogle-earth-enginelandsat

How to reduce the spatial resolution of an image collection in Google Earth Engine?


Good Day

Please may you kindly assist me with the following.

I am attempting to generate a time series of NDVI estimates using Landsat 7 and 8 for a particular region of interest (ROI). I would then like to compare these estimates against NDVI values that are acquired from the MODIS 16-day NDVI composite. While, I am familiar with how to acquire the mean Landsat NDVI values for my ROI at the Landsat spatial resolution (30 m), I would like to aggregate the pixels from this resolution to the MODIS NDVI product resolution (500 m).

I have attempted to do this in the code provided below based on an example provided at https://developers.google.com/earth-engine/guides/resample but I have been unsuccessful in my attempts. I receive the error "ndvi.reduceResolution is not a function"

Do I need to create a function for this instead and map it over the image collection or should I just specify the scale that I would like the averaging to be performed at when charting or exporting the data as a csv?

Many thanks in advance.

///Add region of interest
var ROI = ROI
Map.addLayer(ROI, {}, 'ROI')
Map.centerObject(ROI, 10)

//Define time of interest
// Ensure that the first image that is collected possesses data to calculate NDVI otherwise the script will not work as required
var startdate = '2013-01-01' 
var enddate = '2021-01-01' 

var years = ee.List.sequence(ee.Date(startdate).get('year'), ee.Date(enddate).get('year'));

///Create functions to mask clouds
/// see: https://landsat.usgs.gov/sites/default/files/documents/landsat_QA_tools_userguide.pdf

///This function masks clouds in Landsat 7 imagery.
function maskL7(im) {
  var qa = im.select('BQA');
  var mask = qa.eq(672);
  return im.updateMask(mask).copyProperties(im);
}

///This function masks clouds in Landsat 8 imagery.
function maskL8(im) {
  var qa = im.select('BQA');
  var mask = qa.eq(2720);
  return im.updateMask(mask).copyProperties(im);
}

///Import image collections, filter by date and ROI, apply cloud mask and clip to ROI

///Landsat 7 Collection 1 Tier 1 calibrated top-of-atmosphere (TOA) reflectance
var ls7toa = ee.ImageCollection('LANDSAT/LE07/C01/T1_TOA')
  .filterBounds(ROI)
    .filterDate(startdate, enddate)
      .map(function(im) {return maskL7(im)})
        .map(function(image){return image.clip(ROI)})

///Landsat 8 Collection 1 Tier 1 calibrated top-of-atmosphere (TOA) reflectance
var ls8toa = ee.ImageCollection('LANDSAT/LC08/C01/T1_TOA')
.filterBounds(ROI)
  .filterDate(startdate, enddate)
    .map(function(im) {return maskL8(im)})
      .map(function(image){return image.clip(ROI)})

///Create function to calculate NDVI using Landsat data
    
///Calculate NDVI for Landsat 7
var ls7_ndvi = ls7toa.map(function(image) {
  var ndvi = image.normalizedDifference(['B4', 'B3']).rename('ndvi');
  return image.addBands(ndvi);
});

///Calculate NDVI for Landsat 8
var ls8_ndvi = ls8toa.map(function(image) {
  var ndvi = image.normalizedDifference(['B5', 'B4']).rename('ndvi');
  return image.addBands(ndvi);
});

///Merge the image collections into one and only select the NDVI data
var landsat = ee.ImageCollection(ls7_ndvi.merge(ls8_ndvi));
var ndvi = landsat.select(['ndvi'])
print(ndvi, 'ndvi')

// Load a MODIS NDVI Collection
var modis = ee.Image(ee.ImageCollection("MODIS/006/MOD13A1")
            .first()
              .select('NDVI'))
                    
// Get information about the MODIS projection.
var modisProjection = modis.projection();
print('MODIS projection:', modisProjection);

// Get the Landsat NDVI collection at MODIS scale and projection.
var ndviMean = ndvi
    // Force the next reprojection to aggregate instead of resampling.
    .reduceResolution({
      reducer: ee.Reducer.mean(),
    })
    // Request the data at the scale and projection of the MODIS image.
    .reproject({
      crs: modisProjection
    });
                    
///Create a timer-series plot of NDVI
var chart = ui.Chart.image.series({
    imageCollection: ndviMean,
    region: ROI,
    reducer: ee.Reducer.mean(),
    scale: 500,
})

print(chart, "ndvi") 

Solution

  • Indeed, mapping a function over the ImageCollection will do the trick:

    ///Add region of interest
    var ROI = ROI
    Map.addLayer(ROI, {}, 'ROI')
    Map.centerObject(ROI, 10)
    
    //Define time of interest
    // Ensure that the first image that is collected possesses data to calculate NDVI otherwise the script will not work as required
    var startdate = '2013-01-01' 
    var enddate = '2021-01-01' 
    
    var years = ee.List.sequence(ee.Date(startdate).get('year'), ee.Date(enddate).get('year'));
    
    ///Create functions to mask clouds
    /// see: https://landsat.usgs.gov/sites/default/files/documents/landsat_QA_tools_userguide.pdf
    
    ///This function masks clouds in Landsat 7 imagery.
    function maskL7(im) {
      var qa = im.select('BQA');
      var mask = qa.eq(672);
      return im.updateMask(mask).copyProperties(im);
    }
    
    ///This function masks clouds in Landsat 8 imagery.
    function maskL8(im) {
      var qa = im.select('BQA');
      var mask = qa.eq(2720);
      return im.updateMask(mask).copyProperties(im);
    }
    
    ///Import image collections, filter by date and ROI, apply cloud mask and clip to ROI
    
    ///Landsat 7 Collection 1 Tier 1 calibrated top-of-atmosphere (TOA) reflectance
    var ls7toa = ee.ImageCollection('LANDSAT/LE07/C01/T1_TOA')
      .filterBounds(ROI)
        .filterDate(startdate, enddate)
          .map(function(im) {return maskL7(im)})
            .map(function(image){return image.clip(ROI)})
    
    ///Landsat 8 Collection 1 Tier 1 calibrated top-of-atmosphere (TOA) reflectance
    var ls8toa = ee.ImageCollection('LANDSAT/LC08/C01/T1_TOA')
    .filterBounds(ROI)
      .filterDate(startdate, enddate)
        .map(function(im) {return maskL8(im)})
          .map(function(image){return image.clip(ROI)})
    
    ///Create function to calculate NDVI using Landsat data
        
    ///Calculate NDVI for Landsat 7
    var ls7_ndvi = ls7toa.map(function(image) {
      var ndvi = image.normalizedDifference(['B4', 'B3']).rename('ndvi');
      return image.addBands(ndvi);
    });
    
    ///Calculate NDVI for Landsat 8
    var ls8_ndvi = ls8toa.map(function(image) {
      var ndvi = image.normalizedDifference(['B5', 'B4']).rename('ndvi');
      return image.addBands(ndvi);
    });
    
    ///Merge the image collections into one and only select the NDVI data
    var landsat = ee.ImageCollection(ls7_ndvi.merge(ls8_ndvi));
    var ndvi = landsat.select(['ndvi'])
    print(ndvi, 'ndvi')
    
    // Load a MODIS NDVI Collection
    var modis = ee.Image(ee.ImageCollection("MODIS/006/MOD13A1")
                .first()
                  .select('NDVI'))
                        
    // Get information about the MODIS projection.
    var modisProjection = modis.projection();
    print('MODIS projection:', modisProjection);
    
    // Get the Landsat NDVI collection at MODIS scale and projection.
    var landsat_pro = ndvi.first().projection();    
    var CopyScale = landsat_pro.nominalScale();
    print(CopyScale, 'original scale Landsat (m)')
    
    var landsat_resample = function(image){
      return image.reproject(landsat_pro, null, 500) // insert here the desired scale in meters
    
        // Force the next reprojection to aggregate instead of resampling.
        .reduceResolution({
          reducer: ee.Reducer.mean(),
          maxPixels: 1024
        })
      .copyProperties(image)
    }
    
    var ndviResample = ndvi.map(landsat_resample)
                        
    ///Create a timer-series plot of NDVI
    var chart = ui.Chart.image.series({
        imageCollection: ndviResample,
        region: ROI,
        reducer: ee.Reducer.mean(),
        scale: 500,
    })
    
    print(chart, "ndvi")