Google Earth Engine – Calculate Histogram for Every Image in ImageCollection

functiongoogle-earth-enginegoogle-earth-engine-javascript-apihistogram

I want to calculate histograms for every image in an ImageCollection with reduce.histogram. It works with a single image but I have problems mapping the function over the ImageCollection. I think the issues are ".first()" and the return commands. But I have no clue how to fix it.

Here is the code snippet:

var histo_ic_func = function (histo_ic_map) {

  var map_func = histo_ic_map.map(function(ic_for_calc){

    var histogram_image_ic = ee.Image(ic_for_calc.first());
    var histogram_threshold_ic = histogram_image_ic.select('VV').reduceRegion({
      reducer: ee.Reducer.histogram()
        .combine('mean', null, true)
        .combine('variance', null, true), 
      scale: 10,
      bestEffort: true
    });

    return histogram_threshold_ic.get('VV_mean');
  });

  return imagecollection_threshold.get('VV_mean');
};

Here is the complete GEE script: https://code.earthengine.google.com/3d413950a4a2f389686283aa3c0bec9f. The relevant part starts in line 76.

As final output, I would like to have a FeatureCollection with the results of all image histogram calculations.

Best Answer

It looks like you need to check up on a few GEE basics, starting with .map() functions. Mapping over an ImageCollection or FeatureCollection allows you to apply a function to each image of function within said collection. In simple terms, way you use functions with .map() is basically:

var output_of_mapped_function = input_collection.map(
  function(chosen_name_of_individual_element){
    // CONTENTS OF FUNCTION //
    // For example:
    var output = chosen_name_of_individual_element.selfMask()
    return output
  });

You do this correctly inside of your nested function, but the exterior function meets none of these requirements, and is purely decorative.

Also, any mapped function has to return an ee.Feature() or an ee.Image(). Here, since you are trying to return a numeric value, you need to format it accordingly (see corrected version below). Finally, there are some issues with the variable names, e.g. you are changing the variable name though you have not changed the variable, or you are using variable names that have not yet been assigned to anything.

This is the final version that should work, with added commentary:

// USELESS FUNCTION, ALSO WRONG SYNTAX
//var histo_ic_func = function (histo_ic_map) {
  
  // histo_ic_map DOES NOT EXIST, DID YOU MEAN ic_grid?
  var map_func_outputs = /*histo_ic_map*/ic_grid.map(function(ic_for_calc){
    
    // NO NEED FOR THIS LINE 
    //var histogram_image_ic = ee.Image(ic_for_calc.first());
  
    // JUST USE ic_for_calc DIRECTLY
    var histogram_threshold_ic = /*histogram_image_ic*/ic_for_calc.select('VV').reduceRegion({
          reducer: ee.Reducer.histogram()
            .combine('mean', null, true)
            .combine('variance', null, true), 
          scale: 10,
          bestEffort: true
      });
      
      // MAPPED FUNCTIONS NEED TO RETURN AN IMAGE OR FEATURE
      //return histogram_threshold_ic.get('VV_mean');
      
      // CREATE A FEATURE WITH NULL GEOMETRY AND ADD RESULTS AS PROPERTY
      return ee.Feature(null,{ic_thresh: histogram_threshold_ic.get('VV_mean')});
  });
  
  //return imagecollection_threshold.get('VV_mean');
//};

print(map_func_outputs); //OUTPUTS ARE FEATURE PROPERTIES