//////////////////////////////////////// ///////////// PREPARE IMAGE //////////// //////////////////////////////////////// // Center map on Guatemala study area Map.centerObject(guatemala_mar); // Establish function for masking clouds from Sentinel-2 image collection function maskS2clouds(image) { var qa = image.select('QA60'); // Bits 10 and 11 are clouds and cirrus, respectively. var cloudBitMask = 1 << 10; var cirrusBitMask = 1 << 11; // Both flags should be set to zero, indicating clear conditions. var mask = qa.bitwiseAnd(cloudBitMask).eq(0) .and(qa.bitwiseAnd(cirrusBitMask).eq(0)); return image.updateMask(mask).divide(10000); } // Load image collection of Sentinel-2 surface reflectance data var sentinel_collection = ee.ImageCollection('COPERNICUS/S2_SR') .filterDate('2020-01-01', '2020-05-31') // Pre-filter to get less cloudy granules. .filter(ee.Filter.lt('CLOUDY_PIXEL_PERCENTAGE', 20)) .map(maskS2clouds); // Establish variable for visualizing data on screen (true color) var median_vis = { min: 0.0, max: 0.2, bands: ['B4_median', 'B3_median', 'B2_median'], }; // Reduce Sentinel image collection to single image var sentinel_image = sentinel_collection.reduce(ee.Reducer.median()); // Clip Sentinel image to Guatemala boundary var guatemala_image = sentinel_image.clip(guatemala_mar); // Display Guatemala image Map.addLayer(guatemala_image, median_vis, "Guatemala Image"); //////////////////////////////////////// ///////////// FILTER IMAGE ///////////// //////////////////////////////////////// // Create "NDWI" layer to mask out water features var ndwi_layer = guatemala_image.normalizedDifference(['B3_median', 'B8_median']); // Mask water out of Sentinel image using NDWI layer var guatemala_ndwi = guatemala_image.updateMask(ndwi_layer.lte(0.0)); //Map.addLayer(guatemala_ndwi, median_vis, 'NDWI mask applied'); // Create "elevation" layer to mask out high-elevation features var srtm = ee.Image('USGS/SRTMGL1_003'); var elevation_layer = srtm.select('elevation'); // Mask high elevations out of Sentinel image using elevation layer var guatemala_elevation = guatemala_ndwi.updateMask(elevation_layer.lte(20.0)); //Map.addLayer(guatemala_elevation, median_vis, 'Elevation mask applied'); // Create "NDMI" layer to mask out non-mangrove candidates var ndmi_layer = guatemala_image.normalizedDifference(['B12_median', 'B3_median']); // Mask non-mangrove candidates out of Sentinel image using NDMI layer var guatemala_ndmi = guatemala_elevation.updateMask(ndmi_layer.lte(0.1)); //Map.addLayer(guatemala_ndmi, median_vis, "NDMI mask applied"); //////////////////////////////////////// /////////// CLASSIFY IMAGE ///////////// //////////////////////////////////////// // Designate which spectral bands to include in the classification var bands = ['B8_median', 'B4_median', 'B3_median', 'B2_median']; // Train the classifier using the training points var training = guatemala_image.select(bands).sampleRegions({ collection: guatemala_training, properties: ['class'], scale: 10 }); // Establish the classifier var classifier = ee.Classifier.smileRandomForest(200) .train({ features: training, classProperty: 'class', inputProperties: bands }); // Classify the image var guatemala_classified = guatemala_ndmi.select(bands).classify(classifier); // Mask out all non-mangrove pixels from the classified thematic map var guatemala_class_mask = guatemala_classified.updateMask(guatemala_classified.lte(0)); // Display the preliminary classified thematic map //Map.addLayer(guatemala_class_mask, {palette: ('FF0000')}, 'Preliminary Guatemala Mangrove Classification'); //////////////////////////////////////// //////// REFINE CLASSIFICATION ///////// //////////////////////////////////////// // Display Bunting mangrove layer for reference //var guatemala_bunting_2016 = guatemala_bunting.reduceToImage({ // properties: ['pxlval'], // reducer: ee.Reducer.first() //}); //Map.addLayer(guatemala_bunting_2016, {palette: ('00FF00')}, 'Bunting 2016'); //Map.addLayer(guatemala_mang_training, {palette: ('00FF00')}, 'Guatemala Mangrove Training Points'); // Make sure that the manual adjustment geometry is of type FeatureCollection var guatemala_include = ee.FeatureCollection(guatemala_include); // Dissolve the polygons in the Feature Collection, so the overlapping polygons // don't "cancel each other out" var guatemala_include = guatemala_include.union(); // Clip the classification to the Feature Collection of manual adjustments, and display var guatemala_mangroves = guatemala_class_mask.clip(guatemala_include); Map.addLayer(guatemala_mangroves, {palette: ('00FF00')}, 'Guatemala MAR Mangroves'); //////////////////////////////////////// //////////// CALCULATE AREA //////////// //////////////////////////////////////// // Calculate mangrove area for Guatemala, and print to console var guatemala_mangrove_area = guatemala_mangroves.reduceRegion({ reducer: ee.Reducer.count(), geometry: guatemala_include, scale: 10, maxPixels: 1e9 }); var guatemala_mangrove_area = ee.Number(guatemala_mangrove_area.get('classification')).divide(10000); var guatemala_mangrove_area = ee.Number(guatemala_mangrove_area).format(); print('Guatemala MAR mangrove area (km2) as of 2020:', guatemala_mangrove_area); //////////////////////////////////////// ////////////// EXPORT MAP ////////////// //////////////////////////////////////// // Convert Guatemala mangrove raster to polygon var guatemala_mangroves_polygon = guatemala_mangroves.toInt().reduceToVectors({ geometry: guatemala_include, crs: guatemala_mangroves.projection(), scale: 10, geometryType: 'polygon', eightConnected: false, maxPixels: 1e9 }); // Export Guatemala mangrove polygon to Google Drive //Export.table.toDrive({ // collection: guatemala_mangroves_polygon, // description:'guatemala_mar_mangroves', // fileFormat: 'KMZ' //}); //////////////////////////////////////// ////////////// VALIDATION ////////////// //////////////////////////////////////// // Generate random points for "mangrove presence" validation, and export to Google Drive // I will generate "mangrove absence" buffer and points in GIS program var guatemala_validation_points_presence = ee.FeatureCollection.randomPoints(guatemala_mangroves_polygon, 100); //Export.table.toDrive({collection: guatemala_validation_points_presence, fileFormat: 'GeoJSON'});