3 Base de Google Earth Engine – La manipulation d’image

Après avoir acquis les savoir-faire de base en JavaScript dans le chapitre 2, nous passons maintenant aux manipulations directes de l’API de Google Earth Engine.

Chargement d’une image dans GEE

Pour commencer, nous allons importer une image du satellite Sentinel-2 en utilisant son identifiant d’image et la placer dans une variable appelée image.

var image = ee.Image(‘COPERNICUS/S2/20220502T153809_20220502T154630_T18TYS’) ;

Dans le cas où vous voulez récupérer les métadonnées de l’image, vous devez utiliser la fonction print et cela imprimera les métadonnées dans la « Console » (Figure 21).

print(image) ;
Figure 21 : Métadonnées de l’image imprimées en console GEE

Pour chaque ligne avec une flèche d’expansion à côté, vous pouvez cliquer, et plus d’informations apparaitront. Par exemple, dans le cas ci-dessus, nous avons développé les métadonnées de la section des bandes. Comme vous pouvez le voir, cela nous montre le nom des bandes ainsi que leur type de données, leur système de projection cartographique et la dimension de l’image dans cette bande spécifique (car la résolution spatiale diffère d’une bande à l’autre). Si vous avez eu des difficultés à comprendre les métadonnées, vous pouvez consulter les informations fournies par GEE dans le champ de recherche situé au-dessus du panneau « Code Editor » (Figure 22).

 

Figure 22 : Champ de recherche situé au-dessus de l’éditeur de code.

Il y a deux façons d’accéder à la description des métadonnées :

  1. en cliquant sur « Browse data catalog » et en sélectionnant le jeu de données que vous utilisez;
  2. en tapant le nom du jeu de données dans la « Search Box » (dans cet exemple, il s’agit de Sentinel-2) (Figure 23).

Le résultat sera le suivant :

Figure 23 : Recherche des ressources liées au mot-clé « Sentinel 2 »

Après avoir cliqué sur le nom de votre jeu de données (dans ce cas, Sentinel-2, Level-1C), vous devriez voir cette boîte de dialogue (Figure 24) :

 

Figure 24 : Informations sur le jeu de données [pb_glossary id="310"]Sentinel-2[/pb_glossary] MSI

Visualisation de l’image

L’étape suivante consiste à visualiser notre image. Pour ce faire, nous devons utiliser une simple ligne de code comme ci-dessous :

Map.addLayer(image) ;

Le résultat sera le suivant (Figure 25) :

Figure 25 : Visualisation d’une image [pb_glossary id="310"]Sentinel-2[/pb_glossary] MSI sans ajustement radiométrique préalable.

Comme vous l’avez remarqué, la visualisation n’est pas adéquate car nous n’avons pas utilisé d’arguments de visualisation d’image pour améliorer le rendu de l’image. Afin d’obtenir de meilleurs résultats dans notre visualisation, nous ajoutons quelques paramètres supplémentaires en marge de l’affichage de l’image (Figure 26).

Figure 26 : Visualisation d’une image [pb_glossary id="310"]Sentinel-2 [/pb_glossary] MSI avec les ajustements radiométriques préalables.

Voici les quatre arguments de la commande Map.addLayer ci-dessus :

  1. image : l’imagerie que nous voulons afficher sur la carte;
  2. bands : les bandes sélectionnées dans l’imagerie à afficher sur la carte. Dans ce cas, nous avons choisi les bandes avec le nom de ‘B4’, ‘B3’ et ‘B2’ comme bandes RVB selon la description de l’ensemble de données que nous avons utilisé. Vous pouvez utiliser une combinaison différente de bandes et l’afficher comme une image composite en fausses couleurs;
  3. min, max : représente l’étendue des valeurs numériques affichées sur la carte. Les valeurs par défaut sont 8000 et 17000 comme min et max, respectivement;
  4. Sentinel-2 Level-1C‘ : l’étiquette pour les données que vous visualisez sur la carte. Elle apparaitra dans la liste des couches du « Gestionnaire de couches », en haut à droite de la carte.

Il existe un autre moyen d’améliorer la visualisation des images sans spécifier d’argument. Vous devez passer la souris sur le « Gestionnaire de couches » et cliquer sur l’engrenage. Cela vous ouvrira un autre panneau appelé « paramètres de visualisation », où vous pourrez essayer différents types d’équilibrage radiométrique pour une seule bande ou trois bandes de votre imagerie. Après avoir défini les paramètres de visualisation, vous pouvez les appliquer à l’affichage de la carte, et lorsque vous trouvez le meilleur réglage, importez-le dans l’éditeur de code (il apparaitra dans la section « Imports » en haut du script dans le panneau de l’éditeur de code) et utilisez-le comme ci-dessous (Figure 27) :

 

Figure 27 : Gestion des paramètres d’affichage avec le « Layer Manager »

Astuce

Si vous voulez simplement visualiser une couche sans aucun paramètre de visualisation mais que vous comptez spécifier une étiquette, vous devez mettre {} ou null ou undefined dans l’argument des paramètres de visualisation de l’image.

Map.addLayer(image, null, ‘Sentinel-2 Level-1C’) ;

Malgré ce paramétrage, il reste toujours une lacune avec notre visualisation et c’est que nous devons déplacer la carte à l’endroit où l’image est affichée dans la carte. Afin de palier à cette situation, la solution simple est d’utiliser la commande Map.centerObject.

Tout d’abord, placez un marqueur sur la zone que l’imagerie doit afficher (une fois que vous avez créé un marqueur sur la carte, une géométrie est créée en haut du panneau de votre éditeur de code) et utilisez la commande. Le premier argument à fournir à Map.centerObject est la géométrie (geometry) que nous avons définie comme notre zone d’intérêt (ici nous l’avons arbitrairement nommée geometry) et le second argument est l’échelle de zoom (ici 10) que vous souhaitez que la carte affiche à l’écran (Figure 28).

Figure 28 : Utilisation de la commande Map.CenterObject pour positionner la carte.

Manipulation de l’image

La sélection des bandes

Pour sélectionner les bandes à afficher d’une image, il y a deux avenues possibles :

  1. .select([var_args]); : Sélectionner les bandes à afficher en utilisant leur nom d’origine (Figure 29);
    Figure 29 : Ouverture d’une image en utilisant les noms originaux des bandes spectrales.
  2. .select([var_args],[nouveaux_nom]); : Sélectionner les bandes à afficher en utilisant leur nom d’origine et en leur réassignant un nouveau nom plus significatif (Figure 30).
    Figure 30 : Ouverture d’une image en modifiant les noms originaux des bandes spectrales pour des noms plus significatifs.

Astuce

Comment connaître les noms des bandes ?

Il y a deux façons courantes (Figure 31):

  1. en ouvrant la boîte de dialogue des données que vous utilisez à ce moment-là;
  2. en imprimant simplement l’image et en cliquant sur la flèche d’expansion à côté des bandes.
Figure 31 : Comment identifier les bandes de l’image ? Méthode 1 (gauche) – À partir de la boîte de dialogue ou; Méthode 2 (droite) – En imprimant les métadonnées de l’image dans la console.

Astuce

Renommer les bandes est une chose importante lorsqu’il s’agit d’intégrer différentes collections d’images.
Par exemple, l’ordre des bandes dans Landsat-5 et Landsat-8 est différent (‘SR_B2’ dans Landsat-5 est la bande verte alors que ‘SR_B2’ dans Landsat-8 est la bande bleue). Une fois que vous avez renommé des bandes telles que ‘R’, ‘G’ et ‘B’, l’ordre des bandes dans la collection d’images n’a plus d’importance car vous appellerez désormais chaque bande par son nouveau nom au lieu de son ordre.

Astuce

Il existe trois manières de créer la liste des bandes :

  1. En sélectionnant les bandes individuellement :
    [‘B4′,’B3′,’B2’]
  2. En sélectionnant les bandes par gamme (range):
    [‘B[2-4]’]
  3. En sélectionnant les bandes via une expression rationelle (RegEx)
    [‘B*’]

Opérations arithmétiques

Les opérations arithmétiques entre les bandes d’une image se déclinent avec des noms qui sont instinctifs. Voyons un exemple afin de mieux comprendre :

// Ouverture d’une image de réflectance Sentinel-2
var image = ee.Image(‘COPERNICUS/S2_SR/20210109T185751_20210109T185931_T10SEG’);

// Sélection individuelle de deux bandes distinctes
var swir1 = image.select(‘B11’);
var swir2 = image.select(‘B12’);
à partir de ces deux bandes individuelles, il nous est possible d’appliquer les opérateurs arithmétiques ci-dessous (parmi d’autres):

.add

var addition = swir1.add(swir2);
// additionner swir1 et swir2

.subtract

var subtraction = swir1.subtract(swir2);
// soustraire swir2 et swir1

.multiply

var multiplication = swir1.multiply(swir2);
// multiplier swir1 et swir2

.divide

var division = swir1.divide(swir2);
// diviser swir1 et swir2

Apprenez-en plus sur les opérateurs en consultant ce lien (+ sur les opérateurs arithmétiques GEE).

Imprimons donc l’un des calculs ci-dessus et voyons-le (Figure 32) :

Figure 32 : Calcul multiplicatif entre deux images dans l’éditeur de code de GEE

Comme vous le voyez, GEE a nommé la multiplication de manière aléatoire en choisissant simplement le nom du groupe original (c’est-à-dire ‘B11‘) mais nous voulons que nos noms d’impression et d’image soient descriptifs. C’est pourquoi nous vous montrons ici comment renommer une image de manière explicite.

Renommer une image

Comme nous l’avons mentionné plus haut, lorsque vous effectuez un calcul, tel que le calcul d’un index à partir d’une image, GEE choisira un nom pour votre nouvelle image, et ce nom ne sera pas descriptif.

Donc, pour éviter toute confusion et pouvoir travailler plus efficacement avec les images calculées, nous devons les renommer. Nous prenons le dernier exemple et vous montrons la différence lorsque vous utilisez rename (Figure 33):

Figure 33 : Multiplication d’images en renommant la bande résultante dans l’éditeur de code GEE

Concaténation

Concaténer les images données en une seule image qui contient toutes les bandes de toutes les images (Figure 34).

ee.Image.cat([‘image1′,’image2’]).set(‘system:id’, ‘stacked_images’);
Figure 34 : Concaténation d’images et renommage du résultat.

Calcul de ratios de bandes (index spectraux)

Avec ce que nous avons appris jusqu’à présent, nous pouvons calculer des ratios spectraux ((A-B)/A+B)) à partir d’images. Il existe différentes façons de le faire. Nous vous présentons ici deux des techniques les plus couramment utilisées pour calculer le NDVI.

  1. normalizedDifference : Calcule la différence normalisée entre deux bandes. La différence normalisée est calculée comme suit : (première – deuxième) / (première + deuxième).
    Attention : Notez que le nom de la bande d’image renvoyée est ‘nd’, que les propriétés de l’image d’entrée ne sont pas conservées dans l’image de sortie et qu’une valeur de pixel négative dans l’une ou l’autre bande d’entrée entraînera le masquage du pixel de sortie. Pour éviter de masquer les valeurs négatives en entrée, utilisez ee.Image.expression pour calculer la différence normalisée.

    // Importer l’image Landsat8 de réfectance.

    var image = ee.Image(‘LANDSAT/LC08/C01/T1_SR/LC08_015028_20210529’);

    // Sélectionner et renommer les bandes.

    Var image = image.select([‘B5’,‘B4’,‘B2’],[‘nir’,‘red’,‘blue’]).clip(montreal);

    // Calcul de la différence normalisée (NDVI).
    // NDVI = (NIR – Red) / (NIR + Red)

    var ndvi = image.normalizedDifference([‘nir’,‘red’]);

    // Afficher le NDVI.

    var ndviParams = {min: -1, max: 1, palette: [‘blue’, ‘white’, ‘green’]};

    Map.addLayer(ndvi, ndviParams, ‘NDVI Image’);

  2. .expression : Calcule en utilisant une expression arithmétique (Figure 35).

    // Importer l’image Landsat8 de réfectance.

    var image = ee.Image(‘LANDSAT/LC08/C01/T1_SR/LC08_015028_20210529’);

    // Sélectionner et renommer les bandes.

    Var image = image.select([‘B5’,‘B4’,‘B2’],[‘nir’,‘red’,‘blue’]).clip(montreal);

    // Calcul de la différence normalisée (NDVI).
    // NDVI = (NIR – Red) / (NIR + Red)

    // Calculer l’index grâce à une expression.

    var ndvi = image.expression(‘(NIR – Red) / (NIR + Red)’{‘NIR’: image.select(‘nir’), ‘Red’: image.select(‘red’)});

    // Display NDVI results.

    var ndviParams = {min: -1, max: 1, palette: [‘blue’, ‘white’, ‘green’]};

    Map.addLayer(ndvi, ndviParams, ‘NDVI Image’);

    Figure 35 : Calcul du NDVI dans la région de l’Île de Montréal

Ajouter une bande à une image

On ajoute une bande à une image avec la fonction suivante.

.addBands()

Dans cet exemple, le NDVI calculé est ajouté à l’image originale comme une nouvelle bande. Vous pouvez voir le résultat de l’impression dans « Console » (Figure 36).

Figure 36 : Ajout du NDVI comme nouvelle bande à une image existante.

Opérations booléennes, relationnelles et conditionnelles

Les objets ee.Image disposent d’un ensemble de méthodes booléennes, relationnelles et conditionnelles permettant de construire des règles et des expressions décisionnelles.

Les résultats de ces méthodes permettent de limiter l’analyse à des pixels ou des régions spécifiques grâce au masquage, à l’élaboration de cartes classées et à la réaffectation de valeurs.

Opérations Booléennes

  • .and : Il retournera vrai si les deux conditions étaient vraies.
  • .or : Il retournera vrai si au moins l’une des conditions  était vraie.
  • .not : Il retournera vrai si aucune des conditions n’est vraie.

Opérations relationnelles

  • .eq : Il retournera vrai si les deux valeurs sont égales.
  • .gt : Il retournera vrai si la première valeur est supérieure à la seconde.
  • .gte : Il retournera vrai si la première valeur  est supérieure ou égale à la seconde.
  • .lt : Il retournera vrai si la première valeur est inférieure à la seconde.
  • .lte : Il retournera vrai si la première valeur est inférieure ou égale à la seconde.

Opérations conditionnelles

  • .Where : Effectue un remplacement conditionnel des valeurs.

Maintenant, pour comprendre ce que ces opérations peuvent réellement faire et comment elles fonctionnent ensemble, nous utilisons un exemple qui a la combinaison de tous les opérateurs ci-dessus (Figure 37).

// Cet exemple effectue une classification basée sur les règles du code prédéfinies.

var image = ee.Image(‘LANDSAT/LC08/C01/T1_SR/LC08_015028_20210529’);

Map.addLayer(image, {bands:[‘B4’,‘B3’,‘B2’], min:108, max:1848}, ‘L8 Image’);

var image = image.select([‘B7’,‘B5’,‘B4’,‘B2’],[‘swir’,‘nir’,‘red’,‘blue’]);

var ndvi = image.normalizedDifference([‘nir’,‘red’]).rename(‘NDVI’);

var ndwi = image.normalizedDifference([‘blue’,‘swir’]).rename(‘NDWI’);

var swir = image.select([‘swir’]);

var ndviParams = {min: -1, max: 1, palette: [‘blue’, ‘white’, ‘green’]};

var ndwiParams = {min: -1, max: 1, palette: [‘green’, ‘white’, ‘blue’]};

Map.addLayer(ndvi, ndviParams, ‘NDVI Image’);

Map.addLayer(ndwi, ndwiParams, ‘NDWI Image’);

var dem = ee.Image(‘USGS/SRTMGL1_003’).clip(image.geometry());

Map.addLayer(dem, {min: 2, max: 779}, ‘SRTM DEM’);

//’regle1′: remplace chaque pixel qui présente un ndvi >= 0.7 par 0.

//’regle2′: remplace chaque pixel qui présente un ndvi entre 0 et 0.7 et dem < 400 par 1.

//’regle3′: remplace chaque pixel qui présente un ndvi < 0.3 et swir > 2000 par 2.

//’regle4′: remplace chaque pixel qui présente un ndvi < 0.3 et ndwi > 0 by 3.

var regle1 = ndvi.where(ndvi.gte(0.7), 0);
//vegetation (color:green)

var regle2 = regle1.where(ndvi.gt(0).and(ndvi.lt(0.7).and(dem.lt(400))), 1);
//urbain (color:black)

var regle3 = regle2.where(ndvi.lt(0.3).and(swir.gt(2000)), 2);
//sol nu (color:bright brown)

var regle4 = regle3.where(ndvi.lt(0.3).and(ndwi.gt(0)), 3).rename(‘CLASS’);
//eau (color:blue)

Map.addLayer(regle4, {palette:[‘#0da919’,‘#0da919’, ‘#000000’, ‘#ff9d39’, ‘#0014ff’]}, ‘Classification’);

 

Figure 37 : Classification réalisée en fonction des critères booléens, conditionnels et relationnels (Montréal)

Application d’un masque

Vous pouvez souhaiter masquer certaines parties de l’image. Le fait de masquer des pixels dans une image les exclut de l’analyse. Nous vous présentons ici deux des méthodes ee.Image qui sont fréquemment utilisées pour le masquage.

  1. updateMask
    Met à jour le masque d’une image à toutes les positions où le masque existant n’est pas nul. L’image de sortie conserve les métadonnées et l’empreinte de l’image d’entrée (Figure 38).

    var image = ee.Image(‘LANDSAT/LC08/C01/T1_SR/LC08_015028_20210529’);

    Map.addLayer(image, {bands:[‘B4’,‘B3’,‘B2’], min:108, max:1848}, ‘L8 Image’);

    // Charger le jeu de données sur les changements forestiers de Hansen

    var hansenImage = ee.Image(‘UMD/hansen/global_forest_change_2015’);

    print(hansenImage);

    // Selectionner le masque eau/terre

    var datamask = hansenImage.select(‘datamask’);

    // Creer un masque binaire.

    // Les masques doivent avoir des valeurs 0 et 1.

    // 0 – pixel rejeté

    // 1 – pixel considéré

    var mask = datamask.eq(1).clip(image.geometry());;

    Map.addLayer(mask, {min:0, max:1}, ‘Mask’);

    // Mets a jour le composite avec le masque.

    var maskedComposite = image.updateMask(mask);

    Map.addLayer(maskedComposite, {bands:[‘B4’,‘B3’,‘B2’], min:108, max:1848}, ‘Masked’);

     

    Figure 38 : Masquage des sections en eau de la région de Montréal.
  2. selfMask
    Mets à jour le masque d’une image à toutes les positions où le masque existant n’est pas nul en utilisant la valeur de l’image comme nouvelle valeur de masque. L’image de sortie conserve les métadonnées et l’empreinte de l’image d’entrée.
    La différence de cette méthode avec updateMask est qu’elle ne met pas à jour une autre image sur la base du masque ; au contraire, elle n’a pas besoin d’introduire le masque pour elle car elle se masque elle-même (ici dans cet exemple : sol nu) (Figure 39).

    var image = ee.Image(‘LANDSAT/LC08/C01/T1_SR/LC08_015028_20210529’);

    Map.addLayer(image, {bands:[‘B4’,‘B3’,‘B2’], min:108, max:1848}, ‘L8 Image’);

    // Creer les indices NDVI et NDWI

    var ndvi = image.normalizedDifference([‘B5’, ‘B4’]);

    var ndwi = image.normalizedDifference([‘B3’, ‘B5’]);

    var solnu = ndvi.lt(0.2).and(ndwi.lt(0));

    // Masquer et afficher l’image résultante

    Map.addLayer(solnu.selfMask(), {palette:[‘#ff0000’]}, ‘Sols nus’);

     

    Figure 39 : Masquage de l’entièreté de l’image sauf les zones de sols nu dans la région de Montréal grâce au selfMask

Récupérer une information sur l’image

La fonction qui permet d’obtenir l’identifiant (ID) de l’image est .id et l’utilisation de .getInfo permet de transposer les objets du côté serveur vers le côté client (Figure 40).

Figure 40 : Récupération de l’information d’identifiant de l’image du côté serveur pour affichage côté client

Attention

L’utilisation de .getinfo() en de nombreuses instances peut amener des soucis de synchronisation entre le serveur et le client. Il faut donc y faire appel avec parcimonie.

Ajout d’une propriété à une image

Si vous voulez ajouter une nouvelle propriété à l’image, utilisez .set et suivez la structure ci-dessous (Figure 41):

Figure 41 : Ajout d’une propriété factice à une image
definition

Licence

Symbole de License Creative Commons Attribution - Pas d’utilisation commerciale 4.0 International

Maitriser le développement sous Google Earth Engine Droit d'auteur © 2023 par Charles Gignac, Maryam Rahimzad et Saeid Homayouni est sous licence License Creative Commons Attribution - Pas d’utilisation commerciale 4.0 International, sauf indication contraire.

Partagez ce livre