Classification LULC avec Sentinel-2
Un guide complet pour la classification de l'occupation du sol (LULC) utilisant les données Sentinel-2 dans Google Earth Engine
Couverture complète
Toutes les étapes du processus de classification, de la préparation des données à l'évaluation des résultats.
Random Forest
Utilisation de l'algorithme Random Forest pour une classification robuste et précise.
Analyse complète
Inclut la validation, le calcul des superficies et l'exportation des résultats.
Code complet pour la classification LULC
// Étapes: échantillonnage, entraînement, validation, classification et visualisation // -------------------------------- // 1. PRÉPARATION DES DONNÉES // -------------------------------- // Définir la zone d'étude (à remplacer par votre propre geometry) // Vous pouvez dessiner votre propre geometry en utilisant l'outil de dessin ou importer une limite administrative var geometry = ee.Geometry.Rectangle([/* vos coordonnées */]); // Charger la collection d'images Sentinel-2 var s2Collection = ee.ImageCollection('COPERNICUS/S2_SR') .filterDate('2023-01-01', '2023-12-31') // Ajustez la période selon vos besoins .filterBounds(geometry) .filter(ee.Filter.lt('CLOUDY_PIXEL_PERCENTAGE', 20)); // Créer une image composite médiane var s2 = s2Collection.median(); // Sélectionner les bandes pertinentes et ajouter des indices spectraux var bands = ['B2', 'B3', 'B4', 'B5', 'B6', 'B7', 'B8', 'B8A', 'B11', 'B12']; // Calculer les indices spectraux var ndvi = s2.normalizedDifference(['B8', 'B4']).rename('NDVI'); var ndwi = s2.normalizedDifference(['B3', 'B8']).rename('NDWI'); var ndbi = s2.normalizedDifference(['B11', 'B8']).rename('NDBI'); // Ajouter les indices à l'image var imageWithIndices = s2.select(bands).addBands(ndvi).addBands(ndwi).addBands(ndbi); // -------------------------------- // 2. VISUALISATION DES COMPOSITIONS // -------------------------------- // Composition en vraies couleurs Map.addLayer(s2, {bands: ['B4', 'B3', 'B2'], min: 0, max: 3000}, 'RGB naturel'); // Composition en fausse couleur (proche infrarouge) Map.addLayer(s2, {bands: ['B8', 'B4', 'B3'], min: 0, max: 3000}, 'Fausse couleur NIR', false); // Composition SWIR Map.addLayer(s2, {bands: ['B12', 'B8', 'B4'], min: 0, max: 3000}, 'SWIR', false); // Visualisation des indices Map.addLayer(ndvi, {min: -0.2, max: 0.8, palette: ['red', 'yellow', 'green']}, 'NDVI', false); Map.addLayer(ndwi, {min: -0.8, max: 0.8, palette: ['white', 'blue']}, 'NDWI', false); Map.addLayer(ndbi, {min: -0.6, max: 0.6, palette: ['green', 'white', 'red']}, 'NDBI', false); // Centrer la carte sur la zone d'étude Map.centerObject(geometry, 10); // -------------------------------- // 3. COLLECTE DES DONNÉES D'ENTRAÎNEMENT // -------------------------------- // OPTION 1: Collecte manuelle des points d'entraînement (méthode interactive) // Utilisez l'outil de dessin pour créer des points et importez-les comme des variables // Après avoir créé des points, importez-les comme 'urban_points', 'vegetation_points', etc. /* // Attribuer des classes aux collections de points var urban = urban_points.map(function(feature) { return feature.set('class', 0); }); var vegetation = vegetation_points.map(function(feature) { return feature.set('class', 1); }); var water = water_points.map(function(feature) { return feature.set('class', 2); }); var baresoil = baresoil_points.map(function(feature) { return feature.set('class', 3); }); // Fusionner toutes les collections var trainingPoints = urban.merge(vegetation).merge(water).merge(baresoil); */ // OPTION 2: Création programmatique de points d'entraînement (à des fins d'exemple) // Cette approche est utile pour illustrer le code complet quand vous n'avez pas encore créé de points // Définir des exemples de régions pour chaque classe (à remplacer par vos propres régions) var urbanArea = ee.Geometry.Rectangle([/* coordonnées */]); var vegetationArea = ee.Geometry.Rectangle([/* coordonnées */]); var waterArea = ee.Geometry.Rectangle([/* coordonnées */]); var baresoilArea = ee.Geometry.Rectangle([/* coordonnées */]); // Créer des points aléatoires dans chaque région var urban = ee.FeatureCollection.randomPoints(urbanArea, 50) .map(function(feature) { return feature.set('class', 0); }); var vegetation = ee.FeatureCollection.randomPoints(vegetationArea, 50) .map(function(feature) { return feature.set('class', 1); }); var water = ee.FeatureCollection.randomPoints(waterArea, 50) .map(function(feature) { return feature.set('class', 2); }); var baresoil = ee.FeatureCollection.randomPoints(baresoilArea, 50) .map(function(feature) { return feature.set('class', 3); }); // Fusionner toutes les collections var trainingPoints = urban.merge(vegetation).merge(water).merge(baresoil); // -------------------------------- // 4. DIVISION EN ENSEMBLES D'ENTRAÎNEMENT ET DE VALIDATION // -------------------------------- // Ajouter une colonne avec des nombres aléatoires var withRandom = trainingPoints.randomColumn('random'); // Diviser en ensembles d'entraînement (70%) et validation (30%) var split = 0.7; var training = withRandom.filter(ee.Filter.lt('random', split)); var validation = withRandom.filter(ee.Filter.gte('random', split)); // Visualiser les points d'entraînement et de validation Map.addLayer(training, {color: 'blue'}, 'Points d\'entraînement', false); Map.addLayer(validation, {color: 'red'}, 'Points de validation', false); // Afficher le nombre de points dans chaque ensemble print('Nombre de points d\'entraînement:', training.size()); print('Nombre de points de validation:', validation.size()); // -------------------------------- // 5. ÉCHANTILLONNAGE DES VALEURS SPECTRALES // -------------------------------- // Liste de toutes les bandes à utiliser pour la classification var bandsToUse = bands.concat(['NDVI', 'NDWI', 'NDBI']); // Échantillonner l'image aux emplacements des points d'entraînement var trainingData = imageWithIndices.select(bandsToUse).sampleRegions({ collection: training, properties: ['class'], scale: 20 // Résolution de Sentinel-2 }); // Échantillonner l'image aux emplacements des points de validation var validationData = imageWithIndices.select(bandsToUse).sampleRegions({ collection: validation, properties: ['class'], scale: 20 }); // -------------------------------- // 6. ENTRAÎNEMENT DU CLASSIFICATEUR // -------------------------------- // Créer un classificateur Random Forest et l'entraîner var classifier = ee.Classifier.smileRandomForest({ numberOfTrees: 100, minLeafPopulation: 1, seed: 42 }).train({ features: trainingData, classProperty: 'class', inputProperties: bandsToUse }); // Obtenir des informations sur l'importance des variables (optionnel) var importances = classifier.explain(); print('Importance des variables:', importances); // -------------------------------- // 7. CLASSIFICATION DE L'IMAGE // -------------------------------- // Appliquer le classificateur à l'image var classified = imageWithIndices.select(bandsToUse).classify(classifier); // Définir une palette de couleurs pour les classes var palette = [ '#FF0000', // Rouge pour Urbain (classe 0) '#00FF00', // Vert pour Végétation (classe 1) '#0000FF', // Bleu pour Eau (classe 2) '#FFFF00' // Jaune pour Sol nu (classe 3) ]; // Visualiser la classification Map.addLayer(classified, {min: 0, max: 3, palette: palette}, 'Classification LULC'); // -------------------------------- // 8. VALIDATION ET ÉVALUATION DE LA PRÉCISION // -------------------------------- // Classer les points de validation var validationResult = validationData.classify(classifier); // Créer une matrice de confusion var confusionMatrix = validationResult.errorMatrix('class', 'classification'); // Afficher les résultats de précision print('Matrice de confusion:', confusionMatrix); print('Précision globale:', confusionMatrix.accuracy()); print('Précision du producteur:', confusionMatrix.producersAccuracy()); print('Précision de l\'utilisateur:', confusionMatrix.consumersAccuracy()); print('Coefficient Kappa:', confusionMatrix.kappa()); // -------------------------------- // 9. FILTRAGE POST-CLASSIFICATION (OPTIONNEL) // -------------------------------- // Appliquer un filtre majoritaire pour réduire le bruit de classification var filtered = classified.focal_mode({ radius: 1.5, // Rayon en pixels kernelType: 'circle', units: 'pixels' }); // Visualiser la classification filtrée Map.addLayer(filtered, {min: 0, max: 3, palette: palette}, 'Classification filtrée', false); // -------------------------------- // 10. CALCUL DES STATISTIQUES DE SURFACE // -------------------------------- // Calculer la superficie pour chaque classe var areaImage = ee.Image.pixelArea().addBands(classified); var areas = areaImage.reduceRegion({ reducer: ee.Reducer.sum().group({ groupField: 1, groupName: 'class', }), geometry: geometry, scale: 20, maxPixels: 1e9 }); // Afficher les résultats de superficie print('Superficie par classe (m²):', areas); // Convertir les résultats en hectares et créer un tableau plus lisible var classAreas = ee.List(areas.get('groups')); var classAreasList = classAreas.map(function(item) { var areaDict = ee.Dictionary(item); var classNumber = areaDict.get('class'); var area = ee.Number(areaDict.get('sum')).divide(10000); // Conversion en hectares // Déterminer le nom de la classe var className; if (classNumber.equals(0)) { className = 'Urbain'; } else if (classNumber.equals(1)) { className = 'Végétation'; } else if (classNumber.equals(2)) { className = 'Eau'; } else { className = 'Sol nu'; } return ee.Dictionary({ 'Classe': className, 'Superficie (ha)': area.format('%.2f') }); }); print('Superficie par classe (ha):', classAreasList); // -------------------------------- // 11. EXPORTATION DES RÉSULTATS // -------------------------------- // Exporter la classification vers Google Drive Export.image.toDrive({ image: classified, description: 'LULC_Classification', folder: 'GEE_Exports', region: geometry, scale: 20, maxPixels: 1e9 }); // Exporter les points d'entraînement pour une utilisation future Export.table.toDrive({ collection: trainingPoints, description: 'LULC_Training_Points', fileFormat: 'GeoJSON' }); // -------------------------------- // 12. AJOUT D'UNE LÉGENDE (FACULTATIF) // -------------------------------- // Créer un panneau pour la légende var legend = ui.Panel({ style: { position: 'bottom-left', padding: '8px 15px' } }); // Ajouter un titre à la légende var legendTitle = ui.Label({ value: 'Légende LULC', style: { fontWeight: 'bold', fontSize: '16px', margin: '0 0 4px 0', padding: '0' } }); legend.add(legendTitle); // Créer et ajouter les éléments de la légende var makeRow = function(color, name) { var colorBox = ui.Label({ style: { backgroundColor: color, padding: '8px', margin: '0 0 4px 0' } }); var description = ui.Label({ value: name, style: {margin: '0 0 4px 6px'} }); return ui.Panel({ widgets: [colorBox, description], layout: ui.Panel.Layout.Flow('horizontal') }); }; legend.add(makeRow('#FF0000', 'Urbain (0)')); legend.add(makeRow('#00FF00', 'Végétation (1)')); legend.add(makeRow('#0000FF', 'Eau (2)')); legend.add(makeRow('#FFFF00', 'Sol nu (3)')); // Ajouter la légende à la carte Map.add(legend);
1
Préparation des données
- Définition de la zone d'étude
- Chargement des images Sentinel-2
- Filtrage temporel et spatial
- Calcul des indices spectraux (NDVI, NDWI, NDBI)
2
Visualisation
- Compositions RGB naturel
- Fausse couleur NIR
- Composition SWIR
- Visualisation des indices
3
Collecte des données d'entraînement
- Option manuelle (outil de dessin)
- Option programmatique (exemple)
- Attribution des classes
4
Division des données
- Séparation 70% entraînement / 30% validation
- Randomisation des points
- Visualisation des ensembles
5
Entraînement du classificateur
- Configuration du Random Forest
- 100 arbres, seed=42
- Analyse d'importance des variables
6
Classification et validation
- Application du modèle
- Matrice de confusion
- Métriques de précision
- Filtrage post-classification
7
Analyse et exportation
Calcul des superficies
- Conversion en hectares
- Résultats par classe
Exportation
- Classification vers Google Drive
- Points d'entraînement en GeoJSON
- Ajout de légende interactive
Légende des classes LULC
Couleurs des classes
- Urbain (classe 0)
- Végétation (classe 1)
- Eau (classe 2)
- Sol nu (classe 3)
Palettes des indices
- NDVI: [-0.2 à 0.8]
- NDWI: [-0.8 à 0.8]
- NDBI: [-0.6 à 0.6]
Notes importantes
Configuration initiale
- Vous devez définir votre propre geometry pour délimiter la zone d'étude.
- Dans la partie "OPTION 1", utilisez l'outil de dessin du Code Editor pour créer des points d'entraînement.
- Importez les points comme variables: urban_points, vegetation_points, etc.
- Décommentez la section correspondante dans le code.
Points d'entraînement
- Pour l'échantillonnage manuel: dessinez vos points avec l'outil de dessin.
- L'OPTION 2 avec des points générés automatiquement est fournie pour démarrer rapidement.
- Définissez des zones représentatives pour chaque classe dans l'option programmatique.
Paramètres du modèle
- Ajustez les paramètres du classificateur Random Forest selon vos besoins.
- Nombre d'arbres, profondeur, etc. peuvent être optimisés.
- La seed=42 assure la reproductibilité des résultats.
Exportation
- Modifiez le dossier de destination dans Google Drive si nécessaire.
- Adaptez la résolution (scale) selon vos besoins.
- Le format GeoJSON est recommandé pour les points d'entraînement.
Astuce
Ce code est immédiatement opérationnel dans Google Earth Engine et peut être facilement adapté à d'autres régions d'étude ou personnalisé selon vos besoins spécifiques.