Getting Image with highest max Scene NDVI from Image collection using Google Earth Engine

google-earth-engineimage-mosaicndvi

I have a code that computes NDVI but I want help on how can I get the image and date with the highest NDVI within the collection. I am still new to GEE I saw a couple of codes but I failed to understand them.

    /// Filtering the image collection
var filtered =  S2A.filterBounds(geometry)
                   .filterDate('2021-02-18','2021-04-30')
                   //.sort('CLOUD_COVERAGE_ASSESSMENT', false)
                   .filterMetadata('CLOUDY_PIXEL_PERCENTAGE', 'less_than', 10);
                  
                   
// testing the collection                   
print(filtered);            
          

  ///// computing kNDVI using a function
   var addKNDVI = function(img){
     
  var RED = img.select('B4');
  var NIR = img.select('B8');
  
  // Compute D2 a rename it to d2
  var D2 = NIR.subtract(RED).pow(2)
  .select([0],['d2']);
  
  // Gamma, defined as 1/sigmaˆ2
  var gamma = ee.Number(4e6).multiply(-2.0);
  
  // Compute kernel (k) and KNDVI
  var k = D2.divide(gamma).exp();
  var kndvi = ee.Image.constant(1)
  .subtract(k).divide(ee.Image.constant(1).add(k))
  .select([0],['kndvi']);
  return img.addBands(kndvi).clip(geometry);
  
};
  
            
  ////// maping the whole collection using function
  var with_kndvi = filtered.map(addKNDVI);
  var greenest  = with_kndvi.qualityMosaic('kndvi');

  

  Map.addLayer(with_kndvi,{min:2, max:5, },'kndvi' );
  Map.centerObject(geometry,8);
            

Best Answer

It is unclear whether you want a single image date that represents e.g. the max mean KNDVI within the region of interest or a composite image of the pixels in the time series that are the max KNDVI with an associated date band attached. The answer below includes both. The chunks of code following UPPER CASE comments are edits.

In the mapped function to calculate and add the KNDVI band, an additional band that represents the image timestamp (milliseconds from unix epoch) is added for tracking the dates of the pixels in the time series with max KNDVI. The mean KNDVI region reduction is also added as a property of each image, so that the image with the greatest mean KNDVI can be filtered out later.

var geometry = ee.Geometry.Polygon(
        [[[-122.19836689612622, 37.22349241589311],
          [-122.19836689612622, 37.08229558939655],
          [-122.00335957190747, 37.08229558939655],
          [-122.00335957190747, 37.22349241589311]]], null, false);

// DATES OF INTEREST
var startDate = new Date('2021-02-18');
var endDate = new Date('2021-04-30');
var startDateMillis = startDate.getTime(); // FOR DATE VISUALIZATION
var endDateMillis = endDate.getTime(); // FOR DATE VISUALIZATION

// Filtering the image collection
var filtered =  ee.ImageCollection("COPERNICUS/S2_SR").filterBounds(geometry)
                   .filterDate(startDate, endDate)
                   //.sort('CLOUD_COVERAGE_ASSESSMENT', false)
                   .filterMetadata('CLOUDY_PIXEL_PERCENTAGE', 'less_than', 10);
                  
// testing the collection                   
print(filtered);            
          
// computing kNDVI using a function
var addKNDVI = function(img){
     
  var RED = img.select('B4');
  var NIR = img.select('B8');
  
  // Compute D2 a rename it to d2
  var D2 = NIR.subtract(RED).pow(2)
  .select([0],['d2']);
  
  // Gamma, defined as 1/sigmaˆ2
  var gamma = ee.Number(4e6).multiply(-2.0);
  
  // Compute kernel (k) and KNDVI
  var k = D2.divide(gamma).exp();
  var kndvi = ee.Image.constant(1)
    .subtract(k).divide(ee.Image.constant(1).add(k))
    .select([0],['kndvi']);
  
  // MAKE A DATE BAND IN UNIX TIME (MILLISECONDS FROM UNIX EPOCH)
  var dateBand = ee.Image(img.date().millis()).toLong().rename('millis');
  
  // CALCULATE THE MEAN KNDVI WITHIN THE GEOMETRTY
  var kndviMean = kndvi.reduceRegion({
    reducer: ee.Reducer.mean(),
    geometry: geometry,
    scale: 20,
    bestEffort: true,
    maxPixels: 1e13
  });
  
  // ADD KNDIV & DATE BANDS, SET KNDVI GEOMETRY MEAN AS A PROPERTY
  return img.addBands(ee.Image([kndvi, dateBand])).set(kndviMean);
};

// maping the whole collection using function
var with_kndvi = filtered.map(addKNDVI);
var greenest  = with_kndvi.qualityMosaic('kndvi');

// FETCH THE MAX MEAN KNDVI IMAGE FROM THE WITH_KNDVI COLLECTION
var maxKndviMean = with_kndvi.reduceColumns({
  reducer: ee.Reducer.max(), selectors: ['kndvi']});
var maxKndviMeanImg = with_kndvi.filter(
  ee.Filter.eq('kndvi', maxKndviMean.get('max'))).first();
print('Mean max KNDVI image', maxKndviMeanImg);

Map.addLayer(with_kndvi,
  {bands: ['kndvi'], min: 0.051, max: 0.756, palette: ['white', 'darkgreen']},
  'kndvi');
Map.addLayer(greenest,
  {bands: ['millis'], min: startDateMillis, max: endDateMillis},
  'greenest day (milliseconds)');
Map.addLayer(maxKndviMeanImg,
  {bands: ['B11', 'B8', 'B3'], min: 0, max: 3500},
  'Mean max KNDVI image');
Map.centerObject(geometry, 10);