2

My goal is to Filter an ImageCollection to contain only Images with uniform coverage within a given AOI (Images that have to 'holes' / masked pixels within an AOI). I'm trying to do it by mapping the collection over ee.Reducer.allNonZero() setting isNotEmpty flag and then filtering images by corresponding flags.

This is a script I created (EE code version):

var NO2_coll = ee.ImageCollection("COPERNICUS/S5P/OFFL/L3_NO2")
                .select('tropospheric_NO2_column_number_density');

var aoi = ee.Geometry.Polygon(ee.List([
  [9.18804289906566, 45.468566496899996], [10.203754688320892, 45.468566496899996], 
  [10.203754688320892,45.695567257444594], [9.18804289906566, 45.695567257444594],
  [9.18804289906566, 45.468566496899996]]));

var date_from = '2020-01-04';
var date_to = '2020-01-05'; 

function setEmptyFlag (image) {
  var isNotEmpty = image.reduceRegion({
    reducer: ee.Reducer.allNonZero(),
    geometry: aoi,
    scale: 7000,
  }).values().get(0);

  return image.set('isNotEmpty', isNotEmpty);
}

var coll_filt = NO2_coll.filterBounds(aoi).filter(ee.Filter.date(date_from, date_to));

var coll_with_zero_flag = coll_filt.map(setEmptyFlag);

var coll_filt_clean = coll_with_zero_flag.filterMetadata('isNotEmpty', 'equals', 1);

var single_scene = coll_filt_clean.first();

Map.addLayer(aoi);
Map.addLayer(single_scene);
Map.centerObject(aoi);

But ee.Reducer.allNonZero() always returnes '1' no matter the presence of masked pixels within AOI.

How do I fix it?

Basile
  • 3,543
  • 3
  • 21
  • 49

1 Answers1

1

Not sure if this is what you are looking for, but similarly I was once searching for images which cover my study area with a user-defined number of pixels. Therefore, I estimated the percentage of pixels covering the aoi. I think this might help you achieving your goal.

// Function to filter out images which do not fully cover the study area
function getCover(image, aoi, scale) {

    // calculate the number of inputs 
    var totPixels = ee.Number(image.unmask(1).reduceRegion({
      reducer: ee.Reducer.count(),
      scale: scale,
      geometry: aoi,
    }).values().get(0));

    // Calculate the actual amount of pixels inside the aoi
    var actPixels = ee.Number(image.reduceRegion({
      reducer: ee.Reducer.count(),
      scale: scale,
      geometry: aoi,    
    }).values().get(0));

    // calculate the perc of cover
    var percCover = actPixels.divide(totPixels).multiply(100).round();

  // number as output
  return image.set('percCover', percCover);
}

var coll_filt = NO2_coll.filterBounds(aoi).filter(ee.Filter.date(date_from, date_to));

var coll_with_zero_flag = coll_filt.map(function(image){
  return getCover(image, aoi, 7000);
});

print('List of percentage of covers',coll_with_zero_flag.aggregate_array('percCover'))

You can then set a minimum percentage to filter your image collection. link code

EDIT: Note that if you have a bounded image, unmask() does not add pixels outside the image area. See here for another example.

Kuik
  • 10,043
  • 1
  • 12
  • 19
  • Thank you, @Kuik, this is pretty close! Could you just explain why ee.Reducer.allNonZero() is not a right tool for this? – Basile Mar 19 '20 at 05:51