0

I am trying to iterate over a feature collection which has 10 features located away from each other and does not necessarily fall in same scene of satellite image. So what I want is to to call each feature separately, according to some month and the selected feature, filter images from image collection and perform some indices (NDVI, NDWI, etc.), stack those outputs to one image and return that image for each feature.

Edit:

var villages =  ee.FeatureCollection("users/ishwarn/PosterMap_blocks");
var landsat7 = ee.ImageCollection("LANDSAT/LE07/C02/T1_L2");
var months = ee.List([11,12,1,2,3,4])
var vil_list = villages.toList(villages.size());
var startDate = "2000-11-01",
    endDate = "2001-04-30"
var l7Col = landsat7
              .filterBounds(villages)
              .filterDate(startDate, endDate);
print(l7Col.first().get('DATE_ACQUIRED'))   

// Function: Calculating indices for image collection
var calc_indices = function(image){
  var image = ee.Image(image);
  var ndvi = image.normalizedDifference(["SR_B4","SR_B3"]).rename('ndvi');
  var ndwi = image.normalizedDifference(["SR_B2","SR_B4"]).rename('ndwi');
  var ndbi = image.normalizedDifference(["SR_B5","SR_B4"]).rename('ndbi');
  var newbands = ee.Image([ndvi, ndwi, ndbi]);
  return newbands.set('system:index', image.get('DATE_ACQUIRED'));
};

// Function2: Month filter to calculate median for month
var monthwise = function(month){
  var l7median = l7Col.filter(ee.Filter.calendarRange(month, month, 'month'))
                        .filterBounds(villages)
                        .median();
  return l7median;                      
}
// print(monthwise)

// Iterating over feature collection
var filter_img = function(feature) {
  var geometry = feature.geometry() // Geometry for each feature
  var monthlyMedian = months.map(monthwise);
  var indices = monthlyMedian.map(calc_indices)
  return ee.ImageCollection(indices)
}
              
var ndviCol = ee.ImageCollection(villages.iterate(filter_img));
print(ndviCol);

var n = ndviCol.size();
var ndvi_list = ndviCol.toList(n);

Map.addLayer(ee.Image(ndvi_list.get(2)));
Map.addLayer(villages);

Now all I get is one image collection with 6 images (1 per month as specified in months list).

I want to perform above analysis which would be feature wise and if possible, output be stored in an image collection which would have property of first input image and feature used which would be used as an identifier.

2
  • 1
    Welcome to GIS SE. Thank you for taking the Tour. What have you tried? Where are you stuck? Coding Questions here are expected to contain code.
    – Vince
    Jun 20, 2023 at 10:13
  • Thanks @Vince for your kind suggestion. I have updated the question.
    – Ishwar
    Jun 20, 2023 at 10:52

1 Answer 1

2

The problem with your approach is if you produce the median, you lost the capacity for determining useful information related to separate images. So, I stored all images by month, according to your months list, previous to apply a spatial filter with ee.Join for intersecting your villages layer with the geometry of each image. This produces a Feature Collection where I set as property the number of intersected images with its respective date and id for each feature.

Complete code can be accessed here and as follows.

var villages =  ee.FeatureCollection("users/ishwarn/PosterMap_blocks");
var landsat7 = ee.ImageCollection("LANDSAT/LE07/C02/T1_L2");

var months = ee.List([11,12,1,2,3,4]);
var months_name = ee.List(['nov', 'dec', 'jan', 'feb', 'mar', 'apr']);
var vil_list = villages.toList(villages.size());

var startDate = "2000-11-01",
    endDate = "2001-04-30";

var l7Col = landsat7.filterBounds(villages)
                    .filterDate(startDate, endDate);

var l7Col = l7Col.map(function(img){

  var date = img.get("system:time_start");    // get the 'system:time start' property from the image

  img = ee.Image(img).set("system:time_start", date)
                     .set('fileName', ee.String('image_').cat(ee.Date(date).format().slice(0,10)));

  return(img);
  
});

print("l7Col", l7Col); 

var colByMonth = months.map(function (m) {
     return l7Col.filter(ee.Filter.calendarRange(m,m,'month'));
    });

print("colByMonth)", colByMonth);

///
var medianByMonth = colByMonth.map(function (ele) {
  
  var col = ee.ImageCollection(ele);
  
  var idx = colByMonth.indexOf(ele);
  
  col = col.map(function (img) {
    
    var ndvi = ee.Image(img).normalizedDifference(["SR_B4","SR_B3"]).rename('ndvi');
    var ndwi = ee.Image(img).normalizedDifference(["SR_B2","SR_B4"]).rename('ndwi');
    var ndbi = ee.Image(img).normalizedDifference(["SR_B5","SR_B4"]).rename('ndbi');
    
    return ee.Image(img).addBands([ndvi, ndwi, ndbi]);
    
  });
  
  var m = ee.List(months_name).get(idx);
  
  col = col.select('ndvi', 'ndwi', 'ndbi').median().set('filename', ee.String('image_').cat(m));
  
  return col;
  
});

var colByMonth = colByMonth.map(function (ele) {
  
  var col = ee.ImageCollection(ele);
  
  col = col.map(function (img) {
    
    var ndvi = ee.Image(img).normalizedDifference(["SR_B4","SR_B3"]).rename('ndvi');
    var ndwi = ee.Image(img).normalizedDifference(["SR_B2","SR_B4"]).rename('ndwi');
    var ndbi = ee.Image(img).normalizedDifference(["SR_B5","SR_B4"]).rename('ndbi');
    
    return ee.Image(img).addBands([ndvi, ndwi, ndbi]);
    
  });
  
  col = col.select('ndvi', 'ndwi', 'ndbi');
  
  return col;
  
});

var imageBounds = colByMonth.map(function (ele){
  
  var col = ee.ImageCollection(ele);
  
  col = col.map(function (img) {
    
    var date = img.get("system:time_start");
    
    return ee.Feature(ee.Geometry(ee.Image(img).geometry()))
            .set("image", ee.String('image_').cat(ee.Date(date).format().slice(0,10)));
    
  });
  
  return col;

});

//print(imageBounds);

var spatialFilter = ee.Filter.intersects({
  leftField: '.geo',
  rightField: '.geo'
});

var properties = ["image"];

//To test join
var joining = imageBounds.map(function (ele){

  var joinAll = ee.Join.saveAll('matched').apply(villages, ele, spatialFilter);
  
  var feats = joinAll.map(function(feature){
    var joinedFeat =  ee.List(feature.get('matched'));
    var col = ee.FeatureCollection(joinedFeat).toList(ee.FeatureCollection(joinedFeat).size());
    var polygon = ee.FeatureCollection(joinedFeat).size();
    return ee.Feature(feature).set("n_img_intersected", polygon)
                              .set("col", col);
  });
  
  return feats.toList(feats.size());
  
});

print("joining", joining);

medianByMonth = ee.FeatureCollection(ee.List(medianByMonth));

ee.FeatureCollection(medianByMonth).aggregate_array('filename').evaluate(function (fileNames) {
  fileNames.forEach(function(fileName) {
    var image = medianByMonth
      .filter(ee.Filter.eq('filename', fileName))
      .first();
    Map.addLayer(ee.Image(image), {}, fileName, false);
  });
});

Map.addLayer(villages);
Map.centerObject(villages, 7);

After running it, I got the result of following picture for the median of December (marked in Layers panel). It can also be observed that this composite image (opacity 50 %) intersects 6 features of 10 possible.

enter image description here

Above result can be corroborated at following picture in the Console Tab. Inside red rectangle, it is contemplated the information related to December for Feature 00000000000000000002. Effectively, it can also be corroborated that there are 6 intercepted features in total. Information corresponding to dates and id can be obtained from col property.

enter image description here

Editing Note:

As post's author eliminated the access to the villages Feature Collection, I had to modify my script to be functional. This is the new link. Obtained results are comparable.

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.