Vous êtes sur la page 1sur 21

INTRODUCTION A L’API

JAVASCRIPT

Fernand BALE, mai 2019


SOMMAIRE

1. GENERALITES 2

2. PRENDRE SES MARQUES DANS GEE 3

5.1. PREREQUIS 4
5.2. SE CONNECTER 4

3. GOOGLE EARTH ENGINE CODE EDITOR 5

4. INTRODUCTION A GEE JAVASCRIPT API 6

5. TRAITEMENT D’IMAGES ET DE COLLECTIONS D’IMAGES 8

5.1. ALGORITHMES DE DENUAGEMENT ET DE CALCULS DE NDVI 8


5.2. CALCUL DU NDVI D’UNE COLLECTION 14
5.3. SAUVEGARDER SES DONNEES 18
5.4. UPLOADER SES PROPRES DONNEES 19
5.5. PARTAGER ET EXPORTER SES RESULTATS 19

6. RESSOURCES 19

PAGE 1
1. GENERALITES
Google Earth Engine est une plate-forme cloud pour l'analyse des données géospatiales à
l'échelle mondiale. Les principaux composants de Earth Engine sont:

Base de données: Une archive d'images satellites et autres bases de données geospatiales
disponibles en libre accès.
Puissance de Calcul: une infrastructure de calcul comprenont plus de 20.000 serveurs Google
optimisée pour le traitement parallèle des données géospatiales.
API: API pour JavaScript et Python (hébergées sur GitHub) pour effectuer des requêtes aux
serveurs Earth Engine. Ces documents se concentrent sur JavaScript. (Guide de démarrage
pour l'API Javascript). Pour Python, consultez le guide d'installation Python et les exemples
Python dans le référentiel Earth Engine GitHub.
Éditeur de code: Un environnement de développement intégré (IDE) en ligne pour le
prototypage rapide et la visualisation d'analyses spatiales complexes à l'aide de l'API
Javascript.
Google Earth Engine comprend :
 Earth Explorer : https://explorer.earthengine.google.com/
 Earth Code Editor : https://code.earthengine.google.com/

PAGE 2
2. PRENDRE SES MARQUES DANS GEE
Google Earth Engine permet aux utilisateurs d'exécuter des algorithmes sur des images satellites
géoréférencées et des données vecteurs stockées sur l'infrastructure de Google.
L'API JavaScript de Google Earth Engine fournit une bibliothèque de fonctions permettant la
visualisation et l’analyse de données issues de satellites. En effet, le catalogue de données
publiques de Earth Engine donne accès à une grande quantité d'images et de données
vectorielles.
Il est possible d’ajouter ses propres données et les intégrer à l’analyse.
Il faut donc bien comprendre que tout, absolument tout se fait en ligne ! Néanmoins, les résultats
des traitements peuvent être sauvegardés dans Google Drive, puis téléchargés par la suite.

PAGE 3
Utilisateur navigateur Earth Engine

Figure 1: Exemple d'application développée par GEE

5.1. PREREQUIS
- Notions sur les images satellites
- Notions sur le traitement d’images satellites
- Notions de programmation orientée objets
- Avoir un compte Gmail

5.2. SE CONNECTER
Pour utiliser Google Earth Engine, il faut :
- se connecter à l’adresse : https://code.earthengine.google.com
- Créer un compte

PAGE 4
3. GOOGLE EARTH ENGINE CODE EDITOR
Dans cette section nous allons pratiquer pour mieux apprendre. Dans un premier temps
familiarisons nous avec l’interface de GEE Code editor :

L'éditeur de code Earth Engine (EE), uniquement disponible sur code.earthengine.google.com


est un IDE pour l'API JavaScript de Google Earth Engine. Les fonctionnalités de l'éditeur de
code facilitent et accélérent le développement de traitements géospatiaux complexes.
L'éditeur de code comprend les sections suivantes (cf. figure 1):
 Fenêtre cartographique pour la visualization des données geospatiales
 Documentation de référence de l’API (Docs tab)
 Gestionnaire de script (Scripts tab)
 Ecran de sortie (Console tab)
 Gestionnaire de tâches (Tasks tab)
 Fenêtre d’interaction avec la carte (Inspector tab)
 Moteur de recherche de données ou de scripts
 Outils de dessin.

PAGE 5
4. INTRODUCTION A GEE JAVASCRIPT API
a. Premier script (Hello World)

// Création d’une variable que nous appelons salutation


var salutation = "Hello World"
// Affichage de la variable dans la console
print(greeting)

b. Les types de données


// Strings
// Create a variable called greeting
var greeting = "Salut"
// Show that variable in the console
print(greeting)

// Create a variable called number


var number = 42
// Display that variable in the console
print(number)

// Create a list called listOfNumbers, and give it the values 4, 5, 6, 7


var listOfNumbers = [4, 5, 6, 7]
// Display that variable in the console
print(listOfNumbers)

// Change the value of number to the second element of listOfNumbers, 6


number = listOfNumbers[2]
// Display the new number
print(number)

// Create a dictionary called Stephen dictionary, that contains information about Stephen
var stephenDictionary = {

PAGE 6
// Create a 'name' property, that contains Stephen's name
name: "Stephen",
// Create a 'height' property, that contains Stephen's height
height: 2.0
}

// Print our dictionary


print(stephenDictionary)

// Add five to a number, and print it


print(number + 5)

// Create a function that has two parameters (aka, 'inputs', aka, 'parameters')
var myFunction = function(input1, input2) {
// displays the first input
print("input1 was", input)
// returns the second input
return input2
}

// This function always returns the number five. It has no parameters / arguments / inputs
var noInputs = function() {
return 5
}

// Use our function with number and the value 6. We 'invoke' (aka, 'call', aka, 'run')
// a function by putting parentheses after its name. Any aruments that we are passing
// to the function go in the parentheses.
myFunction(number, 6)

// Assignment: Create a function to add two numbers


function addTwoNumbers(number1, number2) {
// Put your code below.

PAGE 7
return
}
// Should print: 3
print(addTwoNumbers(1, 2))

// assign the variable sum to


var sum = addTwoNumbers(5, 3)
print('sum', sum)

5. Traitement d’images et de collections d’images

Le type imageCollections represente une collection d'images d’un capteur. Les collections
d'images peuvent être filtrées, de sorte que certaines images sont exclues en fonction d'éléments
tels que le lieu, l'heure ou le taux de nuages.
Les collections d'images peuvent être traitées en blocs grâce à la fonction « map ». Elle permet
en effet de modifier chaque image de la collection en une seule ligne de code. Les collections
d'images peuvent être réduites, chaque image de la collection étant aplatie en une seule image.
Dans ce script, nous allons charger une collection d'images. Ensuite, nous allons filtrer la
collection d'images, en sélectionnant uniquement les images qui sont dans une certaine
géométrie et dans un certain laps de temps. Ensuite, nous allons cartographier la collection
d'images, en masquant les pixels qui comportent beaucoup de nuages. Enfin, nous allons réduire
la collection d'images, et prendre une mosaïque ou médiane de la collection.
Exercice:
• définir une région d'intérêt
• Utiliser .filterBounds pour sélectionner uniquement les images dans une zone donnée.
• Utiliser .filterDates pour sélectionner uniquement ces images en 2017.
• Ajouter notre collection d'images à la carte.

5.1. ALGORITHMES DE DENUAGEMENT ET DE CALCULS DE NDVI

var ls8 = ee.ImageCollection('LANDSAT/LC08/C01/T1_TOA')

// Create a polygon in the Park W. We use ee.Geometry.Rectangle. We give it


a list
// of coordinates. The first two are for the bottom-left. The second two
are the
// coordinates for the top-right.
var aoi = ee.Geometry.Rectangle(

PAGE 8
[
// Coordinates for the botom-left
2.2, 11.9,
// Coordinates for the top-right
2.5, 12.2
]
)

// Add the geometry to the map.


Map.addLayer(aoi, {}, 'AOI')
// Select Landsat scenes within the geometry. We will use .filterBounds.
// .filterBounds takes a geometry, and only returns those scenes that
intersect
// that geometry.
var filteredImages = ls8
.filterBounds(aoi)

// Your image collection should contain <<NUMBER>>


print('After filtering bounds, collection size', filteredImages.size())
print('Expected Size:', 341)

// Select scenes from 2017. We will use the .filterDates method.


.filterDates
// takes two dates, in the form of strings. The first date is the start
date.
// The second date is the end date. Only scenes between these dates will
remain
// in the collection. Dates are in the format 'YYYY-MM-DD'.
filteredImages = filteredImages
.filterDate('2017-01-01', '2017-12-31')

// Your image collection should contain 64 images


print('After filtering date, collection size:', filteredImages.size())
print('Expected Size:', 64)

/*
Every Landsat scene has a 'CLOUD_COVER' property. This represents the
percentage
of the scene that is covered in clouds. We will filter out scenes that
are covered
by 40% clouds or greater. .filter() takes as a property an ee.Filter
object.
You can read more about the filters in the Docs tab. We are going to use
the
filter ee.Filter.lt('CLOUD_COVER', 0.4). Images only pass the filter if
their
'CLOUD_COVER' property is less than 0.4.
*/

PAGE 9
filteredImages = filteredImages
.filter(ee.Filter.lt('CLOUD_COVER', 0.4))

print('After filtering date, collection contains:', filteredImages.size())


print('Expected Size:', 19)

// Add the image collection to the map.


Map.addLayer(filteredImages, {min: 0, max: 0.3, bands:'B4,B3,B2'},
'processed image collections')
print(filteredImages)
/*
Mapping an image collection
When we map an image collection, we use a function to modify every
element in
that collection. We provide the .map() collection with a function. The
function
must take an image as its input, and return a new image. Typically, we
use map
to do something like calculating NDVI for every image in a collection,
getting statistics for every image in a collection, or masking every
image in
a collection for clouds.

In this example, we will map a collection for clouds, so that every image
will
have its clouds masked. First, we must create a function that will mask
our
images. To determine what is clouds and what is not, we will use a built-
in
Earth Engine function, called ee.Algorithms.Landsat.simpleCloudScore().
This
takes a Landsat TOA image and returns the same image, with a new band,
'cloud',
that represents the cloudiness of this pixel. More information about
.simpleCloudScore()
is available in the Docs tab.

Once we have an image with information about how cloudy each pixel is, we
will
create a mask where pixels of a certain cloudiness are masked. Finally,
we will
return our masked image.
*/

// So we create our maskClouds function


var maskClouds = function(image) {

PAGE 10
// We want to run the image through the
ee.Algorithms.Landsat.simpleCloudScore().
// This gives the percent chance that the pixel is a cloud.
image = ee.Algorithms.Landsat.simpleCloudScore(image)

// Now we can create a mask. .lte() (think, Less Than or Equal) returns
an image
// where each pixel is 0 if it fails the test, and 1 if it passes. So in
the
// mask image, each pixel will be 1 if it is less than or equal to 0.5,
or
// 0 if it is greater than 0.5.

// We want to create the cloud mask, from the 'cloud' band, so we select
that
// band from the image.
var cloudMask = image.select('cloud')
cloudMask = image.lte(0.5)
// We now apply that mask to the image, using .updateMask().
image = image.updateMask(cloudMask)
return image
}

// Let's see how our masked collection looks.


var maskedImages = filteredImages.map(maskClouds)
Map.addLayer(maskedImages, {min: 0, max: 0.3, bands:'B4,B3,B2'}, 'Masked
Collection')

/*
Compositing and mosaicking
We now have a collection of images, which we have filtered and masked
for clouds. We would now like to turn that collection of images into a
single
image. This will make it easier to analyze or export our information.

There are two techniques that we will look at for turning an image
collection into a
single image. One is mosaicking, and the other is compositing.

Mosaicking
There are two ways that we can mosaic in Earth Engine. We use the
.mosaic() function on
a collection, and Earth Engine will mosaic our masked images, giving
preference to
more recent images.

We can also use .qualityBand('bandName'). This will order the pixels by


the band name

PAGE 11
that we pass.
*/

// Mosaic an image
var mosaickedImage = maskedImages.mosaic()
Map.addLayer(mosaickedImage, {min: 0, max: 0.3, bands:'B4,B3,B2'},
'Mosaicked Image')

// Quality mosaic an image


var qualityMosaickedImage = maskedImages.qualityMosaic('cloud')
Map.addLayer(qualityMosaickedImage, {min: 0, max: 0.3, bands:'B4,B3,B2'},
'Quality Mosaicked Image')

/*
Compositing
Another way that we can turn a collection into a single image is by
using
compositing. We might take the min, the median, the max or the mean value
of a pixel. There are corresponding methods to composite a collection
(ie,
.min(), .max(), .median(), .mean() ). You can read more in the Docs tab.
Right
now, let's take the median value.
*/

// Composite an image
var compositedImage = maskedImages.median()
Map.addLayer(compositedImage, {min: 0, max: 0.3, bands:'B4,B3,B2'},
'Composited Image')

// Take a moment to try out other ways of compositing, like .mean(),


.min(), .max().

/*
Clipping an Image
You can see that our coposited image is much larger that our AOI. We
would like
to clip the image to our original AOI. We can clip an image by using the
clip function.
When we use .clip(), we pass the geometry that we would like to clip an
image to.
We can only use .clip on an image, not on an image collection. If we had
tried to use
this function on our collection before compositing, it would have given
an error.
*/
var clippedImage = compositedImage.clip(aoi)
Map.addLayer(clippedImage, {min: 0, max: 0.3, bands:'B4,B3,B2'}, 'Clipped
Image')

PAGE 12
/*
We have now successfully processed a Landsat collection into a single
image.
We have:
* Created an ee.ImageCollection variable that refers to the Landsat 8
Tier 1 TOA collection.
* Filtered that collection, limiting scenes based on date, on location,
and on cloud coverage.
* Mapped over that collection, to mask cloudy pixels.
* Composited or mosaicked that collection of images into a single
image.
* Clipped that composite image to our original area of interest.
*/

/*
Optional: Chaining function calls
Up to this point, we have been assigning the returned value of each
function
to a new variable, and passing that new variable to the next function,
and so on.
It is possible, however, for us to directly pass the results of each
function
to the next, without having to declare a new variable. The result of the
functions
is exactly the same: we only do this because it is easier to read and
easier to write.

When we chain together function calls, we do it by putting a . between


the methods.
For example, we could write:
var collection = ls8.filterBounds(aoi).filterDate('2016-01-01', '2016-12-
31')

Furthermore, we can put a line break between function calls that we have
chained
together in this way. Below is our function rewritten so that all of the
function
calls are chained together.
*/

var chainedImage = ls8.filterBounds(aoi)


.filterDate('2017-01-01', '2017-12-31')
.filter(ee.Filter.lt('CLOUD_COVER', 0.4))
.map(maskClouds)
.median()
.clip(aoi)

PAGE 13
Map.addLayer(chainedImage, {min:0, max:0.3, bands:'B4,B3,B2'}, 'chained
image')

5.2. CALCUL DU NDVI D’UNE COLLECTION

/*
Normalized difference

Normalized difference bands (also called spectral indices)


express a relationship between two bands. You are all likely familiar
with
a number of normalized diference bands, such as Normalized Difference
Vegetation Index (NDVI), Normalized Difference Moisture Index (NDMI),
or Normalized Burn Ratio (NBR).

Earth Engine makes calculating normalized difference bands simple,


using the
.normalizedDifference method.

For this exercise, we will calculate and display normalized difference


bands
for a Landsat image and time series.
*/

/*
To calculate spectral indices, we are going to use the
ee.Image().normalizedDifference()
function. Using the Docs tab, we can see that normalizedDifference() is a
function
that acts on an image. It has one input: a list containing the names of
the
two bands that are to be used for the normalized difference calculation.
The
returned value is an image where each pixel is equal to:
(first − second) / (first + second)

*/

// First, we will load a single Landsat 8 image. I have chosen a Landsat 8


image
// to test our code on. I found its ID by printing a collection to the map
and
// reading its ID.

var landsatImage = ee.Image("LANDSAT/LC08/C01/T1_TOA/LC08_192052_20170219")

PAGE 14
/*
We now need to determine what bands we are going to use for different
spectral
indices. Using the Docs tab, we saw that the function's input is a list
of strings
representing the names of the bands we are going to use for our
calculations.
We can use the Landsat spectral indices guide
(https://landsat.usgs.gov/sites/default/files/documents/si_product_guide.pd
f)
to see which bands to use for different indices. For now, we will only
use NDVI.
*/

var landsatNdviBands = ["B5", "B4"]

var landsatNdviImage = landsatImage.normalizedDifference(landsatNdviBands)

/*
Now, let's add our NDVI image to the map. We will give it a palette
from the colors
'brown' to the color 'green', and it will stretch the values between
these two colors.
Using the inspector, you can click around on your NDVI image to see what
values are present.
Based on what values you see, choose a min and max value for your
visualiztion.
(replace the null values below)
*/

Map.addLayer(landsatNdviImage, {min: null, max: null, palette:


'brown,green'}, 'landsat_ndvi')

/*
Compare your image with your neighbor.
*/

/*
Sentinel NDVI
We have created a Landsat NDVI. Now, let's create a Sentinel NDVI. The
Sentinel 2
NDVI bands are Bands 4 and 8 (I think...)
*/

// First, we load a Sentinel 2 image.


var sentinelImage =
ee.Image("COPERNICUS/S2/20160916T101022_20160916T171853_T31PDP")
// Now we decide on our normalizedDifference bands.

PAGE 15
var sentinelNdviBands = ["B4", "B8"]
var sentinelNdviImage =
sentinelImage.normalizedDifference(sentinelNdviBands)
Map.addLayer(sentinelNdviImage, {min: null, max: null, palette:
'brown,green'}, 'Landsat NDVI')
/*

=====
Exercises
=====
*/

/*
Getting NDMI
Let's try getting a different kind of spectral index. In Landsat 8, the
NDMI bands
are Band 5 and Band 6. The code below almost works, but it's missing a
little bit.
Replace the null values to make the code work.
*/
var landsatNdmiBands = [null, null]
var landsatNdmiImage = landsatNdmiImage.normalizedDifference(null)
Map.addLayer(landsatNdmiImage, {min: null, max: null, palette:
'white,blue'}, 'Landsat NDMI')

/*
getNdvi function
It would be quite convenient if we could create a function that would
calculate
an image's NDVI and return it. Let's create a function called getNdvi
that takes
a Landsat 8 image as an input and returns that image's NDVI. Replace the
null values.
*/
var getNdvi = function (landsatImage) {
var landsatNdviBands = null
var landsatNdviImage = null
return landsatNdviImage
}

// Now we can assess our function's output with


Map.addLayer(getNdvi(landsatImage), {min:null, max:null,
palette:'brown,green'})

/*
======
Extra
======

PAGE 16
(The following is advanced. We won't go over it in the workshop, but you
may find
it useful.)

Custom Expressions
We saw how to generate a normalized difference index. That calculation
is fairly simple. It is possible to use custom defined indices instead.
We will
use the example of Enhanced Vegetation Index.
*/
// To generate our EVI, we use ee.Image().expression. This takes two
arguments:
// a string defining the arithmetic function to be used to calculate the
index,
// and an optional dictionary, that creates variables that we can use in
our expression.
// You can read more in the Docs tag.

// The first argument is the expression to be used to calculate the EVI


value.
// For each pixel, any variables like 'nir', or 'red' are replaced with the
// value defined in the dictionary below. Then, the equation is evaluated
by the
// earth engine servers.
var landsatEvi = landsatImage.expression(
'2.5 * (nir - red) / (nir + 6 * red - 7.5 * blue + 1)',
// The keys of this dictionary provide the variable names for the
expression above.
{
'red': landsatImage.select('B3'),
'nir': landsatImage.select('B4'),
'blue': landsatImage.select('B1')
})

PAGE 17
CLASSIFICATION NON SUPERVISE

// Load a pre-computed Landsat composite for input.


var input = ee.Image('LANDSAT/LE7_TOA_1YEAR/2001');

// Define a region in which to generate a sample of the input.


var region = ee.Geometry.Rectangle(29.7, 30, 32.5, 31.7);

// Display the sample region.


Map.setCenter(31.5, 31.0, 8);
Map.addLayer(ee.Image().paint(region, 0, 2), {}, 'region');

// Make the training dataset.


var training = input.sample({
region: region,
scale: 30,
numPixels: 5000
});

// Instantiate the clusterer and train it.


var clusterer = ee.Clusterer.wekaKMeans(15).train(training);

// Cluster the input using the trained clusterer.


var result = input.cluster(clusterer);

// Display the clusters with random colors.


Map.addLayer(result.randomVisualizer(), {}, 'clusters');

5.3. SAUVEGARDER SES DONNEES


Google Earth Engine permet deux modes de sauvegardes, via Assets (dans
l’environnement GEE) et Google Drive.

PAGE 18
5.4. UPLOADER SES PROPRES DONNEES
Le upload de données s’effectue via l’ongte Assets. L’utilisateur peut importer des images
TIFF/GeoTIFF ou des shapes files et les organiser en ligne.

5.5. PARTAGER ET EXPORTER SES RESULTATS


Il est possible de partager ses codes et données grâce à l’outil Get link, qui génère le chemin
d’accès à partager par email. On peut également donner accès à son repository à travers les
options de l’Assets

6. Ressources
a. Documentation officielle

PAGE 19
https://developers.google.com/earth-engine/

b. Forum de développeurs

c. Earth Engine & App Engine Example Apps

https://github.com/google/earthengine-api/tree/master/demos
https://developers.google.com/earth-engine/tutorial_api_01

PAGE 20