Image workflows#


import ee
import geemap

except Exception as e:

Set up map window#

ndviVis = {"min":0.2, "max":1, "palette": ['white', 'green']}

Map = geemap.Map(center=[53, 12], zoom=8)

Client library#

The client library lets you run processing tasks on the Google servers. The library can be accessed via a JavaScript and Python API (Application Interface). To better understand the API, check out the documentation. Below is a list of some examples.

Client Libraries:

  • ee.Algorithms

  • ee.Array

  • ee.Blob

  • ee.Classifier

  • ee.Image

  • ee.ImageCollection

  • ee.Reducer

Some libraries such as ee.Algorithms and ee.Reducer contain functions that are applied to other EE objects. They work like a collection of tools. You can access them as follows:

# ee.Algorithms.HillShadow(image, azimuth, zenith, neighborhoodSize, hysteresis)

Other libraries let you create EE objects that have their own functionality (methods). For example, ee.Image() lets you create an image object. Below we create two image objects from the GEE data catalog, specifically two NDVI composites from August and April.

ndviAugust = ee.Image('LANDSAT/LC8_L1T_32DAY_NDVI/20150813')
ndviApril = ee.Image('LANDSAT/LC8_L1T_32DAY_NDVI/20150407')

Map.addLayer(ndviAugust , ndviVis, 'NDVI August')
Map.addLayer(ndviApril , ndviVis, 'NDVI April')

The functions shown under ee.Image in the API documentation are methods of your image object. For example, the addBands() method adds a band to an image object. You must access the method from your image object not from ee.Image(), i.e., ee.Image.addBands() does not work.

ndviStack = ndviAugust.addBands(ndviApril)

Image math#

Image-based math operators are accessed via the created image object, e.g., image.add(), image.subtract, image.multiply(), image.divide(). Let’s subtract the April NDVI from the August NDVI to calculate the change in NDVI.

ndviChange = ndviAugust.subtract(ndviApril)
Map.addLayer(ndviChange, {}, 'delta NDVI')

Logical operations#

We can create a binary mask based on the NDVI change. For example, we might want to separate areas that had an increase in NDVI by 0.2 (or greater) from areas with stable or declining NDVI (NDVI < 0.2).

ndviIncreaseMask = ndviChange.gte(0.2)
Map.addLayer(ndviIncreaseMask, {}, 'Where NDVI Increased')


We can apply the mask using ee.Image.mask() or ee.Image.updateMask(). For example, if we want to mask out stable NDVI areas from the NDVI change map, we can do the following:

ndviNoIncreaseMask = ndviChange.lte(0.2)
ndviChangeMasked = ndviChange.updateMask(ndviNoIncreaseMask)
Map.addLayer(ndviChangeMasked, {}, 'NDVI Increase')

Image properties#

Images conatain several types of metadata information such as band names, projection information, properties, and other metadata.

Get the band names as a list.

bandNames = ndviAugust.bandNames()
print('Band names: ', bandNames.getInfo())
Band names:  ['NDVI']

Get a list of all metadata properties.

properties = ndviAugust.propertyNames()
print('Metadata properties: ', properties.getInfo())
Metadata properties:  ['system:time_start', 'system:time_end', 'system:version', 'system:id', 'system:index', 'system:bands', 'system:band_names']

Get a specific metadata property.

band_info = ndviAugust.get('system:bands')
{'NDVI': {'data_type': {'type': 'PixelType', 'precision': 'float', 'min': -1, 'max': 1}, 'crs': 'EPSG:4326', 'crs_transform': [1, 0, 0, 0, 1, 0]}}

Filter collections#

Usually, we want to limit our operations to a subset of a collection. We can do that by filtering the collection by date, location, and metadata attributes.

l8sr = ee.ImageCollection("LANDSAT/LC08/C02/T1_L2")
geometry = ee.Geometry.Point([13.38, 52.52])

l8c = l8sr.filterDate('2016-07-01', '2017-07-08') \
          .filter('CLOUD_COVER', 70)) \

Map through a collection#

To apply a function to every Image in an ImageCollection use the method. The only argument to map() is a function which takes one parameter: an ee.Image. For example, the following code calculates the NDVI for each image. The resulting collection holds NDVI images corresponding to the Landsat image collection.

def calcNdvi(image):
  return image.normalizedDifference(["SR_B5", "SR_B4"]).rename("ndvi")

ndviCollection =

# adds first image from collection to map canvas
Map.addLayer(ndviCollection.first(), ndviVis, "max NDVI")

Reduce a collection#

From the collection of NDVI images, we can now calculate aggregation statistics such as the mean, max, etc. Aggregating a collection to a single image is called reducing. Reducer’s (reducing functions) are available to you in two ways: 1) via the ee.Image object and 2) via the ee.Reducer object (help).

maxNdvi = ndviCollection.reduce(ee.Reducer.max())

medianNdvi = ndviCollection.median()

Map.addLayer(maxNdvi, {"min":0, "max":1, "palette": ['white', 'green']}, "max NDVI")

Map.addLayer(medianNdvi, {"min":0, "max":1, "palette": ['white', 'green']}, "median NDVI")
Map.centerObject(geometry, 10)



Export to asset#

Often it is useful to save intermediate outputs to your Earth Engine account as an “asset”. When exporting images you can either specify a scale (pixel size) or the affine transformation. Specifying an affine transformation give you control over the alignment of the output pixel grid. This may be useful if you want to match the image pixels with other datasets. Alternatively to crsTransform, you can supply a scale argument for setting the output spatial resolution (without defining the output grid position).

task = ee.batch.Export.image.toAsset(image=maxNdvi,
                                     description='maxNdvi', assetId='maxNdvi',
                                     region=Map.get_bounds(), crs= 'EPSG:3035', 
                                     crsTransform= [30, 0, 4770400, 0, -30, 3149700], 

# uncomment to export
# task.start()

Export via geemap#

    maxNdvi, filename='maxNDVI.tif', scale=90, 
    region=Map.get_bounds(), file_per_band=True

Export to Google Drive#

task = ee.batch.Export.image.toDrive(image=maxNdvi, folder='export', 
                                     description= 'landsat',
                                     region=Map.get_bounds(), scale=30)

# task.start()