Image Classification using Google Earth Engine

Sry Handini Puteri
6 min readJul 26, 2020

Remotely sensed images are in the form of raw data. In order for the image to be analyzed, several processes are required to be done. One of the ways is by implementing image classification. Image classification functions to extract information based on the information within the pixel of the image. The raster then can be transformed into a thematic map. The most common practice for classifying the image is to understand the landcover within an area. There are two methods to classify an image: supervised and unsupervised. Supervised is the method in which the process is being assisted by the analyst by choosing the training samples. As opposed to that, unsupervised finds spectral classes or clusters without the analyst’s intervention.

Classifying an image can be completed in various GIS platforms, such as ArcGIS, QGIS, ENVI, and other image processing software. The advantage of using GEE is that we do not have to download the image in our local directory.

In this article, the supervised image classification is used. The steps are elaborated below.

  1. Display the area that you want to choose

In this article, the area of interest is Palu, Central Sulawesi, Indonesia. There is not much scientific reason, I chose it because it feels relatable. You may choose your own area that you like. Then I add the marker and put it in the area of Palu. The geometry point will automatically be defined as a variable and put as an imported asset at the top of the code window pane.

Type the area in the search box, then enter. The area will be automatically zoomed
Put a marker in the area and change the name of the variable from ‘geometry’ to ‘roi’
//Displaying the image 
var image = ee.Image(ee.ImageCollection(‘LANDSAT/LC08/C01/T1_SR’)
.filterBounds(roi)
.filterDate(‘2019–01–01’, ‘2019–12–30’)
.sort(‘CLOUD_COVER’)
.first());
Map.addLayer(image, {bands: [‘B4’, ‘B3’, ‘B2’],min:0, max: 3000}, ‘True colour image’);
The image that has the least cloud cover will be displayed.

The area is too wide since Landsat 8 will cover 185 km x 180 km (114 mi x 112 mi). Since Palu is at the intersection between 4 scenes of Landsat images, thus the majority of the area is a deepwater body with lots of clouds. That is why I am trying to clip the image to focus on the terrestrial area. I started by drawing a shape to the area near the capital city. The area is relatively cloud-free. The shape then will automatically be a geometry variable, then I change the name into ‘box’

Drawing a shape to the intended area of interest
//Clipping the image
var boundary = image.clip(box);
Map.addLayer(boundary, {bands: [‘B4’, ‘B3’, ‘B2’],min:0, max: 3000}, ‘Clip’);
Clipping result

2. Choose the training samples

  • Each land cover will be represented by several training samples. I divided the landcover into four categories, which are urban, deep water (sea), surface water (river), and vegetation. In this instance, I choose 25 training samples for every land cover. The number can be higher and make sure that they are evenly distributed. The training sample can be in the form of point, line, or polygon. It will see the value of each pixel as the training sample.
  • Hover the cursor to the ‘Geometry Import’, then add ‘new layer’. Setup the configuration for the geometry input. Change the name for each landcover class. Import it as a Feature Collection. Fill in the property to ‘landcover’ and value as 0. Subsequent classes will be 1, 2, 3 and so on. In this case, urban will have value of 0, deep water as 1, surface water as 2, and vegetation as 3. This function to differentiate three classes to ease the visualization process. Repeat the process for the other classes. All layers will be imported as an asset.
Configuring geometry input
6 entries of imports in total

3. Start classifying the image

  • After the classes already defined, the data will be merged first to turn them into a single FeatureCollection. This is the line to merge the geometries (urban, deep water, surface water, vegetation) into a single FeatureCollection. Print(classNames) function to display the feature in the inspector console:
//start classifying the image
var classNames = urban.merge(deepwater).merge(surfacewater).merge(vegetation);
print(classNames);
  • The feature collection will extract the reflectance data for each point from every band. The training data is overlayed with the pixel on the image. There will be additional new properties to the feature collection that represent band values at each point.
//training sample regions
var bands = ['B2', 'B3', 'B4', 'B5', 'B6', 'B7'];
var training = boundary.select(bands).sampleRegions({
collection: classNames,
properties: ['landcover'],
scale: 30
});
print(training);

Then run the script using CART (Classification and Regression Tree) algorithm

var classifier = ee.Classifier.cart().train({
features: training,
classProperty: 'landcover',
inputProperties: bands
});

Next, run the classification.

//Run the classification
var classified = image.select(bands).classify(classifier);

Display the classification with a scale of 11. The color palette will follow the landcover respective class subsequently.

//Display classification
Map.centerObject(classNames, 11);
Map.addLayer(classified,
{min: 0, max: 3, palette: ['red', 'blue', 'green','yellow']},
'classification');

Red represents the urban and settlement areas, blue represents deep water, green represents vegetation and yellow represents the surface water (river).

CART Algorithm

Above is the result of the landcover classification. The first attempt is using CART algorithm. Read this article to understand how CART algorithm works. But, I am not satisfied with the result. There is high number of pixels that are read as the surface water if you take a look in the white box. The algorithm reads the deep sea as surface water. The area looks like deep water because it is pretty far from the coastline, so it is likely to be categorized as deep water. Thus, it leads me to try another method, which is using Minimum Distance classification.

The coastline is read as surface water. My assumption is because the seawater near the coastline still contain huge amount of sediment material which is similar with the river water. The river water in Palu carry a lot of sediments. If you see the true color image, the surface water is not transparent nor dark, it is light brown which indicates sand or clay that is transported from the upstream.

Minimum Distance

Minimum Distance has a slightly more representative result if we compare it with the true color image. This is the article that shows how Minimum Distance works. The vegetation is evenly distributed and the settlement area are well-represented.

Comparing the result. Minimum Distance (Left) ; CART (Right)

Above is the comparison of the landcover classification. There are multiple factors that contribute to the result of the image classification:

  • The number of training samples
  • The spatial resolution of the satellite image

Full script

var image = ee.Image(ee.ImageCollection('LANDSAT/LC08/C01/T1_SR')
.filterBounds(roi)
.filterDate('2019-01-01', '2019-12-30')
.sort('CLOUD_COVER')
.first());
//Map.addLayer(image, {bands: ['B4', 'B3', 'B2'],min:0, max: 3000}, 'True colour image');
//Clipping the image
var boundary = image.clip(box);
Map.addLayer(boundary, {bands: ['B4', 'B3', 'B2'],min:0, max: 3000}, 'Clip');
//start classifying the image
var classNames = urban.merge(deepwater).merge(surfacewater).merge(vegetation);
print(classNames);
//training sample regions
var bands = ['B2', 'B3', 'B4', 'B5', 'B6', 'B7'];
var training = boundary.select(bands).sampleRegions({
collection: classNames,
properties: ['landcover'],
scale: 30
});
print(training);
//image classification
var classifier = ee.Classifier.minimumDistance().train({
features: training,
classProperty: 'landcover',
inputProperties: bands
});
//Run the classification
var classified = boundary.select(bands).classify(classifier);
//Display classification
Map.centerObject(classNames, 11);
Map.addLayer(classified,
{min: 0, max: 3, palette: ['red', 'blue', 'yellow','green']},
'classification');

--

--

Sry Handini Puteri

Personal learning space ; A Geoenthusiast ; Interested in Disaster Risk Management