3

Using the code below, I have filtered my image collection(Landsat images) over the forest regions of India. (Forest regions were found using Hansen image). I have one mean image per month over 6 years from 2013 - 2018. I need to find out and demarcate those regions which have consistently low NDVI value (NDVI<0.25).

Since there are seasonal variations in NDVI value, a pixel corresponding to a particular point can have NDVI value greater or less than 0.25 at different times. So when I give a condition like updateMask(image.lte(0.25)) over a collection of images and then visualizing the regions on the map, I get all those regions where ndvi was less than 0.25 at least once. But I need only those regions where ndvi is less than 0.25 all the time.

What change should I make in my code?

// FILTERING OUT FOREST COVER IN INDIA

var treeCanopyCover = hansen.clip(india).select('treecover2000');
var greater25 = treeCanopyCover.gte(25);


// NDVI FUNCTION

function addNDVI(image) {
var ndvi = image.normalizedDifference(['B5', 'B4']).rename('NDVI');
return image.addBands(ndvi);
}


// FILTERING THE COLLECTION

var startDate = ee.Date('2013-01-01');
var endDate = ee.Date('2018-12-31');
var filtered = l8.filterBounds(india)
      .filterDate(startDate, endDate)
      .filterMetadata('CLOUD_COVER','less_than',25)
      .map(addNDVI);  


var maskedCollection = filtered.map(function(image){
  var x = image.updateMask(greater25);
  return x;
});


// FILTERING MONTHLY WISE OVER YEARS

var map_m = function(y)
{
  y = ee.Number(y);
  var months = ee.List.sequence(1, 12);
  var filtered_col = months.map(function(m) 
{
var filt = maskedCollection.filter(ee.Filter.calendarRange(y, y, 'year'))
                .filter(ee.Filter.calendarRange(m, m, 'month'))
                .mean();

return filt.set('year', y)
      .set('month', m)
      .set('system:time_start',ee.Date.fromYMD(y,m,1)) ;
  });
  return filtered_col;
};

var years = ee.List.sequence(2013, 2018);
var monthlyimages = years.map(map_m).flatten();
var z = ee.ImageCollection(monthlyimages);


// // DISCARDING NULL IMAGES //

var nullimages = z.map(function(image) 
{
  return image.set('count', image.bandNames().length());
})
.filter(ee.Filter.eq('count', 13));


// Finding regions where ndvi is less than 0.25

var ndviViz = {min: 0, max: 0.25, palette: ['red',  'blue']};
var ndviMasked = nullimages.map(function(image){
  image = image.select("NDVI");
  var x = image.updateMask(image.lte(0.25));
  return x;
});
Map.addLayer(ndviMasked.mean(), ndviViz);

I also have a doubt that whether it is right to use ndviMasked.mean() or ndviMasked.mosaic() while adding layer to the map.

2 Answers 2

2

You can use quality mosaic for this purpose (https://developers.google.com/earth-engine/ic_composite_mosaic).

If you calculate a quality mosaic using NDVI band, you get the maximum NDVI over the time series. If the maximum value over the time series is below 0.25, then the pixel was always below that threshold. Once you have the quality mosaic, just mask out those values.

// FILTERING OUT FOREST COVER IN INDIA
var treeCanopyCover = hansen.clip(india).select('treecover2000');
var greater25 = treeCanopyCover.gte(25);

// NDVI FUNCTION
function addNDVI(image) {
var ndvi = image.normalizedDifference(['B5', 'B4']).rename('NDVI');
return image.addBands(ndvi);
}

// FILTERING THE COLLECTION
var startDate = ee.Date('2013-01-01');
var endDate = ee.Date('2018-12-31');
var filtered = l8.filterBounds(india)
      .filterDate(startDate, endDate)
      .filterMetadata('CLOUD_COVER','less_than',25)
      .map(addNDVI);  


var maskedCollection = filtered.map(function(image){
  var x = image.updateMask(greater25);
  return x;
});

// FILTERING MONTHLY WISE OVER YEARS
var map_m = function(y)
{
  y = ee.Number(y);
  var months = ee.List.sequence(1, 12);
  var filtered_col = months.map(function(m) 
{
var filt = maskedCollection.filter(ee.Filter.calendarRange(y, y, 'year'))
                .filter(ee.Filter.calendarRange(m, m, 'month'))
                .mean();

return filt.set('year', y)
      .set('month', m)
      .set('system:time_start',ee.Date.fromYMD(y,m,1)) ;
  });
  return filtered_col;
};

var years = ee.List.sequence(2013, 2018);
var monthlyimages = years.map(map_m).flatten();
var z = ee.ImageCollection(monthlyimages);


// // DISCARDING NULL IMAGES //
var nullimages = z.map(function(image) 
{
  return image.set('count', image.bandNames().length());
})
.filter(ee.Filter.eq('count', 13));

// get quality mosiac using NDVI band
var qm = nullimages.qualityMosaic('NDVI');

// have a look at the quality mosaic
var ndvi_viz = {bands:'NDVI', min:-0.2, max:1, palette:['green', 'orange','red']};
Map.addLayer(qm, ndvi_viz, 'quality mosaic');

// let´s mask out values below 0.25
var mask = qm.select('NDVI').lt(0.25);
var ndviMasked = qm.updateMask(mask);

// have a look at the final result (few pixels)
var ndvi_viz2 = {bands:'NDVI', min:-0.2, max:0.25, palette:['grey', 'white','blue']};
Map.addLayer(ndviMasked, ndvi_viz2, 'masked');
1
  • Exactly! This was what I needed. Thanks a lot. This gives me a map which is almost blank which I think is justifiable because the number of pixels with an NDVI value consistently less than 0.25 will be very less in forest regions. Anyways, thank you very much. Dec 21, 2020 at 17:59
0

Simply replace ndviMasked.mean() with ndviMasked.min()

1
  • No, this doesn't solve my problem. My problem is that the same regions are being marked as having NDVI value less than as well as greater than 0.25. Jul 8, 2019 at 4:56

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

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