3

I have the following code (very basic as I am new user), and I want to create an NDVI difference collection by subtracting every NDVI image from my initial collection, with its previous one (something like NDVI2-NDVI1,NDVI3-NDVI2,...). After that, I want to do some thresholding and assign specific values, but I do not know how to do this.

My attempt:

var imageCollection = ee.ImageCollection("MODIS/006/MCD43A4")
 .filterBounds(geometry)
    .map(function(image){return image.clip(geometry)})
      .filterDate('2005-07-01','2005-08-31');
   var NDVIbands = imageCollection.select("Nadir_Reflectance_Band2","Nadir_Reflectance_Band1","BRDF_Albedo_Band_Mandatory_Quality_Band1","BRDF_Albedo_Band_Mandatory_Quality_Band2");
   var geometry = /* color: #98ff00 */ee.Geometry.Polygon(
        [[[-53.90538056149785, -3.6610951156347706],
          [-53.860061957982225, -3.959810400282152],
          [-53.362930610325975, -3.8529425805852524],
          [-53.42198212399785, -3.5706383493989544]]]);

var masks = function(image){
  var mask1 = image.select("BRDF_Albedo_Band_Mandatory_Quality_Band1").eq(0);
  var mask2 = image.select("BRDF_Albedo_Band_Mandatory_Quality_Band2").eq(0);
  return image.updateMask(mask1).updateMask(mask2);
};

var filtered = NDVIbands.map(masks);

var myNDVI = function(image) {
  var ndvi = image.normalizedDifference(['Nadir_Reflectance_Band2', 'Nadir_Reflectance_Band1']).rename('NDVI');
  return image.addBands(ndvi);
};

var NDVI = filtered.map(myNDVI);

//From this point, I need your help because I am not familiar with this.

//I do not know how to set the slices in order to subtract every NDVI from its previous
//(like NDVI2-NDVI1,NDVI3-NDVI2,...).Based on what I want, my NDVIdif collection must have
//one element less than the initial NDVI collection.

var NDVIdif = NDVI.slice(,).subtract(NDVI.slice(,))


//And here, I want to create classes based on value-limits but again, I do not know how to do this.

var reclass = function(img) {
  var mclass = img.remap([-0.250 - -0.103,-0.105 - 0.201],[  1,   2],   null, 'reclass dNDVI');    
  return mclass;
};
2

For you first question, it is possibly bet practice to first make a list of a certain property in every image. You can then get every current and previous image based on the value in the list:

// First make a list of a useful numerical property of the image collection 
// and make sure they are ordered by time
var NDVI = filtered.map(myNDVI).sort('system:time_start');
var dateList = ee.List(NDVI.aggregate_array('system:time_start')).slice(1); // remove the first date


// Now map over that list, so we now the index of each image (and thus it's previous)
var NDVIdiff = ee.ImageCollection.fromImages(dateList.map(function(date){

  // get the image corresponding to the date
  var currentImage = NDVI.filter(ee.Filter.eq('system:time_start', date)).first();

  // Now we have to get the 'previous' image in the collection
  var indexCurrent = dateList.indexOf(date);
  var indexPrevious = indexCurrent.subtract(1);
  var datePrevious = dateList.get(indexPrevious);
  var previousImage = NDVI.filter(ee.Filter.eq('system:time_start', datePrevious)).first();

  // Subtract the current image from the previous
  var diffImage = currentImage.subtract(previousImage).select(['NDVI'], ['NDVIdiff']);

  // return the image
  return currentImage.addBands(diffImage)
            .set('system:index_previous', previousImage.get('system:index'));
}));

For the second question, I guess you want the NDVI values in a certain range to be labelled to an integer. An option to do that I show below:

// list of numbers to reclass:
var reclassList = [-0.250, -0.103, 0.201, 0.4, 0.6];

var reclass = function(image) {
  // Map over the list
  var reclass = ee.ImageCollection.fromImages(ee.List(reclassList).sort().map(function(value){
    // every value gt a certain number in the reclass List will be 1. 
    // The returned image will ths be 0 for values lower than the lowest value, and a multiple of ones for every next number
    return image.select('NDVI').gt(ee.Number(value)); // I guess you want to this for the NDVI band?
  }))
  // make a summed image and reproject to the origonal projection of the images
  .reduce('sum').rename('reclassNDVI')
  // eventually reproject into the origonal image projection
  .reproject(image.projection(),null, image.projection().nominalScale()); 

  return image.addBands(reclass);
};

// Run the function and print
var reclassCollection = NDVI.map(reclass);

Link script

  • Hello @Kuik and thank you very much for your answer and very useful comments! I do have a few questions regarding the reclass. Why you only used numbers and not limits(you used 3 numbers from my above mentioned limits and then 2 other numbers 0.4 and 0.6)? My last question, why you make a sum image and reproject? Isn't the map over a collection function works for this kind of things? (e.g. to map the reclass function over the difference ndvi collection). – foo Mar 30 at 9:58
  • 1
    I show you a way to reclassify values in a range of NDVI to integers. There are, off course, multiple other ways. You could apply a similar approach with different limit values on the difference image, if desired. I reproject because when you make a composite (summed in this case), the image looses it's original projection. As stated, re-projecting is not necessary. – Kuik Mar 30 at 11:03
  • Very clear, thank you very much! – foo Mar 30 at 11:16

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.