Satellite Imagery using Google Earth Engine and Python

Satellite Imagert Using Google Earth And Python

In this article, we will be learning how to work with Satellite Imagery and visualize them using Python. This tutorial is a very skim introduction to the world of geo-spatial analysis. It is meant for people who at least have a beginner-level knowledge of python.

Satellite Imagery using Google Earth Engine in Python

Google Earth Engine is one of the best sources for satellite imagery and computation. It is a platform for scientific analysis and visualization of geospatial datasets, for academic, non-profit, business, and government users. Earth Engine hosts satellite imagery and stores it in a public data archive that includes historical earth images going back more than forty years.

It is nice of Google to provide an API to communicate with Earth-Engine easily through very less amount of code. The API is created to have similarities with the JavaScript API and is not very pythonic. So you might face little difficulties having your first walk through the API.

1. Installing the ee library

Note: Google earthengine-api is already installed inside the Colab environment. So if you are using the Google Colab platform for running python, you can safely skip this step.

If you are running on a local machine, you need to first install the earthengine-api in your local machine. The pip command for installing the earthengine-api is:

pip install earthengine-api --upgrade

2. Importing and authenticating yourself

# Import the earth-engine module
import ee

Access to Google Earth Engine is currently only available to registered users. So you need to register yourself for Google Earth Engine for using this service.

Moreover, you need to authenticate yourself as a registered user the first time you are using Google earth-engine in your local machine.

ee.Authenticate()

In general, authentication for local installations is a one-time step that generates a persistent authorization token, while VM services such as Colab, limit the token’s lifetime.

Lastly you need to initialize the API.

ee.Initialize()

We are now all set to use the earth-engine API.

3. Load the image dataset

As mentioned earlier there are a large number of datasets available in Earth Engine. Choosing the correct dataset for our task is very important. Each dataset is meant to cover different aspects of the earth. For example Tree cover, water bodies, etc. In this tutorial, we will be using the DMSP OLS: Nighttime Lights Time Series dataset which contains time-series data of the night-light of various countries.

Each dataset if a collection of images. So the naming convention for Dataset is ImageCollection and we will be using this naming convention for the rest of the article.

# Load the Nighttime Image Collection

collection = ee.ImageCollection('NOAA/DMSP-OLS/NIGHTTIME_LIGHTS')

4. Working with the ImageCollection

The most important aspect that separates normal photos from satellite images is the spectrum of the images is way beyond the normal 0-255 range. The images have different bands which can be compared to the channels(RGB) of the normal image. Each band captures a different electromagnetic spectrum.

Now we see what bands each image in the image collection have:

# Extract the first image
first_image = collection.first()

# Display band information about the image
first_image.bandNames().getInfo()

Output:

['avg_vis', 'stable_lights', 'cf_cvg', 'avg_lights_x_pct']

We need the stable_lights band for visualization. Selecting one band from each image from the collection is time consuming, but luckily earth-engine offers a way to select one band from a collection of images.

collection = collection.select('stable_lights')

Now each image in the image collection has a single band. To visualize the change over time will be needing another band that will represent the time.

first_image = collection.first()

# Get number of years after 1991 from the first image
year = ee.Date(first_image.get('system:time_start')).get('year').subtract(1991)

# Turn it into a band
img1 = ee.Image(year).byte().addBands(first_image)

# A new band appears in the new image
img1.bandNames().getInfo()

Output:

['constant', 'stable_lights']

We need to do this for every image in the collection. So we create a function and map it over the collection.

def createTimeBand(img):
    year = ee.Date(img.get('system:time_start')).get('year').subtract(1991)
    return ee.Image(year).byte().addBands(img)

# Map it to the collection to create a new collection
collection = collection.map(createTimeBand)

5. Visualize the night-lights

Now that we have our ImageCollection ready to be displayed, we need a UI to display the images. There are a lot of UI options available like Folium, matplotlib, PIL, etc.

In this tutorial, we have chosen Folium. Folium is a python library based on leaflet.js (open-source JavaScript library for mobile-friendly interactive maps) that you can use to make interactive maps. Folium supports WMS, GeoJSON layers, vector layers, and tile layers which make it very convenient and straightforward to visualize the data we manipulate with python.

If you don’t have folium installed you can install using the following pip command:

pip install folium --upgrade
# Import the folium library
import folium

Now we need to define how to display the google earth images in folium. Here is a function that comes very handy to use with Folium and Earth-Engine.

# Define a method for displaying Earth Engine image tiles to folium map.
def add_ee_layer(self, ee_image_object, vis_params, name):
  map_id_dict = ee.Image(ee_image_object).getMapId(vis_params)
  folium.raster_layers.TileLayer(
    tiles = map_id_dict['tile_fetcher'].url_format,
    attr = 'Map Data © <a href="https://earthengine.google.com/">Google Earth Engine</a>',
    name = name,
    overlay = True,
    control = True
  ).add_to(self)

# Add EE drawing method to folium.
folium.Map.add_ee_layer = add_ee_layer

Now we can create a map, giving the initial coordinates and the zoom factor. Don’t worry if you get it a little wrong. Folium is interactive, which means you can change the location and zoom while you are visualizing the map.

# Create the night map
night_map = folium.Map(location=[37.5010, -102.1899], zoom_start=4.5)

We need to set some parameters for displaying the image, such as the bands and colour preferences of each. Here is a default setting that you might like.

#  visualize the y-intercept in green, and positive/negative slopes as red/blue.

params = {
    'bands' :  ['scale', 'offset', 'scale'],
    'min' : 0,
    'max' : [0.18, 20, -0.18],
}

Before we visualize, we have one final step. We need to reduce the image using LinearFit method which computes the least squares estimate of a linear function of one variable with a constant term.

night_light = collection.reduce(ee.Reducer.linearFit())

Add the image and parameters to the map and display the map.

# Add the image layer to the night_map
night_map.add_ee_layer(night_light, params, 'test')

# Display the map
display(map)
Night Light 1 - Satellite Imagery using Google Earth Engine
Fig 1: Here is a beautiful representation of change of America night light from 1991
Night Light India - Satellite Imagery using Google Earth Engine
Fig 2: Here is a representation of change of night light in India and parts of south Asia since 1991

Conclusion

We have come to the end of the article on visualizing the change of night light using Google Earth Engine. For the next step, you can try to use different bands and even different Datasets. If you are looking further, Google has come up with many other tutorials like Detecting Changes in Sentinel-1 Imagery to get you started with more in-depth methods of geo-spatial analysis.