Quantifying Forest Change

Let's start with the calculation needed to create a band that shows pixels where the Hansen et al. data show both loss and gain.

The Hansen et al. dataset has a band whose pixels are 1 where loss occurred and 0 otherwise (loss) and a band that is 1 where gain has occurred and a 0 otherwise (gain). To create a band where pixels in both the loss and the gain bands have a 1, you can use the and() logical method on images. The and() method is called like image1.and(image2) and returns an image in which pixels are 1 where both image1 and image2 are 1, and 0 elsewhere:

// Load the data and select the bands of interest.
var gfc2014 = ee.Image('UMD/hansen/global_forest_change_2015');
var lossImage = gfc2014.select(['loss']);
var gainImage = gfc2014.select(['gain']);

// Use the and() method to create the lossAndGain image.
var gainAndLoss = gainImage.and(lossImage);

// Show the loss and gain image.
Map.addLayer(gainAndLoss.updateMask(gainAndLoss),
    {palette: 'FF00FF'}, 'Gain and Loss');

The result, zoomed into Arkansas with satellite view, should look something like Figure 1.

Loss Arkansas
Figure 1. Pixels with forest loss and gain in Arkansas.

Combining this example with the result from the previous section, it's now possible to recreate the figure from the beginning of the tutorial:

// Displaying forest, loss, gain, and pixels where both loss and gain occur.
var gfc2014 = ee.Image('UMD/hansen/global_forest_change_2015');
var lossImage = gfc2014.select(['loss']);
var gainImage = gfc2014.select(['gain']);
var treeCover = gfc2014.select(['treecover2000']);

// Use the and() method to create the lossAndGain image.
var gainAndLoss = gainImage.and(lossImage);

// Add the tree cover layer in green.
Map.addLayer(treeCover.updateMask(treeCover),
    {palette: ['000000', '00FF00'], max: 100}, 'Forest Cover');

// Add the loss layer in red.
Map.addLayer(lossImage.updateMask(lossImage),
    {palette: ['FF0000']}, 'Loss');

// Add the gain layer in blue.
Map.addLayer(gainImage.updateMask(gainImage),
    {palette: ['0000FF']}, 'Gain');

// Show the loss and gain image.
Map.addLayer(gainAndLoss.updateMask(gainAndLoss),
    {palette: 'FF00FF'}, 'Gain and Loss');

Quantifying Forest Change in a Region of Interest

Now that you're more familiar with the bands in the Hansen et al. dataset, we can use concepts learned so far to compute statistics about forest gain and loss in a region of interest. For this we'll need to use vector data (points, lines, and polygons). A vector dataset is represented as a FeatureCollection in Earth Engine. (Learn more about feature collections.) One way to load vector data to Earth Engine is from Fusion Tables. (Learn more about importing vector data from Fusion Tables.)

In this section, we'll use several Fusion Tables to compare the total amount of forest loss that happened within the Congo Republic in the year 2012 to the amount of forest loss that happened within concessions in that country at the same time. This can give a sense for how much loss happened in forest outside of official concessions.

As you learned in the Earth Engine API tutorial, the key method for calculating statistics in an image region is reduceRegion(). (Learn more about reducing image regions.) For example, suppose we want to calculate the number of pixels estimated to represent forest loss during the study period. For that purpose, consider the following code:

// Load country boundaries from a Fusion Table.
var countries =
    ee.FeatureCollection('ft:1tdSwUL7MVpOauSgRzqVTOwdfy17KDbw-1d9omPw');
// Get a feature collection with just the Congo feature.
var congo = countries.filter(ee.Filter.eq('Country', 'Congo'));

// Get the loss image.
var gfc2014 = ee.Image('UMD/hansen/global_forest_change_2015');
var lossImage = gfc2014.select(['loss']);

// Sum the values of loss pixels in Congo.
var stats = lossImage.reduceRegion({
  reducer: ee.Reducer.sum(),
  geometry: congo,
  scale: 30
});
print(stats);

this example uses the ee.Reducer.sum() reducer to sum the values of the pixels in lossImage within the congo feature. Because lossImage consists of pixels that have a value of 1 or 0 (for loss or not loss, respectively), the sum of these values is equivalent to the number of pixels of loss in the region.

Unfortunately, running the script as it is results in an error like:

The default maximum number of pixels in reduceRegion() is 10 million. This error message indicates that the Congo Republic covers about 447 million Landsat pixels. Luckily, reduceRegion() takes many parameters, one of which (maxPixels) lets you control how many pixels are used in the computation. Specifying this parameter allows the computation to succeed:

// Load country boundaries from a Fusion Table.
var countries =
    ee.FeatureCollection('ft:1tdSwUL7MVpOauSgRzqVTOwdfy17KDbw-1d9omPw');
// Get a feature collection with just the Congo feature.
var congo = countries.filter(ee.Filter.eq('Country', 'Congo'));

// Get the loss image.
var gfc2014 = ee.Image('UMD/hansen/global_forest_change_2015');
var lossImage = gfc2014.select(['loss']);

// Sum the values of loss pixels in Congo.
var stats = lossImage.reduceRegion({
  reducer: ee.Reducer.sum(),
  geometry: congo,
  scale: 30,
  maxPixels: 1e9
});
print(stats);

By expanding the object printed to the console, observe that the result is 5727543 pixels of forest lost. You can clean up the printout in the console a bit by labeling the output and getting the result of interest from the dictionary returned by reduceRegion():

print('pixels representing loss: ', stats.get('loss'));

Calculating Pixel Areas

You're almost ready to answer the question of how much area was lost in Congo, and how much of that was in concessions. The remaining part is to convert pixels into actual area. This conversion is important because we don't necessarily know the size of the pixels input to reduceRegion(). To help compute areas, Earth Engine has the ee.Image.pixelArea() method which generates an image in which the value of each pixel is the pixel's area in square meters. Multiplying the loss image with this area image and then summing over the result gives us a measure of area:

// Load country boundaries from a Fusion Table.
var countries =
    ee.FeatureCollection('ft:1tdSwUL7MVpOauSgRzqVTOwdfy17KDbw-1d9omPw');
// Get a feature collection with just the Congo feature.
var congo = countries.filter(ee.Filter.eq('Country', 'Congo'));

// Get the loss image.
var gfc2014 = ee.Image('UMD/hansen/global_forest_change_2015');
var lossImage = gfc2014.select(['loss']);
var areaImage = lossImage.multiply(ee.Image.pixelArea());

// Sum the values of loss pixels in Congo.
var stats = areaImage.reduceRegion({
  reducer: ee.Reducer.sum(),
  geometry: congo,
  scale: 30,
  maxPixels: 1e9
});
print('pixels representing loss: ', stats.get('loss'), 'square meters');

Now the result is 4,399,033,540 square meters lost over the study period.

You are now ready to answer the question at the start of this section - how much forest area was lost in the Congo basin in 2012, and how much of that was in concessions?

// Load country boundaries from a Fusion Table.
var countries =
    ee.FeatureCollection('ft:1tdSwUL7MVpOauSgRzqVTOwdfy17KDbw-1d9omPw');
// Get a feature collection with just the Congo feature.
var congo = countries.filter(ee.Filter.eq('Country', 'Congo'));

// Load the oil palm concessions from a Fusion Table.
var oilPalm = ee.FeatureCollection('ft:1Q-5XgXQpAeRhILPoPTx8gnGTzUpSJx-EtKu_BCw', 'geometry');

// Load the fiber concessions from a Fusion Table.
var fiber = ee.FeatureCollection('ft:1uqBi75K8AtJa3q4C-DuKUPYRMGvFHtp0c7E-VTA', 'geometry');

// Create a feature collection that is just oil palm and fiber
// concessions inside Congo.
var oilPalmInCongo = oilPalm.filterBounds(congo);
var fiberInCongo = fiber.filterBounds(congo);
var combined = oilPalmInCongo.merge(fiberInCongo);

// Get the loss image.
var gfc2014 = ee.Image('UMD/hansen/global_forest_change_2015');
var lossIn2012 = gfc2014.select(['lossyear']).eq(12);
var areaImage = lossIn2012.multiply(ee.Image.pixelArea());

// Calculate the area of loss pixels in Congo.
var stats = areaImage.reduceRegion({
  reducer: ee.Reducer.sum(),
  geometry: congo,
  scale: 30,
  maxPixels: 1e9
});
print(
    'area lost in the Congo Republic: ', stats.get('lossyear'),
    ' square meters');

// Calculate the area of loss pixels in the concessions.
var stats = areaImage.reduceRegion({
  reducer: ee.Reducer.sum(),
  geometry: combined,
  scale: 30,
  maxPixels: 1e9
});
print('area lost in concessions: ', stats.get('lossyear'), ' square meters');

The output indicates that of the 352,188,877 square meters of forest lost in the Congo Republic in 2012, 11,109,980 of those were in the palm oil and paper fiber concessions, as represented in the Fusion Tables data provided by the World Resources Institute.

The only changes between this script and the one just prior are the addition of the concessions information and changing the script from looking at overall loss to looking at loss in 2012. This required two changes. First, there's a new lossIn2012 image which has a 1 where loss was recorded in 2012, 0 otherwise. Second, because the name of the band is different (lossyear instead of loss) the property name had to change in the print statement.

In the next section, you'll learn about another deforestation monitoring dataset, FORMA, and compare it to the Hansen et al. data.

Send feedback about...

Google Earth Engine API