Skip to content

Instantly share code, notes, and snippets.

@7yl4r
Last active August 6, 2025 16:05
Show Gist options
  • Save 7yl4r/f1e3889911c50ce08189e5daaf80e22e to your computer and use it in GitHub Desktop.
Save 7yl4r/f1e3889911c50ce08189e5daaf80e22e to your computer and use it in GitHub Desktop.
Claudia's Placencia mangrove
/**
MANGROVE CLASSIFICATION SCRIPT
For Placencia 2025 USING SENTINEL 2
2025/06/09
Claudia Baron-Aguilar
Previous steps.
1. Selection of best image (Using Image selection code)
2. selection of positive and negative goriud-truth points
(Creating List of coordinates code with anotehr code)
3. Build ground-Truth matrix with positive and negative points
with data from step 2 (Presence-absence/ gt_data import above)
Steps.
1. Load image
2. Preprocess image
3. Sample data
4. Train model & Classify
5. Accuracy assessment
*/
////////////////////////////////////////////////////////////////////////////
// 1. LOAD IMAGE //
////////////////////////////////////////////////////////////////////////////
// Previously obtained with "seleccion_imagen" code
// Image ID
var id = '20250321T161011_20250321T161849_T16QCD';
//Load image
var image = ee.Image('COPERNICUS/S2_SR_HARMONIZED/' + id);
// see image
print (image);
// Apply scale factor to the Image
var scaledImage = image.multiply(0.0001);
// Print Scaled Image to the console to inspect
print('scaledImage',scaledImage);
var image = scaledImage; //Image is now equal to scaled Image
//COLOR PALETTES (RGB)//
var visualization = {
min: 0.0,
max: 0.3,
gamma:2,
bands: ['B4', 'B3', 'B2'],
};
//Visualize Image
Map.addLayer(image, visualization,"image");
//Now we have an Image that is ready to be processed
//////////////////////////////////////////////////////////////////////
// // 2. IMAGE PREPROCESSING //
// ///////////////////////////////////////////////////////////////////
//Calculate the ndvi (Normalized Difference Vegetation Index)
var ndvi = image.normalizedDifference(['B8','B4']);
print ('ndvi', ndvi);
var ndviVis = {min: -1, max: 1, palette: ['blue', 'white', 'green']};
Map.addLayer(ndvi, ndviVis, 'ndvi');
//Create Mask where NDVI is greater than the threshold
var ndviMask = ndvi.gte(0.25);
//Apply the ndvi mask to the image
var maskedImage = image.updateMask(ndviMask);
print ('maskedImage', maskedImage);
Map.addLayer (maskedImage, visualization, 'maskedImage');
// // // ////////////////////////////////////////////////////////////////////////////
// // // // 3. SAMPLE DATA //
// // // ////////////////////////////////////////////////////////////////////////////
// Ground truth data
var data = gt_data;
print('Class Codes', data.aggregate_array('class').distinct());
// class Codes are:
// 0: no mangrove
// 1: mangrove
print('Ground truth Points per class', data.aggregate_histogram('class'));
// Number of ground truth points per class
// 0:362
// 1: 40
//select bands to sample
var samplingBands = ['B2', 'B3', 'B4','B5','B6','B7','B8','B8A','B9','B11','B12'];
// Sample multi-espectral dara using all ground truth points
var sampleData = maskedImage.select(samplingBands).sampleRegions({
collection:data,
properties: ['class'],
scale: 10});
// Generate random numbers from 0 to 1 for each sampled class.
var random = sampleData.randomColumn('random');
print ('random', random);
// Split ground truth data:70% for training and 30% for validation,
// to use in the classification model training
var trainingPoints = random.filter(ee.Filter.lt('random', 0.7));
var validationPoints = random.filter(ee.Filter.gte('random', 0.3));
print('Training Samples (70%)', trainingPoints);
// // // ////////////////////////////////////////////////////////////////////////////
// // // // 4. TRAIN MODEL & CLASSIFY //
// // // ////////////////////////////////////////////////////////////////////////////
//Define and train the classifier. In this case the SVM Classifier.
var SVM = ee.Classifier.libsvm ({
kernelType:'RBF',
// Low gamma measn less curvature.
// High gamma means more curvature.
// Range between 0.001 and 100
gamma: 4,
// Low cost: smooth decision surface.
// Higher cost: you aim to classify more points correctly
// (more missclassification possible).
// Range between 1 and 1000
cost: 50
});
var model = SVM.train({
features:trainingPoints,
classProperty: 'class',
inputProperties: samplingBands
});
// Classify the image using the trained classifier
var classified = maskedImage.classify(model);
// Define a palette for the distint classes
var classPalette = {min:0, max:1, plaette:['#3090C7','#CD7F32']};
// Dis[play map with classification
Map.addLayer(classified, classPalette,"SVM classification",false);
// Display presence pixels ONLY (Useful to export layer of only mangrove to QGis)
var class1Mask = classified.eq(1);
var class1Image = classified.updateMask(class1Mask);
Map.addLayer(class1Image, {}, "class1");
//We crate a mask associated to a polygon to clean the image in the more inland areas where
//we know there is not mangrove
var class1ImageMasked = class1Image.updateMask(
ee.Image.constant(1).clip(inlandPolygon).mask().not()
);
Map.addLayer(class1ImageMasked, {}, 'clean class1');
// // / ////////////////////////////////////////////////////////////////////////////
// // // // 5. ACCURACY ASSESSMENT //
// // // ////////////////////////////////////////////////////////////////////////////
// Calculate accuracy using validation data created in point 3
// Classify the image using the trained classifier
var validation = validationPoints.classify(model);
// Get a confusion matrix representing expected accuracy (Using validation points- 30%)
var errorMatrix = validation.errorMatrix('class', 'classification');
print('validation overall accuracy', errorMatrix.accuracy());
//Estimate user and producer accuracies
var producerAccuracy = errorMatrix.producersAccuracy();
var userAccuracy = errorMatrix.consumersAccuracy();
print('Producer Acuracy SVM', producerAccuracy);
print('User Accuracy SVM', userAccuracy);
// The Kappa Coefficient is generated from a statistical test to evaluate the accuracy
// of a classification. Kappa evaluates how well the classification performed
// as compared to just randomly assigning values, i.e. did the classification do better
// than random. The Kappa Coefficient can range from -1 t0 1. A value of 0 indicated that
// the classification is no better than a random classification. A negative number
// indicates the classification is significantly worse than random. A value close to 1
// indicates that the classification is significantly better than random.
var kappa = errorMatrix.kappa();
print ('Kappa statistic', kappa);
//////////////////////////////////////////////////////////////////////////////////////
// // // 6. EXPORT SHAPE FILE TO DRIVE // //
//////////////////////////////////////////////////////////////////////////////////////
// Si le cambias el nombre a la variable "roi", tambien tienes que cambiarlo en la linea "var region = roi ;"
// cambiar especificamente al area que quieres guardar
// The order of the coordinates goes as follows:
// [[[westLon, southLat],
// [eastLon, southLat],
// [eastLon, northLat],
// [westLon, northLat],
// [westLon, southLat]]]); // repetiddo como la primera
var roi = // south area -Belize-
ee.Geometry.Polygon(
[[[ -88.13157854678775,16.46213607050848],
[-88.13157854678775,16.84992519338283],
[-88.46631111711997,16.84992519338283],
[-88.46631111711997,16.46213607050848],
[-88.13157854678775,16.46213607050848]]]);
// Save the cleaned Sentinel Mosaic RGB at full resolution
var description = 'export_Mnagrove_layer_geotiff_' ; // Description for the export task
var region = roi ; // Region of interest described above
var scale = 10 ; // Spatial resolution in meters. Put here the resolution of you image/satellite.
var crs = 'EPSG:4326' ; // Coordinate reference system (WGS 84)
var maxPix = 1e13 ; // Maximun number of pixels alloed for export
var fileNamePre = 'Mangrove_Placencia_2025' ; // Name the file to save
Export.image.toDrive({
image: class1ImageMasked, // The image variable you want to export
description: description,
region: region,
scale: scale,
fileFormat: 'GeoTIFF',
fileNamePrefix: fileNamePre,
crs: crs,
maxPixels: maxPix,
skipEmptyTiles: true
}) ;
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment