NDWI and water level monitoring

I am working on a GEE script to monitor the water level of a lake in Switzerland. I have one script for Landsat 5 bands (before 2015) and one script for Sentinel2 bands. I'm trying to classify the pixels of water in blue and the others in black: it works for the script in Landsat but not in S2, even if I changed the bands... I also tried to make a gap filling and a smoothing but I have an error message saying: "Image.reduceRegion, argument 'image': Invalid type. Expected type: Image. Actual type: ImageCollection"

var areaOfInterest =
    ee.Geometry.Polygon(
        [[[6.684030451902143,47.06054590866372],
[6.711152949460737,47.06054590866372],
[6.711152949460737,47.086149628020074],
[6.684030451902143,47.086149628020074]]]);
// Zoom sur l'aire
Map.centerObject(areaOfInterest);
Map.addLayer(areaOfInterest);

// Définir une aire temporelle
var startDate = '2016-07-01';
var endDate = '2016-08-31';

// Charger les données S2 pour la période sélectionnée
var sentinelImageCollection = ee.ImageCollection('COPERNICUS/S2')
                  .filterBounds(areaOfInterest)
                  .filterDate(startDate, endDate);
print("Nombre d'images = ", sentinelImageCollection.size());

// Filtrer les nuages et choisir l'image la moins nuageuse
var sentinelImage = 
    sentinelImageCollection.sort('CLOUDY_PIXEL_PERCENTAGE')
    .first()
    .clip(areaOfInterest);
print("Image la moins nuageuse = ", sentinelImage.date());

// Visualisation avec filtre RGB
Map.addLayer(
    sentinelImage,
    {min: 0.0, max: 2000, bands: ['B4', 'B3', 'B2']},
    'RGB');
    
    // Calculer le NDWI
var ndwi =
    sentinelImage.normalizedDifference(['B3', 'B8']).rename('NDWI');
Map.addLayer(
    ndwi,
    {palette: ['red', 'yellow', 'green', 'cyan', 'blue']},
    'NDWI');
    
   //Créer le filtre pour les pixels d'eau 
var ndwiThreshold = ndwi.gte(0.0);
var ndwiMask = ndwiThreshold.updateMask(ndwiThreshold);
Map.addLayer(
    ndwiThreshold,
    {palette:['black', 'white']},
    'NDWI Binary Mask');
Map.addLayer(ndwiMask, {palette:['blue']}, 'NDWI Mask');

// Exporter l'image, spécifier le système de coordonnées, l'échelle, et sélectionner la région.
Export.image.toDrive({
  image: ndwiThreshold.visualize({min:0, max:1}),
  description: 'NDWI binary mask',
  crs: 'EPSG:4326',
  scale: 10,
  region: areaOfInterest
});

// Calculer les pixels d'eau dans l'aire
var ndwiPixelArea =
    ee.Image.pixelArea().addBands(
        ndwiMask.select('NDWI')).divide(1e6).reduceRegion({
            reducer: ee.Reducer.sum().group(1),
            geometry: areaOfInterest,
            scale: 10,
            bestEffort: true
});

var list = ee.List(ee.Dictionary(ndwiPixelArea).get('groups'));
var group0 = ee.Dictionary(list.get(0));
var ndwiWaterArea = ee.Number(group0.get('sum')).float();

print("Surface d'eau (km2):", ndwiWaterArea);


// Calcul du MNDWI
 // Utilisation de la bande infrarouge courte (B11) pour détecter l'eau
var mndwi = sentinelImageCollection.map(function(image) {
  var mndwi = image.normalizedDifference(['B3', 'B11']);  
   return mndwi.rename('MNDWI').copyProperties(image, image.propertyNames());
});

// Visualisation
var mndwiParams = {min: -1, max: 1, palette: ['blue', 'white', 'green']};
Map.addLayer(mndwi, mndwiParams, 'MNDWI');

// Calcul de la moyenne et de l'écart-type du NDWI sur la période
var mndwiMean = mndwi.reduce(ee.Reducer.mean());
var mndwiStdDev = mndwi.reduce(ee.Reducer.stdDev());

print("Moyenne du MNDWI :", mndwiMean);
print("Écart-type du MNDWI :", mndwiStdDev);


// Création d'une collection de données temporelles pour la régression linéaire
var timeSeries = ee.ImageCollection(mndwi.iterate(function(image, prev) {
  return ee.Image(prev).addBands(image);
}, ee.Image(0)));

// Régression linéaire sur la série temporelle
var linearTrend = timeSeries.reduce(ee.Reducer.linearFit());

// Extraction de la pente (tendance) de la régression linéaire
var slope = linearTrend.select('scale');


// Tracé de la série temporelle du MNDWI pour un pixel donné
var chart = ui.Chart.image.series({
  imageCollection: mndwi,
  region: areaOfInterest,
  reducer: ee.Reducer.mean(),
  scale: 30  

// Résolution des données Sentinel-2
}).setOptions({title: 'Série temporelle du MNDWI'});

print(chart);

//Histogramme
var Histogramme= ui.Chart.image.histogram(mndwi,areaOfInterest,100,10);
Histogramme = Histogramme.setOptions({title:'Histogramme MNDWI'});
print(Histogramme);

//Affichage de la legende
var palette = ['ff3510','ebff10','20ff18','1afff2','1629ff']

function createColorBar(titleText, palette, min, max) {
  // Titre de la légende
  var title = ui.Label({
    value: titleText, 
    style: {fontWeight: 'bold', textAlign: 'center', stretch: 'horizontal'}});

  // Bande de couleurs
  var legend = ui.Thumbnail({
    image: ee.Image.pixelLonLat().select(0),
    params: {
      bbox: [0, 0, 1, 0.1],
      dimensions: '200x20',
      format: 'png', 
      min: 0, max: 1,
      palette: palette},
    style: {stretch: 'horizontal', margin: '8px 8px', maxHeight: '40px'},
  });
  
  // Labels de la légende
  var labels = ui.Panel({
    widgets: [
      ui.Label(min, {margin: '4px 10px',textAlign: 'left', stretch: 'horizontal'}),
      ui.Label((min+max)/2, {margin: '4px 20px', textAlign: 'center', stretch: 'horizontal'}),
      ui.Label(max, {margin: '4px 10px',textAlign: 'right', stretch: 'horizontal'})],
    layout: ui.Panel.Layout.flow('horizontal')});
  
  // Création d'un panel avec les trois éléments
  var legendPanel = ui.Panel({
    widgets: [title, legend, labels],
    style: {position: 'bottom-left', padding: '8px 15px'}
  })
  return legendPanel
}
// Création de la légende 
var colorBar = createColorBar('Valeurs du NDWI', palette, 0, 0.99)

Map.add(colorBar)

//// Création d'un UI application////

// Définition du layout de l'UI App
var title = ui.Label ('Explorateur NDWI Lac des Brenets');
title.style().set({
  'position': 'top-center',
  'fontSize': '24px'
});
var resultsPanel = ui.Panel();
var chartPanel = ui.Panel();
var selectionPanel = ui.Panel({
  layout: ui.Panel.Layout.flow('horizontal'),
})

resultsPanel.style().set({
  width: '400px',
  position: 'bottom-right'
});
var resetPanel = ui.Panel();

resultsPanel.add(selectionPanel)
resultsPanel.add(chartPanel)
resultsPanel.add(resetPanel)

//Fonction pour remettre l'application à l'état initial
var resetEverything = function() {
  chartPanel.clear()
  selectionPanel.clear()
  resetPanel.clear()
  
  Map.clear()
  
//Addition des éléments à afficher
  Map.add(title);
  Map.add(resultsPanel)
  Map.onClick(displayChart)
  
//Suppression des éléments à ne pas afficher
  //Map.setControlVisibility(false);
  //Map.setControlVisibility({zoomControl: true});

  
// Définir la fenêtre de visualisation initiale
//var bounds = ee.Geometry.Rectangle(Map.getBounds())
  Map.addLayer (ndwi, mndwiParams, 'NDWI', 1)
  Map.add(colorBar)

  var label = ui.Label ('Cliquez sur la carte pour afficher les données en un point')
  resetPanel.add(label)
}
// Création et affichage du graphique
var displayChart = function(point){
  resetPanel.clear()
  var button = ui.Button({
    label: 'Reset',
    onClick: resetEverything})
    resetPanel.add(button)
    var pselect = ee.Geometry.Point(point['lon'], point['lat']).buffer(1e4);
Map.addLayer(pselect, null, 'area')
    
//Mediane du buffer de notre point
  var ndwimean = sentinelImageCollection.select('NDWI').map(function(img){
  var mean = image.reduceRegion({
    reducer:ee.Reducer.mean(),
    geometry: pselect,
    scale: 1e3,
    bestEffort:true,
    maxPixels: 1e14,
    tileScale:4,
  });
  return ee.Feature(null,mean).set('system:time_start',img.get('system:time_start'));
});

  var chart = ui.Chart.feature.byFeature(ndwimean, 'system:time_start', 'NDWI')
  .setOptions({
  title: 'NDWI Time Series',
   vAxis: {title: 'NDWI'},
        hAxis: {title: 'Date'}, 
        gridlines: {count:12},
        trendlines: { 0: {  
      type: 'linear',
      color: 'green',
      lineWidth: 3,
      opacity: 0.2,
    }
  }
});
        chartPanel.clear()
        selectionPanel.clear();
        
//Addition d'un bouton pour choisir la date à afficher
        selectionPanel.add(ui.Label('Choissisez une image à afficher:'))
        chartPanel.add(chart)
        
        var addndwiLayer = function(dateString){
          var date = ee.Date.parse ('YYYY-MM-DD', dateString)
          var image = ee.Image(sentinelImage.filter(ee.Filter.date(date,date.advance(1,'month'))).mosaic())
          Map.addLayer(image.select('NDWI'), mndwiParams, 'NDWI Image -' + dateString)
        }
        
        sentinelImageCollection.aggregate_array('system:time_start').evaluate(function(ids){
          var dates = ee.List(ids).distinct().map(function(timestamp){
            return ee.Date(timestamp).format('YYYY-MM-DD')
          })
          dates.evaluate(function(dateList){
            selectionPanel.add(ui.Select({
              items: dateList,
              onChange: addndwiLayer,
              placeholder: 'Choissisez une date'
            }))
          })
        });
}; 

// Réinitialisation
resetEverything();

I tried changing the bands for the S2 bands, and tried changing ImageCollection to SentinelImageCollection

Upvotes: 0

Views: 60

Answers (1)

ciranzo
ciranzo

Reputation: 82

I'm trying to classify the pixels of water in blue and the others in black: it works for the script in Landsat but not in S2, even if I changed the bands...

var ndwiWater = ndwi.gte(0.0); // 1 values == water
var ndwiMask = ndwi.updateMask(ndwiWater); // Get ndwi water values
Map.addLayer(ndwiWater, {palette:['black', 'blue']}, 'NDWI Binary Mask');
Map.addLayer(ndwiMask, {palette:['blue']}, 'NDWI Mask');

The ndwiWater variable is a binary image (0,1) that should be applied to the original image (ndwi) in order to select only the pixels with a value of 1 (ndwiMask).

I also tried to make a gap filling and a smoothing but I have an error message saying: "Image.reduceRegion, argument 'image': Invalid type. Expected type: Image. Actual type: ImageCollection"

This error is related to the ui.Chart.image.histogram. According to the function documentation, the first parameter must be an image (not an ImageCollection).

//Histogramme
var Histogramme= ui.Chart.image.histogram(mndwi.first(),areaOfInterest,100,10);
Histogramme = Histogramme.setOptions({title:'Histogramme MNDWI'});
print(Histogramme);

I hope these comments help resolve your issues.

Upvotes: 1

Related Questions