4

I have script that calculte mean NDVI values for a given geometry ,creates layers for every year with those NDVI values and then print it. The problems are:

  1. When I print the number of pixels that were found, I get only one number, instead of number for every year
  2. I would like to get it as table so for every year I get the number of pixels that their value is higher than 0.3/0.4/0.5

this is my code:

var geometry=Mexico_city;
Map.centerObject(geometry,10);

/**
 * Function to mask clouds based on the pixel_qa band of Landsat 8 SR data.
 * @param {ee.Image} image input Landsat 8 SR image
 * @return {ee.Image} cloudmasked Landsat 8 image
 */
function maskL8sr(image) {
  // Bits 3 and 5 are cloud shadow and cloud, respectively.
  var cloudShadowBitMask = (1 << 3);
  var cloudsBitMask = (1 << 5);
  // Get the pixel QA band.
  var qa = image.select('pixel_qa');
  // Both flags should be set to zero, indicating clear conditions.
  var mask = qa.bitwiseAnd(cloudShadowBitMask).eq(0)
                 .and(qa.bitwiseAnd(cloudsBitMask).eq(0));
  return image.updateMask(mask);
}

var dataset = ee.ImageCollection('LANDSAT/LC08/C01/T1_SR')
                  .filterDate('2013-01-01', '2019-12-02')
                  .select('B4', 'B5','pixel_qa')
                  .filterBounds(geometry)
                  .map(maskL8sr);

//clip the dataset according to the geometry
var clippedCol=dataset.map(function(im){ 
  return im.clip(geometry);
});

// Get the number of images.
var count = clippedCol.size();
print('Count: ',count);


//function to calculate NDVI in LANDSAT8

var addNDVI = function(image) {
  var NDVI = image.normalizedDifference(['B5', 'B4'])
  .rename('NDVI')
  .copyProperties(image,['system:time_start']);
  return image.addBands(NDVI);

};

//NDVI to the clipped image collection
var withNDVI = clippedCol.map(addNDVI).select('NDVI');

var NDVIcolor = {
  min: 0,
  max:1,
  palette: ['FFFFFF', 'CE7E45', 'DF923D', 'F1B555', 'FCD163', '99B718', '74A901',
    '66A000', '529400', '3E8601', '207401', '056201', '004C00', '023B01',
    '012E01', '011D01', '011301'],
};



//Filter according to number of pixels

var ndviWithCount = withNDVI.map(function(image){
  var countpixels = ee.Number(image.reduceRegion({
  reducer: ee.Reducer.count(),
  geometry: geometry,
  crs: 'EPSG:4326',
  scale: 30,
  }).get('NDVI'));

  return image.set('count', countpixels);
});


print('NDVIwithCount:',ndviWithCount);

var max = ndviWithCount.reduceColumns(ee.Reducer.max(),  ["count"]);
print(max.get('max'));
var max_number=(max.get('max'));


//filter between a range
var filter = ndviWithCount.filter(ee.Filter.rangeContains(
          'count',1165989, 1765989));
print(filter, 'filtered');

// Declare years of interest
var years = ee.List.sequence(2013, 2019);

// Map a function to select data within the year and apply mean reducer
var byYear = ee.ImageCollection.fromImages(
    years.map(function(y) {
      return filter
        .filter(ee.Filter.calendarRange(y, y, 'year'))
        .reduce(ee.Reducer.mean())
        .set('year', y);
    })
  );

  // Look at your output: number of elemnts should be like number of years  
print(byYear, "byYear");




var listOfImages =(byYear.toList(byYear.size()));

var NumberOfImages=listOfImages.size();

print('number of images',NumberOfImages);

var listOfNumbers = ee.List.sequence(0,NumberOfImages.subtract(2));
listOfNumbers = listOfNumbers.map(function(n) {
  return ee.Number(n).add(1);
});

listOfNumbers=listOfNumbers.getInfo();



for (var i in listOfNumbers) {
  var image = ee.Image(listOfImages.get(listOfNumbers[i]));
  var toexport=image.visualize(NDVIcolor).addBands(image);


  // do what ever you need with image
  Map.addLayer(image, NDVIcolor, i);
//   Export.image.toDrive({
//   image: toexport.toFloat(),
//   description: i,
//   scale:30,
//   crs:'EPSG:4326',
//   maxPixels:1310361348,
//   region:geometry.geometry().bounds()

// });


 }

 print(ui.Chart.image.series(byYear, geometry, ee.Reducer.mean(), 30, 'year'));

 //Count of Vegetation pixels
// Make an image of NDVI > 0.3 


// var gt03 = meanImage.gt(0.3).selfMask().rename('NDVI_gt03');
// Map.addLayer(gt03,ndviParams,'gt03');

for (var i in listOfNumbers) {
  var image = ee.Image(listOfImages.get(listOfNumbers[i]));
  var gt03 = image.gt(0.3).selfMask().rename('NDVI_gt03');
  Map.addLayer(gt03,NDVIcolor,'NDVI 0.3' + i);
  //count the number of total pixels
  var c03 = gt03.reduceRegion({
  reducer: ee.Reducer.count(),
  geometry: geometry,
  crs: 'EPSG:4326',
  scale: 30,
  });

}

for (var i in listOfNumbers) {
  var image = ee.Image(listOfImages.get(listOfNumbers[i]));
  var gt04 = image.gt(0.4).selfMask().rename('NDVI_gt04');
  Map.addLayer(gt03,NDVIcolor,'NDVI 0.4' + i);
  //count the number of total pixels
  var c04 = gt03.reduceRegion({
  reducer: ee.Reducer.count(),
  geometry: geometry,
  crs: 'EPSG:4326',
  scale: 30,
  });

}

for (var i in listOfNumbers) {
  var image = ee.Image(listOfImages.get(listOfNumbers[i]));
  var gt05 = image.gt(0.5).selfMask().rename('NDVI_gt05');
  Map.addLayer(gt03,NDVIcolor,'NDVI 0.5' + i);
  //count the number of total pixels
  var c05 = gt03.reduceRegion({
  reducer: ee.Reducer.count(),
  geometry: geometry,
  crs: 'EPSG:4326',
  scale: 30,
  });

}

print('NDVI gt03:',c03);
print('NDVI gt04:',c04);
print('NDVI gt05:',c05);

1 Answer 1

2

Don't use the for loops, map over the numbers as you did while constructing the yearly mosaics and map over the images to do that for each individual image. For example, you could do this immediately while you are mapping over the yearly composites.

// Declare years of interest
var years = ee.List.sequence(2013, 2019);
var gtNumbers = ee.List.sequence(0.3, 0.5,0.1);
var gtNames = ee.List(['NDVI_gt03','NDVI_gt04','NDVI_gt05']);

// Map a function to select data within the year and apply mean reducer
var byYear = ee.ImageCollection.fromImages(
    years.map(function(y) {
      var image = withNDVI.filter(ee.Filter.calendarRange(y, y, 'year'))
        .mean().set('year', y);
        // map over the gt numbers
        var data = gtNumbers.map(function(number){
          var count = image.gt(ee.Number(number)).selfMask()
          //count the number of total pixels
                    .reduceRegion({
                      reducer: ee.Reducer.count(),
                      geometry: geometry,
                      crs: 'EPSG:4326',
                      scale: 30,
          });
          return count.values().get(0); 
        });
        // rewrite the data output
        data = ee.Dictionary.fromLists(gtNames, data)
      return image.set(data);
    })
  );

  // Look at your output: number of elemnts should be like number of years  
print(byYear, "byYear");

Next time, please reduce your code to only the necessary for the actual problem. Here is a link to the full code. Note that I reduced some code and made a sample geometry.

4
  • @kulik thank you for the answer, i'll writ eit different next time. Trying to understand your script: where am I supppose to see the output of number of pixels gt x for each image? and what get(0) relates to? and why did you add the number of total pixels? (or do you mean total pixels gt than 0.3,0.4...)
    – ReutKeller
    Dec 3, 2019 at 15:29
  • The properties of each image has the number of pixels. The properties are named 'NDVI_gt03','NDVI_gt04','NDVI_gt05'. reduceRegion() returns a dictionary. If you apply .values().get(0) you will get the first value of that dictionary (and as there is only value, you can safely use get(0)).
    – Kuik
    Dec 3, 2019 at 17:12
  • @kulik im still confused because I don't know how from this code I can get for each image (which is the mean from the year) the 3 pixels count
    – ReutKeller
    Dec 9, 2019 at 10:27
  • Here are two examples: link
    – Kuik
    Dec 9, 2019 at 17:30

Your Answer

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

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