SAR Flood Mapping with Sentinel-1 and Google Earth Engine

SHARE:

Step-by-step flood mapping using Sentinel-1 and Google Earth Engine with population and land impact analysis.

 This tutorial demonstrates how to map flood extent using Sentinel-1 SAR imagery and a change detection approach within Google Earth Engine (GEE). By comparing radar backscatter before and after a flood event, we can generate accurate flood extent maps—even under cloud cover or nighttime conditions.

1.🌍 Area of Interest (AOI)

For demonstration, the script uses a predefined polygon in Beira, which experienced a severe coastal flood event in March 2019. This area is defined using the ee.Geometry.Polygon object.


// Sample polygon over Beira (March 2019 cyclone flood)
var geometry = ee.Geometry.Polygon([
  [[35.53377589953368, -19.6674648789114],
   [34.50106105578368, -18.952058786515526],
   [33.63314113390868, -19.87423907259203],
   [34.74825343859618, -20.61123742951084]]
]);

This image displays a screenshot of the flood mapping project developed in the Google Earth Engine (GEE) Code Editor. It illustrates the user interface, script panel, and map view used to process and visualize SAR data for flood analysis.

Screenshot of Google Earth Engine Code Editor showing flood mapping script and SAR imagery
GEE Code Editor – SAR Flood Mapping Script in Action

2.📅 Time Periods for Analysis

The script defines two distinct time periods to compare radar signals before and after the flood:


// Define timeframes
var before_start = '2019-03-01';
var before_end = '2019-03-10';
var after_start = '2019-03-10';
var after_end = '2019-03-23';

This allows for a clean capture of flood impact by minimizing the influence of seasonal or unrelated land cover changes.

3. ⚙️ SAR Data Parameters

Key SAR parameters can be adjusted to optimize results depending on your region:

  • Polarization: VH (recommended for flood) or VV
  • Pass Direction: DESCENDING (preferred consistency)
  • Difference Threshold: 1.25 (adjustable for sensitivity)

var polarization = "VH";
var pass_direction = "DESCENDING";
var difference_threshold = 1.25;

Step 2: Define the Area of Interest (AOI)

In this step, a polygon geometry is defined using ee.Geometry.Polygon. The area chosen in the example corresponds to Beira, Mozambique, a region affected by severe flooding in March 2019. You can use this demo or draw your own region of interest using Earth Engine’s polygon drawing tool.


// Demo geometry for Beira flood
var geometry = ee.Geometry.Polygon([
  [[35.53377589953368, -19.6674648789114],
   [34.50106105578368, -18.952058786515526],
   [33.63314113390868, -19.87423907259203],
   [34.74825343859618, -20.61123742951084]]
]);

📌 Tip: When testing other areas, make sure to draw your polygon in the Earth Engine Code Editor and assign it to geometry. Don’t forget to uncheck the geometry box in the Imports pane so it doesn’t obscure the map.

Step 3: Define Flood Period Dates

Next, you define the date ranges for before and after the flood. Sentinel-1 data has a typical revisit time of 6 days, so the date ranges must accommodate that.


// Time frame before the flood
var before_start = '2019-03-01';
var before_end = '2019-03-10';

// Time frame after the flood
var after_start = '2019-03-10';
var after_end = '2019-03-23';

⏳ Why this matters: The entire flood mapping process depends on capturing changes in radar backscatter between these two periods.

Step 4: Configure SAR Parameters

These parameters filter the Sentinel-1 dataset to include only images relevant to your study. The default settings use the VH polarization and descending orbit direction, which are commonly suitable for flood detection due to higher contrast between water and land.


var polarization = "VH";        // Preferred for flood detection
var pass_direction = "DESCENDING";  // Consistent orbit direction is important
var difference_threshold = 1.25;    // Sensitivity of flood detection

🎛️ Adjustments: You can change the polarization to VV or adjust the threshold if your detection yields too many false positives or negatives.

Step 5: Load and Filter Sentinel-1 SAR Imagery

The script now accesses the Sentinel-1 GRD dataset and filters it based on the SAR parameters you specified earlier (instrument mode, polarization, orbit direction, resolution, and AOI). The result is two collections: one before the flood and one after.


// Convert geometry to FeatureCollection
var aoi = ee.FeatureCollection(geometry);

// Load Sentinel-1 GRD data
var collection = ee.ImageCollection('COPERNICUS/S1_GRD')
  .filter(ee.Filter.eq('instrumentMode','IW'))
  .filter(ee.Filter.listContains('transmitterReceiverPolarisation', polarization))
  .filter(ee.Filter.eq('orbitProperties_pass', pass_direction)) 
  .filter(ee.Filter.eq('resolution_meters', 10))
  .filterBounds(aoi)
  .select(polarization);

// Filter by dates
var before_collection = collection.filterDate(before_start, before_end);
var after_collection = collection.filterDate(after_start, after_end);

You can use the following function to print the range of acquisition dates from each collection:


// Extract min and max date of image collection
function dates(imgcol) {
  var range = imgcol.reduceColumns(ee.Reducer.minMax(), ['system:time_start']);
  return ee.String('from ')
    .cat(ee.Date(range.get('min')).format('YYYY-MM-dd'))
    .cat(' to ')
    .cat(ee.Date(range.get('max')).format('YYYY-MM-dd'));
}

This helps ensure that valid Sentinel-1 acquisitions are being used for each flood phase.

Step 6: Create Mosaics and Apply Speckle Filtering

SAR data often contains noise known as "speckle." To reduce this and simplify the analysis, the script mosaics the available images and applies a smoothing filter using a 50-meter radius.


// Create mosaics and clip to AOI
var before = before_collection.mosaic().clip(aoi);
var after = after_collection.mosaic().clip(aoi);

// Apply speckle filtering
var smoothing_radius = 50;
var before_filtered = before.focal_mean(smoothing_radius, 'circle', 'meters');
var after_filtered = after.focal_mean(smoothing_radius, 'circle', 'meters');


Before Flood SAR Image
Before Flood SAR Mosaic
After Flood SAR Image
After Flood SAR Mosaic

Step 7: Detect Flood Extent Using Change Detection

The core of the flood detection algorithm compares backscatter differences between the two dates. A simple ratio is applied between the "after" and "before" images. The result is then thresholded to generate a binary flood mask.


// Compute change ratio and threshold
var difference = after_filtered.divide(before_filtered);
var threshold = difference_threshold;
var difference_binary = difference.gt(threshold);

⚠️ Important: Areas with values above the threshold are marked as flooded. Adjust this threshold to fine-tune the result for your region.

Step 8: Refine Flood Map Using Ancillary Data

The initial flood mask can include noise or false positives. To improve accuracy, we use three key filters:

  • Permanent Water Removal: We mask out areas classified as perennial water bodies using the JRC Global Surface Water dataset (where water exists for more than 10 months per year).
  • Pixel Connectivity: We remove isolated pixels by filtering out flood areas with fewer than 8 connected neighbors.
  • Slope Filtering: We exclude areas with slopes steeper than 5% using the WWF HydroSHEDS DEM, since floods are less likely in steep terrain.

// Remove permanent water pixels
var swater = ee.Image('JRC/GSW1_0/GlobalSurfaceWater').select('seasonality');
var swater_mask = swater.gte(10).updateMask(swater.gte(10));
var flooded_mask = difference_binary.where(swater_mask, 0);
var flooded = flooded_mask.updateMask(flooded_mask);

// Remove isolated pixels
var connections = flooded.connectedPixelCount();
flooded = flooded.updateMask(connections.gte(8));

// Mask steep slope areas
var DEM = ee.Image('WWF/HydroSHEDS/03VFDEM');
var slope = ee.Algorithms.Terrain(DEM).select('slope');
flooded = flooded.updateMask(slope.lt(5));

Step 9: Calculate Flooded Area (in Hectares)

The script uses the pixel area and a mask to calculate total flooded area within the region of interest. Results are converted from square meters to hectares for reporting.


// Calculate flooded area in hectares
var flood_pixelarea = flooded.select(polarization).multiply(ee.Image.pixelArea());
var flood_stats = flood_pixelarea.reduceRegion({
  reducer: ee.Reducer.sum(),
  geometry: aoi,
  scale: 10,
  bestEffort: true
});
var flood_area_ha = flood_stats.getNumber(polarization).divide(10000).round();

This gives an accurate estimate of the inundated surface in your study area.

🔗 Tip: For advanced post-processing or validation, export the flood raster or vector layers to QGIS or ArcGIS.

Step 10: Estimate Human and Agricultural Exposure

The script goes further by analyzing flood impact on population and land use. The JRC GHSL dataset is used for population exposure, while the MODIS Land Cover is used to quantify affected cropland and urban areas.


// Load population density map and calculate exposed people
var population_count = ee.Image('JRC/GHSL/P2016/POP_GPW_GLOBE_V1/2015').clip(aoi);
var flooded_res1 = flooded.reproject({ crs: population_count.projection() });
var population_exposed = population_count.updateMask(flooded_res1).updateMask(population_count);
var stats = population_exposed.reduceRegion({
  reducer: ee.Reducer.sum(),
  geometry: aoi,
  scale: 250,
  maxPixels: 1e9
});
var number_pp_exposed = stats.getNumber('population_count').round();

Ready for the next step? In the upcoming section, we will assess impacts on agriculture and urban infrastructure, and visualize everything with Earth Engine UI widgets.

Step 11: Analyze Affected Cropland Using MODIS

The MODIS Land Cover dataset (MCD12Q1) is used to identify croplands affected by flooding. The script filters out cropland pixels based on MODIS class codes and intersects them with the flood mask.


// Load MODIS land cover and extract cropland classes
var LC = ee.ImageCollection('MODIS/006/MCD12Q1')
  .filterDate('2014-01-01', after_end)
  .sort('system:index', false)
  .select("LC_Type1")
  .first()
  .clip(aoi);

var cropmask = LC.eq(12).or(LC.eq(14));
var cropland = LC.updateMask(cropmask);

// Match scale of flood layer to MODIS land cover
var flooded_res = flooded.reproject({ crs: LC.projection() });
var cropland_affected = flooded_res.updateMask(cropland);

// Calculate affected cropland area in hectares
var crop_pixelarea = cropland_affected.multiply(ee.Image.pixelArea());
var crop_stats = crop_pixelarea.reduceRegion({
  reducer: ee.Reducer.sum(),
  geometry: aoi,
  scale: 500,
  maxPixels: 1e9
});
var crop_area_ha = crop_stats.getNumber(polarization).divide(10000).round();

Step 12: Assess Impact on Urban Areas

Urban areas are also extracted from the MODIS land cover product using class code 13. The flood mask is intersected with this layer to calculate affected urban infrastructure.


// Extract and calculate affected urban areas
var urbanmask = LC.eq(13);
var urban = LC.updateMask(urbanmask);
var urban_affected = urban.mask(flooded_res).updateMask(urban);

var urban_pixelarea = urban_affected.multiply(ee.Image.pixelArea());
var urban_stats = urban_pixelarea.reduceRegion({
  reducer: ee.Reducer.sum(),
  geometry: aoi,
  scale: 500,
  bestEffort: true
});
var urban_area_ha = urban_stats.getNumber('LC_Type1').divide(10000).round();

Step 13: Display Results Using Google Earth Engine UI

Earth Engine’s ui.Panel elements are used to display flood extent, exposed population, affected cropland, and urban areas interactively on the map. These panels provide instant summaries for decision-making.


// Create results panel
var results = ui.Panel({ style: { position: 'bottom-left', padding: '8px 15px', width: '350px' } });

var title = ui.Label('Flood Impact Results', { fontSize: '18px', color: '#3333ff', margin: '0 0 15px 0' });
var text1 = ui.Label('Flood status between:', { fontWeight: 'bold' });
var number1 = ui.Label(after_start + ' and ' + after_end, { color: 'bf0f19', fontWeight: 'bold', margin: '0 0 15px 0' });

var text2 = ui.Label('Estimated flood extent:', { fontWeight: 'bold' });
var number2 = ui.Label('Loading...', { color: 'bf0f19', fontWeight: 'bold' });
flood_area_ha.evaluate(function(val) { number2.setValue(val + ' hectares'); });

var text3 = ui.Label('Exposed population:', { fontWeight: 'bold' });
var number3 = ui.Label('Loading...', { color: 'bf0f19', fontWeight: 'bold' });
number_pp_exposed.evaluate(function(val) { number3.setValue(val); });

var text4 = ui.Label('Affected cropland:', { fontWeight: 'bold' });
var number4 = ui.Label('Loading...', { color: 'bf0f19', fontWeight: 'bold' });
crop_area_ha.evaluate(function(val) { number4.setValue(val + ' hectares'); });

var text5 = ui.Label('Affected urban areas:', { fontWeight: 'bold' });
var number5 = ui.Label('Loading...', { color: 'bf0f19', fontWeight: 'bold' });
urban_area_ha.evaluate(function(val) { number5.setValue(val + ' hectares'); });

results.add(ui.Panel([title, text1, number1, text2, number2, text3, number3, text4, number4, text5, number5]));
Map.add(results);

📌 Insight: These result panels are essential for quick visual interpretation by disaster managers or environmental analysts.

➡️ In the final part, we will add a map legend, export the data for offline analysis, and include a multilanguage SEO footer for global discoverability.

4. Detecting Flood Extent

To identify flood-affected areas, we compute the ratio between the after and before SAR images using the following line of code:

var difference = after_filtered.divide(before_filtered);

This division highlights significant changes in backscatter values, which are indicative of water accumulation. A threshold is applied to classify pixels as flooded:

var threshold = difference_threshold;
var difference_binary = difference.gt(threshold);

Note: A threshold like 1.25 is often chosen empirically, and adjusting it may reduce false positives or negatives.

Refining the Flood Mask

The script uses auxiliary datasets to improve classification accuracy:

  • Excludes permanent water bodies using JRC’s Global Surface Water dataset:

var swater = ee.Image('JRC/GSW1_0/GlobalSurfaceWater').select('seasonality');
var swater_mask = swater.gte(10).updateMask(swater.gte(10));
var flooded_mask = difference_binary.where(swater_mask, 0);
  • Eliminates isolated noise using connectedPixelCount().
  • Masks out steep slopes (> 5%) using a HydroSHEDS DEM:

var DEM = ee.Image('WWF/HydroSHEDS/03VFDEM');
var slope = ee.Algorithms.Terrain(DEM).select('slope');
var flooded = flooded.updateMask(slope.lt(5));

5. Calculating Flooded Area

The script calculates the total flood extent in hectares using pixel area multiplication:


var flood_pixelarea = flooded.select(polarization).multiply(ee.Image.pixelArea());
var flood_stats = flood_pixelarea.reduceRegion({
  reducer: ee.Reducer.sum(),
  geometry: aoi,
  scale: 10,
  bestEffort: true
});
var flood_area_ha = flood_stats.getNumber(polarization).divide(10000).round();

📌 Tip: For highly accurate statistics, remove bestEffort and set maxPixels higher.

🔗 View Full Earth Engine Script: SAR-Based Flood Mapping (Sentinel-1)

Also see: How to Compute EVI in Google Earth Engine

🌐 Also searched as: Flood mapping with Sentinel-1 in GEECartographie des inondations Sentinel-1 GEEHochwassererkennung Sentinel-1 GEEDetección de inundaciones Sentinel-1 GEESentinel-1 洪水マッピング GEEرسم خريطة الفيضانات Sentinel-1 في GEE

Open All Collapse All Refresh Feeds
RSS Feeds & Updates
Geospatial Tools

GIS & Remote Sensing

Workflows and tutorials on spatial data and imagery analysis.

gis.geojamal.com

Remote Sensing Indices

Explore NDVI, SAVI, NDWI and many spectral indicators.

rs.geojamal.com

GeoAI & ML

Machine learning tools and spatial intelligence applications.

geoai.geojamal.com
Mapping & Visualization

Map Resources

Shapefiles, basemaps and vector tiles for GIS projects.

maps.geojamal.com

Earth Tools & Maps

Explore satellite viewers, terrain tools and visual apps.

earth.geojamal.com

Coordinate Tools

View, transform and clean coordinates on a live map.

coordinates.geojamal.com
AI & Smart Processing

GeoAI & ML

AI tools for automated analysis of Earth data.

geoai.geojamal.com

GEE Scripts & Apps

Google Earth Engine apps and tutorials.

gee.geojamal.com
Coordinate & File Converters

Geo Format Converter

Convert CSV, KML, GPX, GeoJSON, Excel, and more.

convert.geojamal.com

Coordinate Tools

Live projection and geocoding tools.

coordinates.geojamal.com
Learning Platforms

TV: English Tutorials

Video content for GEE, GIS, remote sensing in English.

tv.geojamal.com

TV: Arabic Tutorials

Arabic video lessons on mapping and geospatial analysis.

ar.tv.geojamal.com

How-To Guides

Written tutorials and step-by-step guides.

howto.geojamal.com

GeoJamal بالعربية

الموقع الرسمي للمحتوى العربي في نظم المعلومات الجغرافية، الاستشعار عن بعد، والخرائط الذكية.

ar.geojamal.com
Downloads & Resources

Downloads Center

Free GIS tools, satellite data, software and add-ons.

downloads.geojamal.com

SASPlanet Center

Offline satellite downloading and map exploration tools.

sasplanet.geojamal.com
GPS & Field Tools

GPS Utilities

Geotagged photos, live location, export to KML or GPX.

gps.geojamal.com

Coordinate Tools

Field-ready conversion and projection mapping support.

coordinates.geojamal.com
Multilingual Access

GeoJamal بالعربية

الموقع الرسمي للمحتوى العربي في نظم المعلومات الجغرافية، الاستشعار عن بعد، الذكاء الاصطناعي الجغرافي، وتحليل الخرائط.

ar.geojamal.com
Name

CHIRPS,1,Climate,1,Cloud masking,1,Crop Impact,1,DEM,1,Disaster Monitoring,1,EVI,3,Export,2,Fire forest,1,Flood Mapping,1,Forest,1,GEE,1,GEE Academy,3,GEE script,1,GEE Tutorial,1,GeoJamal,1,Google Earth Engine,1,Image analysis,6,JRC,1,Land Cover,1,Landsat,1,LST,1,MODIS,4,NDVI,5,NOAA,1,remote sensing,3,SAR Analysis,1,Sentinel,2,Sentinel-1,1,Sentinel-2,1,Snow,1,SRTM,3,temperature,1,time series,1,vegetation index,3,VIIRS,1,
ltr
item
GEE Academy: SAR Flood Mapping with Sentinel-1 and Google Earth Engine
SAR Flood Mapping with Sentinel-1 and Google Earth Engine
Step-by-step flood mapping using Sentinel-1 and Google Earth Engine with population and land impact analysis.
https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjFejTQhu5U2nBYrXK_3JgVkXvjVjlS0WLbFz3JN3nJ-9lGAA4Zgej2ANQD3A5vFD7ReUrF2ZwajRBd8sk8V7z_giO7CHg83v6Awu076SZK3mSob8eTSfIyiLE7YU2pAeRmwgI-FiEuKzEHjeb9iVNE6bjFvypcW05LIN954aWetYsx1xnln1zz4JviEEw/w640-h360/SAR-FLOOD-MAPPING-Earth-Engine-Code-Editor.png
https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjFejTQhu5U2nBYrXK_3JgVkXvjVjlS0WLbFz3JN3nJ-9lGAA4Zgej2ANQD3A5vFD7ReUrF2ZwajRBd8sk8V7z_giO7CHg83v6Awu076SZK3mSob8eTSfIyiLE7YU2pAeRmwgI-FiEuKzEHjeb9iVNE6bjFvypcW05LIN954aWetYsx1xnln1zz4JviEEw/s72-w640-c-h360/SAR-FLOOD-MAPPING-Earth-Engine-Code-Editor.png
GEE Academy
https://gee.geojamal.com/2025/04/sar-flood-mapping-with-sentinel-1-and.html
https://gee.geojamal.com/
https://gee.geojamal.com/
https://gee.geojamal.com/2025/04/sar-flood-mapping-with-sentinel-1-and.html
true
3421025227311197355
UTF-8
Loaded All Posts Not found any posts VIEW ALL Readmore Reply Cancel reply Delete By Home PAGES POSTS View All RECOMMENDED FOR YOU LABEL ARCHIVE SEARCH ALL POSTS Not found any post match with your request Back Home Sunday Monday Tuesday Wednesday Thursday Friday Saturday Sun Mon Tue Wed Thu Fri Sat January February March April May June July August September October November December Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec just now 1 minute ago $$1$$ minutes ago 1 hour ago $$1$$ hours ago Yesterday $$1$$ days ago $$1$$ weeks ago more than 5 weeks ago Followers Follow THIS PREMIUM CONTENT IS LOCKED STEP 1: Share to a social network STEP 2: Click the link on your social network Copy All Code Select All Code All codes were copied to your clipboard Can not copy the codes / texts, please press [CTRL]+[C] (or CMD+C with Mac) to copy Table of Content