Image math can be performed using operators like add()
and
subtract()
, but for complex computations with more than a couple of terms, the
expression()
function provides a good alternative. See the following sections
for more information on operators and
expressions.
Operators
Math operators perform basic arithmetic operations on image bands. They take two inputs: either two images or one image and a constant term, which is interpreted as a single-band constant image with no masked pixels. Operations are performed per pixel for each band.
As a simple example, consider the task of calculating the Normalized Difference Vegetation
Index (NDVI) using Landsat imagery, where add()
, subtract()
,
and divide()
operators are used:
Code Editor (JavaScript)
// Load a 5-year Landsat 7 composite 1999-2003. var landsat1999 = ee.Image('LANDSAT/LE7_TOA_5YEAR/1999_2003'); // Compute NDVI. var ndvi1999 = landsat1999.select('B4').subtract(landsat1999.select('B3')) .divide(landsat1999.select('B4').add(landsat1999.select('B3')));
import ee import geemap.core as geemap
Colab (Python)
# Load a 5-year Landsat 7 composite 1999-2003. landsat_1999 = ee.Image('LANDSAT/LE7_TOA_5YEAR/1999_2003') # Compute NDVI. ndvi_1999 = ( landsat_1999.select('B4') .subtract(landsat_1999.select('B3')) .divide(landsat_1999.select('B4').add(landsat_1999.select('B3'))) )
Only the intersection of unmasked pixels between the two inputs are considered and returned as unmasked, all else are masked. In general, if either input has only one band, then it is used against all the bands in the other input. If the inputs have the same number of bands, but not the same names, they're used pairwise in the natural order. The output bands are named for the longer of the two inputs, or if they're equal in length, in the first input's order. The type of the output pixels is the union of the input types.
The following example of multi-band image subtraction demonstrates how bands are matched automatically, resulting in a “change vector” for each pixel for each co-occurring band.
Code Editor (JavaScript)
// Load a 5-year Landsat 7 composite 2008-2012. var landsat2008 = ee.Image('LANDSAT/LE7_TOA_5YEAR/2008_2012'); // Compute multi-band difference between the 2008-2012 composite and the // previously loaded 1999-2003 composite. var diff = landsat2008.subtract(landsat1999); Map.addLayer(diff, {bands: ['B4', 'B3', 'B2'], min: -32, max: 32}, 'difference'); // Compute the squared difference in each band. var squaredDifference = diff.pow(2); Map.addLayer(squaredDifference, {bands: ['B4', 'B3', 'B2'], max: 1000}, 'squared diff.');
import ee import geemap.core as geemap
Colab (Python)
# Load a 5-year Landsat 7 composite 2008-2012. landsat_2008 = ee.Image('LANDSAT/LE7_TOA_5YEAR/2008_2012') # Compute multi-band difference between the 2008-2012 composite and the # previously loaded 1999-2003 composite. diff = landsat_2008.subtract(landsat_1999) # Compute the squared difference in each band. squared_difference = diff.pow(2) # Define a map centered on Australia. map_diff = geemap.Map(center=[-24.003, 133.565], zoom=5) # Add the image layers to the map and display it. map_diff.add_layer( diff, {'bands': ['B4', 'B3', 'B2'], 'min': -32, 'max': 32}, 'diff.' ) map_diff.add_layer( squared_difference, {'bands': ['B4', 'B3', 'B2'], 'max': 1000}, 'squared diff.', ) display(map_diff)
In the second part of this example, the squared difference is computed using
image.pow(2)
. For the complete list of mathematical operators handling
basic arithmetic, trigonometry, exponentiation, rounding, casting, bitwise operations
and more, see the API documentation.
Expressions
To implement more complex mathematical expressions, consider using
image.expression()
, which parses a text representation of a math operation.
The following example uses expression()
to compute the Enhanced
Vegetation Index (EVI):
Code Editor (JavaScript)
// Load a Landsat 8 image. var image = ee.Image('LANDSAT/LC08/C02/T1_TOA/LC08_044034_20140318'); // Compute the EVI using an expression. var evi = image.expression( '2.5 * ((NIR - RED) / (NIR + 6 * RED - 7.5 * BLUE + 1))', { 'NIR': image.select('B5'), 'RED': image.select('B4'), 'BLUE': image.select('B2') }); Map.centerObject(image, 9); Map.addLayer(evi, {min: -1, max: 1, palette: ['a6611a', 'f5f5f5', '4dac26']});
import ee import geemap.core as geemap
Colab (Python)
# Load a Landsat 8 image. image = ee.Image('LANDSAT/LC08/C02/T1_TOA/LC08_044034_20140318') # Compute the EVI using an expression. evi = image.expression( '2.5 * ((NIR - RED) / (NIR + 6 * RED - 7.5 * BLUE + 1))', { 'NIR': image.select('B5'), 'RED': image.select('B4'), 'BLUE': image.select('B2'), }, ) # Define a map centered on San Francisco Bay. map_evi = geemap.Map(center=[37.4675, -122.1363], zoom=9) # Add the image layer to the map and display it. map_evi.add_layer( evi, {'min': -1, 'max': 1, 'palette': ['a6611a', 'f5f5f5', '4dac26']}, 'evi' ) display(map_evi)
Observe that the first argument to expression()
is the textual representation of
the math operation, the second argument is a dictionary where the keys are variable names used
in the expression and the values are the image bands to which the variables should be
mapped. Bands in the image may be referred to as b("band name")
or
b(index)
, for example b(0)
, instead
of providing the dictionary. Bands can be defined from images other than the input when using
the band map dictionary. Note that expression()
uses "floor division", which
discards the remainder and returns an integer when two integers are divided. For example
10 / 20 = 0
. To change this behavior, multiply one of the operands by
1.0
: 10 * 1.0 / 20 = 0.5
. Only the intersection of unmasked pixels
are considered and returned as unmasked when bands from more than one source image are
evaluated. Supported expression operators are listed in the following table.
Type | Symbol | Name |
---|---|---|
Arithmetic | + - * / % ** | Add, Subtract, Multiply, Divide, Modulus, Exponent |
Relational | == != < > <= >= | Equal, Not Equal, Less Than, Greater than, etc. |
Logical | && || ! ^ | And, Or, Not, Xor |
Ternary | ? : | If then else |