Google Earth Engine – Mapping land cover changes

Google Earth Engine is a cloud computing platform for planetary scale remote sensing analysis. It provides access to a multi-petabyte catalog of satellite imagery and geospatial datasets, including virtually all Landsat, MODIS and Sentinel image catalogs, as well as derivatives such as NDVI, land cover classifications and forest change maps. Additionally, Earth Engine allows users to leverage Google's powerful computing infrastructure to process these images.

One of the earliest and most high-profile applications of Earth Engine was the map of global forest change produced by Matt Hansen and his team at the University of Maryland. In this tutorial, we demonstrate the use of Earth Engine by performing a similar analysis, but on a much smaller scale. We will map forest cover change between 2001 and 2011 in a Landsat scene in Brazil.

Load images

In this tutorial, we will create a map of forest change between 2001 and 2011 in a small area of ​​Brazil. To do this, we need satellite images of the study area from 2001 and 2011, preferably at the same time of year, to eliminate seasonality as a confounding variable. The Landsat satellites are a good candidate here: they revisit the same area every 16 days with a resolution of 30m, and their entire catalog dating back to 1972 can be found on Earth Engine.

Try searching for "landsat" in the Earth Explorer data directory to see the available datasets. You'll notice that image collections are available for each different Landsat satellite and with different levels of processing. We will use orthorectified top-of-the-atmosphere (TOA) reflection collection for Landsat 5 and Landsat 7. Each collection is identified by a unique ImageCollection ID (e.g. LANDSAT/LT5_L1T_TOA_FMASK) and each Landsat scene photographed by that satellite Composed, each scene is identified by a unique Image ID (e.g. LANDSAT/LT5_L1T_TOA_FMASK/LT52240632011210CUB01).

For this tutorial, we have selected two Landsat scenes from July 2001 and July 2011 as the basis for our analysis. To load and view these scenes, paste the following code into your code editor:

 load landsat scenes for 2001 & 2011 in Brazil
// landsat 5 - 2011-07-29
var ls5 = ee.Image('LANDSAT/LT5_L1T_TOA_FMASK/LT52240632011210CUB01');
print(ls5);

// landsat 7 - 2001-07-09
var ls7 = ee.Image('LANDSAT/LE7_L1T_TOA_FMASK/LE72240632001190EDC00');
print(ls7);

// plot true colour composites
Map.addLayer(ls5, {bands: ['B3', 'B2', 'B1'], gamma: 1.5}, '2011');
Map.addLayer(ls7, {bands: ['B3', 'B2', 'B1'], gamma: 1.5}, '2001');
Map.centerObject(combined, 9);

 

In the map pane you should now see these Landsat scenes overlaid. In the upper left corner of the map, click the Layer button to toggle whether you see the scene from 2001 or 2011. {bands: ['B3', 'B2', 'B1']}The use of Map.addLayers() in the call tells Earth Engine which bands to draw, in which case a true color composite will be generated. Try using {bands: ['B4', 'B3', 'B2']} for standard false-color composite highlight vegetation. In addition to the map, the print() statements in the code also print the image's metadata to the console (upper right pane ). For example, you can browse the images here to see what bands are available.

Mask clouds and shadows

These images were specifically selected to have very limited cloud cover, however, there are some that we wish to mask these cloudy pixels and remove them from our analysis. Fortunately, the Landsat collection we are using contains an extra band with an integer indicating whether a given pixel is shadow (2), snow (3), or cloud (4). We will extract this band, convert it to binary (1 for pixels to keep, 0 for pixels to obscure due to clouds or shadows), and use it to mask the original image. I'm also going to rename the bands so we can differentiate between years. fmask

 

 landsat scenes for 2001 & 2011 in Brazil
// landsat 5 - 2011
var ls5 = ee.Image('LANDSAT/LT5_L1T_TOA_FMASK/LT52240632011210CUB01');
// create binary mask band for clouds and shadows
var ls5Mask = ls5.select('fmask').lt(2);
// select bands 1-5 and rename to append year
ls5 = ls5.
  select(['B1', 'B2', 'B3', 'B4', 'B5']).
  rename(['B1_2011', 'B2_2011', 'B3_2011', 'B4_2011', 'B5_2011']);
// mask out clouds
ls5 = ls5.updateMask(ls5Mask);

// landsat 7 - 2001
var ls7 = ee.Image('LANDSAT/LE7_L1T_TOA_FMASK/LE72240632001190EDC00');
// create binary mask band for clouds and shadows
var ls7Mask = ls7.select('fmask').lt(2);
// select bands 1-5 and rename to append year
ls7 = ls7.
  select(['B1', 'B2', 'B3', 'B4', 'B5']).
  rename(['B1_2001', 'B2_2001', 'B3_2001', 'B4_2001', 'B5_2001']);
// mask out clouds
ls7 = ls7.updateMask(ls7Mask);

// plot true colour composites
Map.addLayer(ls5, {bands: ['B3_2011', 'B2_2011', 'B1_2011'], gamma: 1.5}, '2011');
Map.addLayer(ls7, {bands: ['B3_2001', 'B2_2001', 'B1_2001'], gamma: 1.5}, '2001');
Map.centerObject(ls7, 9);

Note that these Landsat images now have holes where the clouds are.

Create a multi-date stack

We are interested in identifying pixels that changed from forest to non-forest (or vice versa) between 2001 and 2011. So we need to overlay these two scenarios so that we can analyze them simultaneously. I visualized this stack by mapping the infrared band of 2011 to red and the infrared band of 2001 to green and blue. In this composite image, areas of deforestation will appear in red.

 landsat scenes for 2001 & 2011 in Brazil
// landsat 5 - 2011
var ls5 = ee.Image('LANDSAT/LT5_L1T_TOA_FMASK/LT52240632011210CUB01');
// create binary mask band for clouds and shadows
var ls5Mask = ls5.select('fmask').lt(2);
// select bands 1-5 and rename to append year
ls5 = ls5.
  select(['B1', 'B2', 'B3', 'B4', 'B5']).
  rename(['B1_2011', 'B2_2011', 'B3_2011', 'B4_2011', 'B5_2011']);
// mask out clouds
ls5 = ls5.updateMask(ls5Mask);

// landsat 7 - 2001
var ls7 = ee.Image('LANDSAT/LE7_L1T_TOA_FMASK/LE72240632001190EDC00');
// create binary mask band for clouds and shadows
var ls7Mask = ls7.select('fmask').lt(2);
// select bands 1-5 and rename to append year
ls7 = ls7.
  select(['B1', 'B2', 'B3', 'B4', 'B5']).
  rename(['B1_2001', 'B2_2001', 'B3_2001', 'B4_2001', 'B5_2001']);
// mask out clouds
ls7 = ls7.updateMask(ls7Mask);

// stack to create multi-date composite
var combined = ls7.addBands(ls5);
// mask clouds
var cloudMask = combined.updateMask(ls7Mask).updateMask(ls5Mask);

// plot true colour composites
Map.addLayer(ls5, {bands: ['B3_2011', 'B2_2011', 'B1_2011'], gamma: 1.5}, '2011');
Map.addLayer(ls7, {bands: ['B3_2001', 'B2_2001', 'B1_2001'], gamma: 1.5}, '2001');
// plot multi-date composite
Map.addLayer(combined, {bands: ['B5_2011', 'B5_2001', 'B5_2001'], gamma: 1.5}, 'combined');
Map.centerObject(combined, 9);

Try using a multi-date image to identify areas of deforestation, then turn off this image in the layer manager and slide between the 2001 and 2011 images to confirm that deforestation is indeed occurring.

training polygons

We will perform supervised forest change classification using the random forest algorithm. To do this, we need to provide training data for the algorithm, i.e. we need to delineate regions of known fate to characterize different classes of spectral signatures. In particular, we are interested in the following 4 classes:

class name description

0

forest

forest in 2000 and 2011

1

forestLoss

forest loss

2

nonforest

non-forest in 2000 and 2011

3

forestGain

forest gain

Earth Engine provides a tool for drawing polygons directly on the map, which we will use to draw polygons for each of the four classes. The goal is to capture as much variability within classes as possible, so we will try to use 4-6 polygons per class to capture the full diversity of classes. First, click the Polygon Tool in the upper left corner of the map, this will create a new polygon layer.

Now click on the gear icon next to this new layer and fill the details as highlighter in the image below. This layer will be used for Category 1: forests that were unchanged between 2001 and 2011. You need to give it a name ("forest"), set the type to "feature" instead of geometry, and add a new "class" attribute (this will be level 0).

Now use all three layers of satellite imagery to identify areas that remained forest throughout the study period and create some polygons to delineate these areas. Keep your polygons small and remember to capture variety in this class. Once you are done with this class, move on to the other classes, making sure to create a new layer for each class and fill in the layer properties with the correct information. Call your layers: forest, forestLoss, nonforest, and forestGain.

Once you're done, scroll up to the top of the code editor and you'll see a new section for importing these polygon layers. Be sure to save your code at this point so you don't lose these polygons!

Extract cell value

Finally, we need to combine these four training layers into one and extract the image cell values ​​from within the polygon. This will generate a table that associates the pixels of each category with the spectral band values ​​in those pixels. It's likely that when you select polygons, some classes (such as unchanged forest) have easy examples to find, so the training polygons for these classes cover a larger area. Ideally, we would like each class to have the same number of training units. Additionally, Earth Engine imposes usage limits that will be exceeded and an error returned if the training polygon contains too many cells. To solve this problem, we will subsample within the polygon. Add the following code to the end of your existing script.

// subsample training polygons with random points
// this ensures all classes have same sample size
// also EE can't handle too many cells at once
var trainingLayers = [forest, forestLoss, nonforest, forestGain];
var n = 500;
// loop over training layers
for (var i = 0; i < trainingLayers.length; i++) { 
  // sample points within training polygons
  var pts = ee.FeatureCollection
    .randomPoints(trainingLayers[i].geometry(), n);
  // add class
  var thisClass = trainingLayers[i].get('class');
  pts = pts.map(function(f) {
    return f.set({class: thisClass});
  });
  // extract raster cell values
  var training = combined.sampleRegions(pts, ['class'], 30);
  // combine trainging regions together
  if (i === 0) {
    var trainingData = training;
  } else {
    trainingData = trainingData.merge(training);
  }
}

random forest

Now that we have the images and training data, it's time to run random forest classification. Add the following code to your script to fit a random forest model and plot the resulting forest changes.

 classify with random forests
// use bands 1-5 from each time period
var bands = ['B1_2001', 'B1_2011', 'B2_2001', 'B2_2011', 'B3_2001', 'B3_2011',
             'B4_2001', 'B4_2011', 'B5_2001', 'B5_2011'];
// fit a random forests model
var classifier = ee.Classifier.randomForest(30)
  .train(trainingData, 'class', bands);
// produce the forest change map
var classified = combined.classify(classifier);
var p = ['00ff00', 'ff0000', '000000', '0000ff'];
// display
Map.addLayer(classified, {palette: p, min: 0, max: 3}, 'classification');

Below is an example forest change plot, yours may be slightly different because you may have selected a different training region. In this map, forest is green, nonforest is black, forestLoss is red, and forestGain is blue.

Accuracy assessment

Before we use the map we just created, it's important to understand how accurate it is. For example, if a classification map shows that forest loss has occurred in a given area, how confident can we be that that area actually experienced forest loss?

Confusion matrix is a standard method for evaluating the performance of classification algorithms. It takes cases of a known class (such as training data or an independent validation dataset) and compares them to the predicted class. The rows of the matrix are instances of the actual classes, while the columns are instances of the predicted classes. The diagonal of the matrix gives the number of correct classifications, while the off-diagonal gives the number of incorrect classifications. For example, if we only have two classes, the matrix might look like this:

In this example, 10 cases of class 12 were correctly classified, while 5 of 8 cases of class 2 were correctly classified. Looking at the off-diagonal components, in 2 cases, class 1 was incorrectly assigned to class 2, and 3 Case category 2 was incorrectly assigned to category 1. Overall accuracy is the total number of correct classifications as a proportion of the total number of cases, in this case 15/20=75.

To calculate the confusion matrix and overall accuracy of the forest change map, add the following code to the end of the script:

// accuracy assessement
var confMat = classifier.confusionMatrix();
print('Confusion matrix: ', confMat);
print('Overall accuracy: ', confMat.accuracy());

You should now see the console's confusion matrix and overall accuracy.

In this case, our accuracy in all classes is very good, but please note that we use training data to perform validation. In practice, it is better to collect an independent validation dataset or split the training dataset into training and validation subsets to avoid bias in accuracy assessment.

in conclusion

In this tutorial, we use supervised classification to build a forest change map for a single Landsat scene in Brazil. However, this only scratches the surface of what Earth Engine is capable of. We can expand our analysis to include larger areas or study land changes in different geographic locations or biomes. Furthermore, applications are not limited to land cover changes in conservation contexts, Earth Engine is broadly applicable to any task requiring analysis of spatiotemporal trends on the Earth's surface.

Guess you like

Origin blog.csdn.net/weixin_48048649/article/details/128925003