1

I am trying to represent a raster giving to the palette the "max" and "min" of the raster according to the actual raster values. Instead of giving a minimum value of -1 and maximum value of 1 for the NDVI, I want that the minimum real value of the image represents the minimum value of the palette and the same for the maximum value. For instance, if the minimum value of a NDVI image is -0.7 and the maximum is 0.8 I want those values as "min" and "max" as parameters for the palette.

I thought that looking for the minimum/maximum value of the image with a reducer and transforming them to a Number I would be able to do it. However, when I run the code, I get the following error:

NDVI: Layer error: Can't encode object: abs() Computes the absolute value of the input. Args:this:input (Number): The input value.

The code is the following:

// Load image.
var img = ee.Image('MODIS/006/MOD09GA/2012_03_09');

// Use the normalizedDifference(A, B) to compute (A - B) / (A + B)
var ndvi = img.normalizedDifference(['sur_refl_b02', 'sur_refl_b01']);

var Min = ee.Number(ndvi.reduceRegion({
     reducer: ee.Reducer.min(),
     //scale: 250,
     maxPixels: 1e9,
     geometry: geometry,
     }));
  print(Min, 'NDVImin');

var Max = ee.Number(ndvi.reduceRegion({
      reducer: ee.Reducer.max(),
     //scale: 250,
     maxPixels: 1e9,
     geometry: geometry,
     }));
  
print(Max, 'NDVImax');

var BandCompViz = {min:Min, max:Max, palette:
  ['ffffff','b7f0ae','21f600','0000FF','FDFF92','FF2700','d600ff']};


// Center the map
Map.setCenter(-94.84497, 39.01918, 8);


Map.addLayer(ndvi, BandCompViz, 'NDVI');

https://code.earthengine.google.com/384e02f60104985848eb90fac875dfa6

1

There are two problems in your script. The first is that layer visualization parameters cannot currently contain computed values, so you'll have to explicitly download the computed min and max. The simplest edit of your script to do that would be to replace

var BandCompViz = {min:Min, max:Max, palette:...};

with

var BandCompViz = {min:Min.getInfo(), max:Max.getInfo(), palette:...};

but that is not ideal because it will actually hang the browser while the values are computed, and also makes two separate requests (processing the entire image twice) when one would be better.

Fixing that well also ties into the other problem in your script: you wrote

var Min = ee.Number(ndvi.reduceRegion({
     reducer: ee.Reducer.min(),
     //scale: 250,
     maxPixels: 1e9,
     geometry: geometry,
     }));

but this is not correct because the output of reduceRegion is always a dictionary of the reducer outputs, not a number. That is, it is {nd: -0.6111111111111112}, not -0.6111111111111112.

Conveniently, this is actually helpful for solving the other problem: we can compute the min and the max at the same time by combining two reducers, and they will both be in the dictionary which we can then download with a single request.

var MinMax = ndvi.reduceRegion({
  reducer: ee.Reducer.min().combine(ee.Reducer.max(), '', true),
  geometry: geometry,
});

Now MinMax is a dictionary with two entries, nd_min and nd_max. To compute the visualization parameters, we fetch the entire dictionary at once, asynchronously with evaluate so it doesn't hang the browser:

MinMax.evaluate(function (MinMaxDict) {
  var BandCompViz = {
    min: MinMaxDict['nd_min'], 
    max: MinMaxDict['nd_max'], 
    palette: ['ffffff','b7f0ae','21f600','0000FF','FDFF92','FF2700','d600ff']
  };
  Map.addLayer(ndvi, BandCompViz, 'NDVI');
});

https://code.earthengine.google.com/f176d01052d4af098b40705c05272474

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.