Remote sensing

Remote Sensing Applications: Built-up Assessment

Introduction

Built-up places can be found almost everywhere nowadays. The majority of built-up places are found on land. Thus, it is a no-brainer why a majority of remote sensing applications are focused on land surfaces. Built-up refers to areas, dominated (more than 50% in cover) by non-vegetated, human-constructed elements, such as roads, buildings, runways and industrial facilities.

Going by the definition, built-up area assessment is a key factor in urban studies, where there is a high prevalence of built-up surfaces compared to rural areas. Just as there are many vegetation indices such as Normalized Difference Vegetation Index (NDVI), Normalized Difference Moisture Index (NDMI) and Enhanced Vegetation Index (EVI) for vegetation studies, urban studies employ just as many in assessing built-up cover. These include the Normalized Difference Built-up Index (NDBI), Index-Based Built-up Index (IBBI), Urban Index (UI) and Built-up Index (BUI). The last is what shall be our major focus but not before passing a stealing glance at NDBI.

Photo by Wylkon Cardoso on Unsplash

In this exercise, we shall explore remote sensing applications. We shall use the BUI to extract the built-up area in Sao Paulo, Brazil. BUI is a relatively more accurate index compared to NDBI. It is also relatively easy to calculate. In the BUI, positive values indicate built-up areas. In all built-up indices, a major problem that still exists is that it is hard to delineate both built-up and bare areas since the reflectance characteristics are quite similar. However, we cross our fingers bare areas will not influence our results too much since Sao Paulo is a relatively green city! At least from a bird’s eye view of course!

Let’s load an administrative shapefile for Sao Paulo to work with. The shapefile is accessible from here.

Let’s first begin from R. Then we shall go to GEE for Google Earth Engine.

As always, the usual spatial R packages have to be loaded first.

library(sp)
library(sf)
## Linking to GEOS 3.9.1, GDAL 3.4.3, PROJ 7.2.1; sf_use_s2() is TRUE
library(rgdal)
## Please note that rgdal will be retired by the end of 2023,
## plan transition to sf/stars/terra functions using GDAL and PROJ
## at your earliest convenience.
## 
## rgdal: version: 1.5-32, (SVN revision 1176)
## Geospatial Data Abstraction Library extensions to R successfully loaded
## Loaded GDAL runtime: GDAL 3.4.3, released 2022/04/22
## Path to GDAL shared files: C:/Users/gachuhi/AppData/Local/R/win-library/4.2/rgdal/gdal
## GDAL binary built with GEOS: TRUE 
## Loaded PROJ runtime: Rel. 7.2.1, January 1st, 2021, [PJ_VERSION: 721]
## Path to PROJ shared files: C:/Users/gachuhi/AppData/Local/R/win-library/4.2/rgdal/proj
## PROJ CDN enabled: FALSE
## Linking to sp version:1.5-0
## To mute warnings of possible GDAL/OSR exportToProj4() degradation,
## use options("rgdal_show_exportToProj4_warnings"="none") before loading sp or rgdal.
library(rgeos)
## rgeos version: 0.5-9, (SVN revision 684)
##  GEOS runtime version: 3.9.1-CAPI-1.14.2 
##  Please note that rgeos will be retired by the end of 2023,
## plan transition to sf functions using GEOS at your earliest convenience.
##  GEOS using OverlayNG
##  Linking to sp version: 1.5-0 
##  Polygon checking: TRUE
library(raster)

Let’s read the downloaded Sao Paulo Municipalities shapefile into R Studio.

# Read the Sao Paulo municipalities shapefile into R Studio
sao <- readOGR(dsn="E:/documents/gis800_articles/building_detection/sao_paulo/sao_paulo.shp")
## OGR data source with driver: ESRI Shapefile 
## Source: "E:\documents\gis800_articles\building_detection\sao_paulo\sao_paulo.shp", layer: "sao_paulo"
## with 650 features
## It has 16 fields

With that done, we have saved the shapefile into the object sao. Time to view it.

# View the sao object
plot(sao)
remote sensing applications - sao paulo
Municipalities in Sao Paulo region

Wow. Sao Paulo isn’t just a small city, as presumed. It’s a whole region! However, we don’t want to work with this conglomeration of municipalities. We just want a single unitary shapefile, you know, for clipping a raster into. The above sao object is only good if were are planning to clip a raster, say a satellite image or DEM into various municipalities.

To create a single unitary shapefile where all municipalities have been merged into a single region, we have to aggregate them. In our case, the municipalities will be aggregated into a single attribute that is common to all of them. To do this, let’s first view the attributes of sao and choose a field value that is common to the hundreds of municipalities in this region.

# View the first few attributes of sao
sao@data[0:15, ]
##    CODMUNIC             NOMEMUNICP                    NOMEMUNIC CODUF  NOMEUF_1
## 0      <NA>                   <NA>                         <NA>  <NA>      <NA>
## 1      <NA>                   <NA>                         <NA>  <NA>      <NA>
## 2      <NA>                   <NA>                         <NA>  <NA>      <NA>
## 3      <NA>                   <NA>                         <NA>  <NA>      <NA>
## 4      <NA>                   <NA>                         <NA>  <NA>      <NA>
## 5   3500105             ADAMANTINA                   Adamantina    35 SAO PAULO
## 6   3500204                 ADOLFO                       Adolfo    35 SAO PAULO
## 7   3500303                  AGUAI                     Agua\xa1    35 SAO PAULO
## 8   3500402         AGUAS DA PRATA            \xb5guas da Prata    35 SAO PAULO
## 9   3500501       AGUAS DE LINDOIA       \xb5guas de Lind\xa2ia    35 SAO PAULO
## 10  3500550 AGUAS DE SANTA BARBARA \xb5guas de Santa B\xa0rbara    35 SAO PAULO
## 11  3500600     AGUAS DE SAO PEDRO     \xb5guas de S\xc6o Pedro    35 SAO PAULO
## 12  3500709                 AGUDOS                       Agudos    35 SAO PAULO
## 13  3500758               ALAMBARI                     Alambari    35 SAO PAULO
## 14  3500808      ALFREDO MARCONDES            Alfredo Marcondes    35 SAO PAULO
##    NOMEUF_2 REGIAO_1 REGIAO_2 CODMESO              NOMEMESO CODMICRO
## 0      <NA>     <NA>     <NA>    <NA>                  <NA>     <NA>
## 1      <NA>     <NA>     <NA>    <NA>                  <NA>     <NA>
## 2      <NA>     <NA>     <NA>    <NA>                  <NA>     <NA>
## 3      <NA>     <NA>     <NA>    <NA>                  <NA>     <NA>
## 4      <NA>     <NA>     <NA>    <NA>                  <NA>     <NA>
## 5        SP  SUDESTE       SE      08   PRESIDENTE PRUDENTE       35
## 6        SP  SUDESTE       SE      01 SAO JOSE DO RIO PRETO       04
## 7        SP  SUDESTE       SE      07              CAMPINAS       29
## 8        SP  SUDESTE       SE      07              CAMPINAS       30
## 9        SP  SUDESTE       SE      07              CAMPINAS       33
## 10       SP  SUDESTE       SE      04                 BAURU       22
## 11       SP  SUDESTE       SE      06            PIRACICABA       28
## 12       SP  SUDESTE       SE      04                 BAURU       20
## 13       SP  SUDESTE       SE      11          ITAPETININGA       42
## 14       SP  SUDESTE       SE      08   PRESIDENTE PRUDENTE       36
##                NOMEMICRO CODUFMESO CODUFMESOM  AREA_97 ID
## 0                   <NA>      <NA>       <NA>     <NA>  1
## 1                   <NA>      <NA>       <NA>     <NA>  2
## 2                   <NA>      <NA>       <NA>     <NA>  3
## 3                   <NA>      <NA>       <NA>     <NA>  4
## 4                   <NA>      <NA>       <NA>     <NA>  5
## 5             ADAMANTINA      3508     350835 411,7792  6
## 6  SAO JOSE DO RIO PRETO      3501     350104 210,8163  7
## 7           PIRASSUNUNGA      3507     350729 473,3618  8
## 8  SAO JOAO DA BOA VISTA      3507     350730 142,5886  9
## 9                 AMPARO      3507     350733 59,99524 10
## 10                 AVARE      3504     350422 408,5039 11
## 11            PIRACICABA      3506     350628  3,64473 12
## 12                 BAURU      3504     350420 967,5698 13
## 13          ITAPETININGA      3511     351142 159,2092 14
## 14   PRESIDENTE PRUDENTE      3508     350836 119,5107 15

Looks like the value SUDESTE under the REGIAO_1 field is common to all, if not most, municipalities. It’s like the attribute of a Province in a Kenya Counties shapefile. If one would like to merge all counties, say to their former respective provinces, the Province attribute would do the trick.

Let’s use the aggregate function from the sp package to aggregate the municipalities into one shapefile. The REGIAO_1 field.

# Aggregate municipalities using the REGIAO_1 field
sao_region <- aggregate(sao, by = "REGIAO_1", do_union = T)

# Plot the aggregated shapefile
plot(sao_region)
The result of aggregating the Sao Paulo municipalities

Done! We know that a few municipalities did not have any value under the REGIAO_1 and these may have still retained their boundaries. However, they are so small they are hardly visible. Methinks they could have been islands.

# Check attributes of the aggregated shapefile
sao_region@data[0:5, ]
## [1] NA        "SUDESTE" NA        NA        NA

Let’s save our aggregated shapefile from R into our computer’s directory. Thereafter, we shall transfer it to Google Earth Engine (GEE) where the bulk of our work shall reside.

# Save the aggregated shapefile into your directory
sao_region_shp <- writeOGR(sao_region, dsn = ".", layer = "sao_region",
                       driver = "ESRI Shapefile",  overwrite_layer = T)

After saving your shapefile, head over to your GEE account.

GEE

First things first. In your GEE account, head over to the assets tab.

Assets tab in GEE

Click on the New drop-down appearing with the yellow halo above. Select Shapefiles from the Table upload section. You will get a dialog box like the one below.

Dialog box

Select the sao_region_shp shapefile from your directory ensuring you have selected the dependencies such as .shp, .shx, .dbf and .prj as explained in the dialog box.

Once done, click Upload. The shapefile will appear under your legacy assets. In order to import it into your GEE script, just click the arrow with the hover text ‘Import into script’. The shapefile should appear in your GEE code editor. Give it the name sao_region.

For assessing the built-up area in Sao Paulo, we created the following variables.

  • city
  • point1
  • point2

Below is the code that will load all the above variables, including that of sao_region into your GEE code editor.

var sao_region = ee.FeatureCollection("users/sammigachuhi-test/sao_region"),
    city = 
    /* color: #d63000 */
    /* shown: false */
    /* displayProperties: [
      {
        "type": "rectangle"
      }
    ] */
    ee.Geometry.Polygon(
        [[[-46.949648518267026, -23.182191189569593],
          [-46.949648518267026, -23.842046005948035],
          [-46.103701252642026, -23.842046005948035],
          [-46.103701252642026, -23.182191189569593]]], null, false),
    point = 
    /* color: #98ff00 */
    /* shown: false */
    ee.Geometry.Point([-46.598294953027256, -23.677920629371847]),
    point2 = /* color: #0b4a8b */ee.Geometry.Point([-46.598086018267026, -23.33359429234038]);

Built-up area assessment

To undertake our built-up assessment, let’s first zoom in on Sao Paulo.

// zoom to shapefile of Sao Paulo region
Map.centerObject(sao_region, 6);
Let’s add our sao_region shapefile into the code editor and view it.
// Add the Sao Paulo shapefile to google earth engine map canvas
Map.addLayer(sao_region, {}, "sao_paulo");
Remote Sensing applications for built up areas
Sao Paulo shapefile in GEE

Remember the two points that we had created, point1 and point2. They are about to point us somewhere. The two points are crucial in downloading Sentinel-2 images to those specific locations. Let’s go ahead and load our Sentinel-2 images into GEE.

// Load Sentinel 2 image for clearest month of the year which is August

var sao_clear = ee.ImageCollection('COPERNICUS/S2_SR_HARMONIZED')
    .filterBounds(point)
    .filterDate('2021-08-01', '2021-08-30')
    .sort('CLOUDY_PIXEL_PERCENTAGE')
    .first();
    
var sao_clear2 = ee.ImageCollection('COPERNICUS/S2_SR_HARMONIZED')
    .filterBounds(point2)
    .filterDate('2021-08-01', '2021-08-30')
    .sort('CLOUDY_PIXEL_PERCENTAGE')
    .first();
    
print("Images over Sao Paulo July - September 2021: ", sao_clear);
print("Images over Sao Paulo July - September 2021: ", sao_clear2);

Let’s add our Sentinel 2 images to the GEE canvas.

Map.addLayer(sao_clear, {min: -67, max: 1700, bands:['B4', 'B3', 'B2']}, "Sao Paulo 2021");
Map.addLayer(sao_clear2, {min: -67, max: 1700, bands:['B4', 'B3', 'B2']}, "Sao Paulo 2021vs2");

Below are our two images. They in fact line up to each other so well that there is absolutely no space between them. However, they are separate. Unless we look for a way to join them, it will be double work to assess the built-up area in both of them.

What shall we do? Mosaic! Like, more psyche!!

remote sensing applications
The downloaded Sentinel 2 images

Mosaicing. Our two images may not overlap, but the technique will be the same. In GEE, mosaicking is the technique of combining several images with overlapping parts (the images may be obtained at different times, different viewing angles or different sensors) into a largescale seamless high resolution image. Our two images may not be overlapping each other, but the technique will be the same. In GEE, mosaicking is done using the mosaic() method.

Before mosaicking the two images, however, we have to first combine both to form a single collection using the ee.ImageCollection() method. Thereafter, the mosaicking is done on the image collection. This two-step procedure is done using the code script below.

// Mosaic sao_clear and sao_clear2
var sao_images = ee.ImageCollection([sao_clear, sao_clear2]);

var sao_images2 = sao_images.mosaic();

Map.addLayer(sao_images2, {min: -67, max: 1700, bands:['B4', 'B3', 'B2']}, "Sao Paulo 2021 Mosaicked");

Remember the city bounding box we had created earlier? Its purpose was to serve as a bounding box to clip the larger mosaicked image to the city core. We will clip the larger mosaicked image, which is too large an area for built-up assessment anyway, to the city core.

Let’s go ahead and clip the mosaicked image – sao_images2 to the city core.

var sao_images_clip = sao_images2.clip(city);

Map.addLayer(sao_images_clip, {min: -67, max: 1700, bands:['B4', 'B3', 'B2']}, "Sao Paulo 2021 Clipped");
remote sensing applications
The clipped mosaic

Calculating the Normalized Difference Built-up Index (NDBI)

Now that we have our image reduced to a sufficient scale for our analysis, we shall first perform NDBI on it followed by other calculations that will build up to BUI. We calculate NDBI using the formula shown below:

NDBI = (SWIR – NIR)/(SWIR + NIR)

GEE’s ee.Image expression method simplifies mathematical expressions involving images. We define the mathematical formula using the expression parameter and select the images to use in the expression using the map parameter. We use the above method to calculate NDBI like so:

var ndbi_expression = '(SWIR - NIR)/(SWIR + NIR)';

var ndbi2021 = sao_images_clip.expression({
  expression: ndbi_expression,
  map: {
    SWIR: sao_images_clip.select("B11"),
    NIR: sao_images_clip.select("B8")
  }
}).rename("ndbi");

Map.addLayer(ndbi2021, {palette:['blue', 'yellow', 'red']}, "NDBI 2021");
remote sensing applications - NDBI
The NDBI image for Sao Paulo

We have also defined the bandnames of the output images to read “ndbi” using the rename method.

Calculating the Normalized Difference Vegetation Index

NDVI may be confusing you when we are primarily dealing with built-up areas. But remember, we previously mentioned that we calculate BUI by subtracting NDVI from NDBI. That is, BUI = NDBI – NDVI.

Let’s calculate the NDVI speedily.

The formula for NDVI is (NIR – Red)/(NIR + Red). We shall use the image.expression() function to calculate the NDVI just like we did for NDBI.

// Calculate the Normalized Difference Vegetation Index (NDVI) for sao_images_clip

var ndvi_expression = '(NIR - Red)/(NIR + Red)';

var ndvi2021 = sao_images_clip.expression({
  expression: ndvi_expression,
  map: {
    NIR: sao_images_clip.select('B8'),
    Red: sao_images_clip.select('B4')
  }
}).rename('ndvi');

Map.addLayer(ndvi2021, {palette: ['red', 'yellow', 'green']}, "NDVI 2021");
NDVI Images remote sensing applications
The NDVI image over Sao Paulo

The NDVI image looks lovely!

Now without further ado, let’s calculate the BUI for Sao Paulo. Sao Paulo looks to be located in a lush green environment. Therefore, bare areas should not constitute much of a large percentage of our end results. Therefore, if the area’s greenery favours us, the BUI should mostly collect the impervious surfaces.

Let’s do this thing. BUI formula is NDBI – NDVI.

// Calculate the Built Up Index (BUI)
// BUI = NDBI - NDVI

var bui2021 = ndbi2021.subtract(ndvi2021).rename('bui');

Map.addLayer(bui2021, {palette:['green', 'yellow', 'red']}, 'BUI 2021');
Built-up Area result

Notice that towards the southeast there seems to be a high reading of built-up areas (more positive values indicate built-up areas) in yellow. However, on closer inspection, this yellow patch is in fact a lake! It seems that even though bare areas are rare in Sao Paulo, the BUI also captures water values as built-up too! The explanation could be that built-up and water register low NIR values, and thus are difficult to distinguish from each other. The same issue is also, albeit to a lesser extent, prevalent in the NDBI image. Oh well, we shall work with what we have.

In BUI and NDBI, higher positive values indicate built-up and barren areas. In our case, barren areas are almost non-existent. As such, built-up areas carry the most part. Since we want to only extract the most probable built-up area(s) from our bui2021 image, we shall work with a threshold of 0. Extracting all pixels with a value above this threshold should comfortably give us an image of built-up only, with the additional problem of water bodies also captured therein.

First, let’s get the minimum and maximum values for the bui2021 image.

// Get min max of bui2021
var bui2021_minmax = bui2021.reduceRegion({
  reducer: ee.Reducer.minMax(),
  geometry: city,
  scale: 10,
  bestEffort: true
});

print("Min max values for bui2021: ", bui2021_minmax);
print("BUI for 2021", bui2021);

The values of both extremes are:

bui_max: 1.867632850241546
bui_min: -1.741782898901804

Let’s select all bui2021 pixels above a threshold of 0.

// Select all areas above a threshold of 0

var datamask2021 = bui2021.select("bui");

var mask2021 = datamask2021.gte(0);

var built2021 = bui2021.updateMask(mask2021);

Map.addLayer(built2021, {palette:['red']}, "Built 2021");

Time to calculate the total built-up area within Sao Paulo’s city bounds. The pixelArea() function calculates the area of each pixel in square metres. Thus, calculating the total sum of the areas of all pixels–which are in square metres–will give us the area of that image in…what? …square metres.

// Calculate area of the Built-up area (BUI) in 2021
var builtArea2021 = built2021.multiply(ee.Image.pixelArea());

var stats2021 = builtArea2021.reduceRegion({
  reducer: ee.Reducer.sum(),
  geometry: city,
  scale: 10,
  bestEffort: true
});

Let’s print the total built-up surface area within the city bounds we had set for Sao Paulo.

print("Total impervious surface area is: ", stats2021);

We get a value of 107454854.88727954 or roughly 107 square kilometres. However, these values are false since we also captured waterbodies. For example, the water feature encircled in yellow in the figure below. In order to get the most authentic built-up area values, one will need to mask out the waterbodies.

Built-up areas in Sao Paulo in 2021, overlying a True-color Google Earth Satellite image

The collection of water pixels is a disappointment, but the BUI calculation did a fair job of extracting built-up areas and leaving out vegetated surfaces.

Conclusion

Several urban studies have used built-up indices, assessing the built-up cover and studying the contribution of buildings to the urban heat island effect. However, the confusion about bare soil, or barren areas with built-up cover has led to the development of new indices that take both into account. Examples are Dry Built-up Index (DBI) and Dry Bare-Soil Index (DBSI). In our case, we didn’t find barren areas prevalent in our region of interest, but we counted water features as built-up.

Similar reflectance values mostly cause confusion about land covers, therefore we must conduct additional processes to get the true result. Of late, machine learning has been promising. For example, instead of collecting all built-up areas indiscriminately, machine learning looks for specified patterns and collates them to the end result. For example, if one only wanted to collect building features from an image, machine learning would look for rectangular and other defined polygonal patterns. We extract rectangular and clear-cut polygon shapes with matching reflectance characteristics as features. This process eliminates roads from the end result, thus giving the researcher a true estimate of buildings in an area.

Here is the full code script for this exercise.

var sao_region = ee.FeatureCollection("users/sammigachuhi-test/sao_region"),
    city = 
    /* color: #d63000 */
    /* shown: false */
    /* displayProperties: [
      {
        "type": "rectangle"
      }
    ] */
    ee.Geometry.Polygon(
        [[[-46.949648518267026, -23.182191189569593],
          [-46.949648518267026, -23.842046005948035],
          [-46.103701252642026, -23.842046005948035],
          [-46.103701252642026, -23.182191189569593]]], null, false),
    point = /* color: #98ff00 */ee.Geometry.Point([-46.598294953027256, -23.677920629371847]),
    point2 = /* color: #0b4a8b */ee.Geometry.Point([-46.598086018267026, -23.33359429234038]);
    
    //////////////////////////////
    
    // zoom to shapefile of Sao Paulo region
Map.centerObject(sao_region, 6);

// Add the Sao Paulo shapefile to google earth engine map canvas
Map.addLayer(sao_region, {}, "sao_paulo");

// Load Sentinel 2 image for clearest month of the year which is August

var sao_clear = ee.ImageCollection('COPERNICUS/S2_SR_HARMONIZED')
    .filterBounds(point)
    .filterDate('2021-08-01', '2021-08-30')
    .sort('CLOUDY_PIXEL_PERCENTAGE')
    .first();
    
var sao_clear2 = ee.ImageCollection('COPERNICUS/S2_SR_HARMONIZED')
    .filterBounds(point2)
    .filterDate('2021-08-01', '2021-08-30')
    .sort('CLOUDY_PIXEL_PERCENTAGE')
    .first();
    
print("Images over Sao Paulo July - September 2021: ", sao_clear);
print("Images over Sao Paulo July - September 2021: ", sao_clear2);

Map.addLayer(sao_clear, {min: -67, max: 1700, bands:['B4', 'B3', 'B2']}, "Sao Paulo 2021");
Map.addLayer(sao_clear2, {min: -67, max: 1700, bands:['B4', 'B3', 'B2']}, "Sao Paulo 2021vs2");

// Mosaic sao_clear and sao_clear2
var sao_images = ee.ImageCollection([sao_clear, sao_clear2]);

var sao_images2 = sao_images.mosaic();

Map.addLayer(sao_images2, {min: -67, max: 1700, bands:['B4', 'B3', 'B2']}, "Sao Paulo 2021 Mosaicked");

// Clip the Mosaicked image to the variable city bounds

var sao_images_clip = sao_images2.clip(city);

Map.addLayer(sao_images_clip, {min: -67, max: 1700, bands:['B4', 'B3', 'B2']}, "Sao Paulo 2021 Clipped");

// Calculate Normalized Difference Built-up Index (NDBI) for sao_images_clip

var ndbi_expression = '(SWIR - NIR)/(SWIR + NIR)';

var ndbi2021 = sao_images_clip.expression({
  expression: ndbi_expression,
  map: {
    SWIR: sao_images_clip.select("B11"),
    NIR: sao_images_clip.select("B8")
  }
}).rename("ndbi");

Map.addLayer(ndbi2021, {palette:['blue', 'yellow', 'red']}, "NDBI 2021");

// Calculate the Normalized Difference Vegetation Index (NDVI) for sao_images_clip

var ndvi_expression = '(NIR - Red)/(NIR + Red)';

var ndvi2021 = sao_images_clip.expression({
  expression: ndvi_expression,
  map: {
    NIR: sao_images_clip.select('B8'),
    Red: sao_images_clip.select('B4')
  }
}).rename('ndvi');

Map.addLayer(ndvi2021, {palette: ['red', 'yellow', 'green']}, "NDVI 2021");

// Calculate the Built Up Index (BUI)
// BUI = NDBI - NDVI

var bui2021 = ndbi2021.subtract(ndvi2021).rename('bui');

Map.addLayer(bui2021, {palette:['green', 'yellow', 'red']}, 'BUI 2021');

// Get min max of bui2021
var bui2021_minmax = bui2021.reduceRegion({
  reducer: ee.Reducer.minMax(),
  geometry: city,
  scale: 10,
  bestEffort: true
});

print("Min max values for bui2021: ", bui2021_minmax);
print("BUI for 2021", bui2021);

// Select all areas above a threshold of 0

var datamask2021 = bui2021.select("bui");

var mask2021 = datamask2021.gte(0);

var built2021 = bui2021.updateMask(mask2021);

Map.addLayer(built2021, {palette:['red']}, "Built 2021");

// Calculate area of the Built-up area (BUI) in 2021
var builtArea2021 = built2021.multiply(ee.Image.pixelArea());

var stats2021 = builtArea2021.reduceRegion({
  reducer: ee.Reducer.sum(),
  geometry: city,
  scale: 10,
  bestEffort: true
});

print("Total impervious surface area is: ", stats2021);

Leave a Reply

Your email address will not be published. Required fields are marked *

More Reading

Post navigation