[GIS] Count the number of pixels according to their value using for loop

countfunctiongoogle-earth-enginelooppixel

I have script that does the enxt procedures:

  1. create imagecollection from Landsat7
  2. clip the images according to specific geometry and calculte NDVI for each one
  3. filter the rasters according to the number of pixels (I don't want to have small rasters)
  4. creates images by calculte for each year the mean NDVI value.
  5. Creates timeseries graph based on years.

Now I want to create the 6th step which is to calculte for each raster how many pixels got NDVI value greater than 3. because I have one image per year I want to create a for loop that will count those pixels for each year and will produce a table.
I have written a code but it is not good because it seems like javascript doesn't understand that "i" is image. also, I don't think this code will prosuce a table in the end.

This is my code:

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

// 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);
    })
  );

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

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

print(c03,year);
}

The wrror message:

i.gt is not a function

*I don't understand this error, because this code works when I do it on one image so why here it can't?

*maybe instead of lop I should use function? then what is the differences between them?

My end goal: To get a table or any calculation which shows for each year the number of pixels that were found in my raster with value higher than 0.3

Best Answer

I suggest you always include a link to a working EE script when posting a question. It makes it easier to help you. You're trying to do something like this, right?

var listOfImages = years.map(function(y) {
  y = ee.Number(y)
  var image = collection
    .filterDate(
      ee.Date.fromYMD(y, 1, 1), 
      ee.Date.fromYMD(y.add(1), 1, 1)
    )
    .map(maskClouds)
    .reduce(ee.Reducer.mean()) // .median() might be better here...
    .select(['B3.*', 'B4.*'], ['B3', 'B4'])
  var ndvi = image
    .normalizedDifference(['B3', 'B4'])
    .rename('ndvi')
  return ndvi
    .updateMask(ndvi.gt(0.3))
    .set('year', y);
})


var counts = listOfImages.iterate(function (image, acc) {
  image = ee.Image(image)
  acc = ee.FeatureCollection(acc)
  var count = image.reduceRegion({
    reducer: ee.Reducer.count(),
    geometry: geometry,
    crs: 'EPSG:4326',
    scale: 30,
  }).get('ndvi')
  return acc.merge(ee.FeatureCollection([
    ee.Feature(null, {year: image.get('year'), count: count})
  ]))
}, ee.FeatureCollection([]))

var chart = ui.Chart.feature.byFeature(counts, 'year', 'count')
print(chart)

https://code.earthengine.google.com/7c9bf82c0aeeeed71ba25808b83a1251

You should be careful when using client-side looping in your scripts - unless you really know what you're doing. Using EE functions like map() and iterate() is usually the right thing to do.

Related Question