Google Earth Engine – Extracting Index of Band with Max Value Among All Bands

google-earth-enginegoogle-earth-engine-javascript-api

I'm discovering the Dynamic world dataset and I would like to extract for each pixel the most probable class.
Each class is stored on a separated band from 1 to 9 representing the probability of the class on [0, 1]. I would like to create a band "most_prob_class" that gives the number of the band with the highest value. Is it only possible?

I know it's already computed in the label band for this very dataset, but I found the problem interesting.

Here is some code to understand the structure of the dataset:

// get the data and filter them to your need
var dynamic_world = ee.ImageCollection("GOOGLE/DYNAMICWORLD/V1")
var start = ee.Date('2021-04-02');
var filter = ee.Filter.date(start, start.advance(1, 'month'));
var dw_image = ee.Image(dynamic_world.filter(filter).mosaic())

// here I gather some information related to the dataset I manipulate: 
// the name of the classes to select only the one I want to analyse
var CLASS_NAMES = ['water', 'trees', 'grass', 'flooded_vegetation', 'crops', 'shrub_and_scrub', 'built', 'bare', 'snow_and_ice'];
// the associated color palette
var VIS_PALETTE = ['419bdf', '397d49', '88b053', '7a87c6', 'e49635', 'dfc35a', 'c4281b', 'a59b8f', 'b39fe1'];

Best Answer

If anybody needs to run this computation for this dataset or another, you can follow this pattern and adapt it to your need:

// get the data and filter them to yor need
// dynamic world is forcing me to filter spacially but that may not be required from your dataset
// we want 1 image with 1 band per class probability
var dynamic_world = ee.ImageCollection("GOOGLE/DYNAMICWORLD/V1")
var start = ee.Date('2021-04-02');
var end = start.advance(1, 'month');
var point = ee.Geometry.Point(20.6729, 52.4305);
var filter = ee.Filter.and(ee.Filter.bounds(point),ee.Filter.date(start, end));
var dw_image = ee.Image(dynamic_world.filter(filter).first())

// here I gather some information related to the dataset I manipulate: 
// the name of the classes to select only the one I want to analyse
var CLASS_NAMES = ['water', 'trees', 'grass', 'flooded_vegetation', 'crops', 'shrub_and_scrub', 'built', 'bare', 'snow_and_ice'];
// the associated color palette
var VIS_PALETTE = ['419bdf', '397d49', '88b053', '7a87c6', 'e49635', 'dfc35a', 'c4281b', 'a59b8f', 'b39fe1'];
// a simple List with all the class numbers
var CLASS_NUMBER = ee.List.sequence(1, 9)

// To compute my new band I first need to extract only the class emmbeding  
// probability, then I search for the max value for each pixel. 
var filtered_dw_image = dw_image.select(CLASS_NAMES)
var max_prob = filtered_dw_image.reduce(ee.Reducer.max())

// then I set all band values to 0 if they are not the band with the highest probability
var most_prob_class = max_prob.eq(filtered_dw_image)

// Now I multiply this binary mask with a Image that has a constant value 
// coresponding to each band. The one that are the max will keep it's number,
// the others will be remain to 0. 
most_prob_class = most_prob_class.multiply(ee.Image.constant(CLASS_NUMBER))

// finally I sum all the band value resulting in a single band image with
// the value of the band with the maximum probability
most_prob_class  = most_prob_class.reduce(ee.Reducer.sum())

You can see the result in action in https://code.earthengine.google.com/f17d6ffa816679b1614d7c9ad594c4d3