Cartographier un “mégafeu” de forêt

Caractériser l’impact d’un feu de forêt avec R.

R
Cartographie
Télédétection
Imagerie multispectrale
Auteur·rice
Affiliation

N. Frerebeau

UMR 6034 Archéosciences Bordeaux

Date de publication

28 juillet 2026

Modifié

12 août 2026

Le 22 juillet 2026, un feu de forêt s’est déclaré sur la commune de Saumos (Gironde). L’incendie a rapidement atteint une haute intensité, ravageant 420 km2, au point d’être qualifié de “mégafeu”1. L’objectif ici est de produire une cartographie de l’incendie et d’en caractériser l’impact sur les sols. Le tout avec R (R Core Team 2026) et des données libres.

Cette caractérisation repose sur le calcul d’un indice spectral, à partir des valeurs de réflectance obtenues par imagerie spatiale. Les données utilisées sont issues de Sentinel-2, une mission européenne d’imagerie multispectrale à large champ (290 km) et haute résolution avec une fréquence de revisite mondiale élevée (10 jours à l’équateur avec un satellite, soit 5 jours avec deux satellites). L’instrument multispectral échantillonne 13 bandes spectrales : 4 bandes à 10 m (visible et proche infrarouge), 6 bandes à 20 m (bord rouge et infrarouge à ondes courtes) et 3 bandes à 60 m de résolution spatiale (bandes atmosphériques). Ces données permettent d’évaluer l’état et l’évolution du sol et de sa couverture.

Cinq packages R sont nécessaires : sf (Pebesma et Bivand 2023; Pebesma 2018) pour le traitement des données vectorielles, terra (Hijmans et al. 2026) pour le traitement des données raster, ainsi que ggplot2 (Wickham 2016), ggspatial (Dunnington 2025) et khroma (Frerebeau 2025) pour la visualisation.

## Installer les packages nécessaires
pkg <- c("ggplot2", "ggspatial", "terra")
pkg_missing <- !(pkg %in% installed.packages())
install.packages(pkg[pkg_missing])

Préparation des données

La zone d’intérêt est un rectangle de 55 km d’Est en Ouest (du centre de Bordeaux à la pointe du Cap Ferret) et de 45 km du Nord au Sud (de Lacanau à Gujan-Mestras) :

## Définir l'emprise du découpage (xmin, xmax, ymin, ymax)
## Système de coordonnées projetées WGS 84 / UTM zone 30N (EPSG:32630)
box <- c(xmin = 637300, xmax = 692300, ymin = 4940500, ymax = 4985500)
aoi <- terra::ext(box)

Les données de la missions Sentinel-2 sont distribuées sous licence libre et peuvent être téléchargées depuis le portail Copernicus Browser. Deux ensembles d’images sont nécessaires, correspondant à la situation avant et après l’incendie. Les données initiales sont celles du 21 juillet 2026 (veille de l’incendie), tandis que les données du 12 août correspondent à la situation après l’incendie (l’incendie a été déclaré fixé et maîtrisé le 1er août 2026).

On importe uniquement les bandes d’intérêt ici (tableau 1) : rouge, vert, bleu, proche infrarouge (near infrared, NIR) et infrarouge à ondes courtes (short-wavelength infrared, SWIR).

Les données utilisées ici sont de niveau 2A : il s’agit de données ortho-rectifiées en réflectance de surface, après correction des effets atmosphériques (Bottom-Of-Atmosphere, BOA).
Table 1: Bandes spectrales des clichés Sentinel-2.
Bande Longueur d’onde centrale (nm) Largeur de la bande (nm) Résolution spatiale (m)
B2 (bleu) 494 65 10
B3 (vert) 560 35 10
B4 (rouge) 665 30 10
B8 (NIR 1) 834 115 10
B8A (NIR 2) 865 20 20
B11 (SWIR 1) 1612 90 20
B12 (SWIR 2) 2194 180 20
## Lire les données pour chaque bande d'intérêt
pre_02 <- terra::rast("T30TXQ_20260721T105621_B02_20m.jp2") # Bande 2 (bleu)
pre_03 <- terra::rast("T30TXQ_20260721T105621_B03_20m.jp2") # Bande 3 (vert)
pre_04 <- terra::rast("T30TXQ_20260721T105621_B04_20m.jp2") # Bande 4 (rouge)
pre_08 <- terra::rast("T30TXQ_20260721T105621_B08_10m.jp2") # Bande 8 (NIR 1)
pre_8A <- terra::rast("T30TXQ_20260721T105621_B8A_20m.jp2") # Bande 8A (NIR 2)
pre_11 <- terra::rast("T30TXQ_20260721T105621_B11_20m.jp2") # Bande 11 (SWIR 1)
pre_12 <- terra::rast("T30TXQ_20260721T105621_B12_20m.jp2") # Bande 12 (SWIR 2)

## Sous-échantillonner la bande 8
pre_08 <- terra::aggregate(pre_08, fact = 2)

## Combinaison des différentes bandes
## Rouge, vert, bleu, NIR 1, NIR 2, SWIR 1, SWIR 2
pre_stack <- c(pre_04, pre_03, pre_02, pre_08, pre_8A, pre_11, pre_12)
names(pre_stack) <- c("R", "G", "B", "NIR1", "NIR2", "SWIR1", "SWIR2")

## Découpage selon la zone d'intérêt
pre_crop <- terra::crop(pre_stack, aoi)

De la même manière, on importe les données pour la journée du 12 août :

## Lire les données pour chaque bande d'intérêt
post_02 <- terra::rast("T30TXQ_20260812T105651_B02_20m.jp2") # Bande 2 (bleu)
post_03 <- terra::rast("T30TXQ_20260812T105651_B03_20m.jp2") # Bande 3 (vert)
post_04 <- terra::rast("T30TXQ_20260812T105651_B04_20m.jp2") # Bande 4 (rouge)
post_08 <- terra::rast("T30TXQ_20260812T105651_B08_10m.jp2") # Bande 8 (NIR 1)
post_8A <- terra::rast("T30TXQ_20260812T105651_B8A_20m.jp2") # Bande 8A (NIR 2)
post_11 <- terra::rast("T30TXQ_20260812T105651_B11_20m.jp2") # Bande 11 (SWIR 1)
post_12 <- terra::rast("T30TXQ_20260812T105651_B12_20m.jp2") # Bande 12 (SWIR 2)

## Sous-échantillonner la bande 8
post_08 <- terra::aggregate(post_08, fact = 2)

## Combinaison des différentes bandes
## Rouge, vert, bleu, NIR 1, NIR 2, SWIR 1, SWIR 2
post_stack <- c(post_04, post_03, post_02, post_08, post_8A, post_11, post_12)
names(post_stack) <- c("R", "G", "B", "NIR1", "NIR2", "SWIR1", "SWIR2")

## Découpage selon la zone d'intérêt
post_crop <- terra::crop(post_stack, aoi)

Les bandes de réflectance de Sentinel-2 sont stockées sous forme de nombres entiers. Pour les convertir en valeur de réflectance, il est nécessaire des les normaliser par une valeur de quantification et d’appliquer un décalage additionnel par bande (ces deux valeurs sont précisées dans les métadonnées BOA_QUANTIFICATION_VALUE et BOA_ADD_OFFSET ; ici, 10000 et 1000 respectivement) :

La réflectance est la proportion de lumière qu’une surface renvoie par rapport à ce qu’elle reçoit. Sa valeur est comprise entre 0 et 1, cependant les données Sentinel-2 peuvent contenir des valeurs négatives ou supérieures à 1. Les premières sont dues aux étapes de prétraitement (corrections atmosphériques notamment), tandis que les secondes s’expliquent par la physique (réflexions spéculaires par exemple).
## Conversion en réflectance
pre_refl <- (pre_crop - 1000) / 10000
post_refl <- (post_crop - 1000) / 10000

## Remplacer les valeurs de réflectance négatives par zéro
pre_refl[pre_refl < 0] <- 0
post_refl[post_refl < 0] <- 0

On peut désormais visualiser les données en utilisant les bandes du visible (rouge, vert, bleu), grâce à la fonction plotRGB(). L’argument stretch permet de définir la méthode à utiliser pour étirer les valeurs de réflectance entre 0 et 255.

## Avant incendie
terra::plotRGB(
  x = pre_refl,
  stretch = "lin", 
  mar = c(1, 1, 0, 0) + 0.1,
  axes = TRUE
)

## Après incendie
terra::plotRGB(
  x = post_refl,
  stretch = "lin", 
  mar = c(1, 1, 0, 0) + 0.1,
  axes = TRUE
)
(a) Avant incendie.
(b) Après incendie.
Figure 1: Images RVB (rouge, vert, bleu) de la zone d’intérêt.

Enfin, on prépare un masque afin d’éliminer les pixels susceptibles d’affecter l’analyse. Pour cela, on peut utiliser la couche de classification (Scene Classification Layer, SCL) des données Sentinel-2. Cette couche fournit des informations sur la couverture du sol, résumées en 12 classes (tableau 2, figure 2).

Table 2: Classes de la couche SCL.
Classe Description
0 Absence de donnée
1 Pixel saturé ou défectueux
2 Ombres projetées topographiques
3 Ombres des nuages
4 Végétation
5 Sans végétation
6 Eau
7 Probabilité faible de nuages
8 Probabilité moyenne de nuages
9 Probabilité élevée de nuages
10 Cirrus fins
11 Neige ou glace
## Lire les données SCL
scl_pre <- terra::rast("T30TXQ_20260721T105621_SCL_20m.jp2")
scl_post <- terra::rast("T30TXQ_20260812T105651_SCL_20m.jp2")

## Découpage selon la zone d'intérêt
scl_pre_crop <- terra::crop(scl_pre, aoi)
scl_post_crop <- terra::crop(scl_post, aoi)

## Visualisation des classes
scl_colors <- data.frame(
  value = c(0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11),
  color = c("#000000", "#ff0000", "#2f2f2f", "#643200", "#00a000", "#ffe65a", 
            "#0000ff", "#808080", "#c0c0c0", "#ffffff", "#64c8ff", "#ff96ff")
)
terra::plot(scl_pre_crop, type = "classes", col = scl_colors)
terra::plot(scl_post_crop, type = "classes", col = scl_colors)
(a) Avant incendie.
(b) Après incendie.
Figure 2: Classification de la couverture du sol issue de Sentinel-2.

Le couvert nuageux constitue la principale limitation des données optiques satellitaires. Il est donc nécessaire de supprimer les nuages en masquant tous les pixels qui présentent des valeurs SCL égales à 3, 8, 9 et 10 (voire 7). Certaines surfaces claires peuvent cependant être classées par erreur comme nuages (voir, par exemple, les prés-salés près d’Arès et de Lège-Cap-Ferret, au Nord du Bassin d’Arcachon ; figure 2 (a)).

Par commodité, on se limite ici à masquer l’océan et les lacs (classe 6) afin d’éliminer les étendues d’eau des analyses à venir :

## Création du masque en remplaçant la classe 6 (eau) par des valeurs manquantes
## (les classes 0 et 1 sont absentes dans les données)
water_pre <- terra::classify(scl_pre_crop, cbind(6, NA))
water_post <- terra::classify(scl_post_crop, cbind(6, NA))

## Appliquer le masque aux données
pre_mask <- terra::mask(pre_refl, water_pre)
post_mask <- terra::mask(post_refl, water_post)

Visualisation

Plutôt que se limiter aux seules bandes du visibles (rouge, vert et bleu), plusieurs combinaisons de bandes spectrales peuvent être utilisées. Ces images composites permettent de mettre en évidence différentes caractéristiques de la zone étudiée.

Composite infrarouge

L’image en fausses couleurs infrarouge est obtenue en combinant les bandes B8 (NIR 1), B4 (rouge) et B3 (vert). Cette combinaison produit une image permettant de mettre en valeur la végétation saine et dense en rouge vif, car elle absorbe le vert et le bleu (figure 3). Les teintes rouge foncé indiquent une végétation à feuilles ou plus saine, tandis que les rouges plus clairs correspondent à des prairies ou à des zones à végétation clairsemée. Les zones urbaines et dénudées apparaissent en cyan, tandis que le sol est représenté par des nuances de marron.

## Avant l'incendie
terra::plotRGB(pre_mask, r = 4, g = 1, b = 2, stretch = "lin")

## Après l'incendie
terra::plotRGB(post_mask, r = 4, g = 1, b = 2, stretch = "lin")
(a) Avant incendie.
(b) Après incendie.
Figure 3: Image en fausse couleur infrarouge (NIR 1, rouge, vert).

Composite urbaine

L’image en fausses couleurs dite urbaine est obtenue en combinant les bandes B12 (SWIR 2), B11 (SWIR 1) et B4 (rouge). Les zones urbaines sont mises en évidence par des tons violets, gris et blancs (figure 4).

## Avant l'incendie
terra::plotRGB(pre_mask, r = 7, g = 6, b = 1, stretch = "lin")

## Après l'incendie
terra::plotRGB(post_mask, r = 7, g = 6, b = 1, stretch = "lin")
(a) Avant incendie.
(b) Après incendie.
Figure 4: Image en fausse couleur urbaine (SWIR 2, SWIR 1, rouge).

Composite agricole

L’image en fausses couleurs dite agricole est obtenue en combinant les bandes B11 (SWIR 1), B8 (NIR 1) et B2 (bleu). Les forêts de conifères apparaissent dans un vert foncé, tandis que les forêts de feuillus apparaissent dans un vert vif (figure 5). En effet, les aiguilles des conifères absorbent davantage dans l’infrarouge à ondes courtes et présentent une réflexion plus faible dans le proche infrarouge que la végétation à feuilles. Les zones de végétation clairsemée ou dénudées apparaissent en marron et en mauve.

## Avant l'incendie
terra::plotRGB(pre_mask, r = 6, g = 4, b = 3, stretch = "lin")

## Après l'incendie
terra::plotRGB(post_mask, r = 6, g = 4, b = 3, stretch = "lin")
(a) Avant incendie.
(b) Après incendie.
Figure 5: Image en fausse couleur agricole (SWIR 1, NIR 1, bleu).

Composite SWIR

L’image en fausses couleurs SWIR est obtenue en combinant les bandes B12 (SWIR 2), B8A (NIR 2) et B4 (vert). La végétation saine apparaît dans des nuances de vert (figure 6 (a)), tandis que l’absence de réflectance dans l’infrarouge (NIR et SWIR) des sols couverts de cendres permet de très bien mettre en évidence la cicatrice laissée par l’incendie (figure 6 (b)).

## Avant l'incendie
terra::plotRGB(pre_mask, r = 7, g = 5, b = 2, stretch = "lin")

## Après l'incendie
terra::plotRGB(post_mask, r = 7, g = 5, b = 2, stretch = "lin")
(a) Avant incendie.
(b) Après incendie.
Figure 6: Image en fausse couleur SWIR (SWIR 2, NIR 2, vert).

Indices spectraux

Au-delà de la seule visualisation, il est possible de calculer des indices de télédétection (ou indices spectraux) afin d’obtenir des informations sur les propriétés physiques et chimiques du sol et de sa couverture. Ces indices correspondent aux rapports entre les valeurs de différentes bandes et sont généralement compris entre -1 et +1.

Végétation et humidité

L’indice de végétation par différence normalisé (Normalized Difference Vegetation Index, NDVI, Rouse et al. 1974) permet de comparer la quantité de lumière rouge absorbée par une plante avec la quantité de lumière dans le proche infrarouge qu’elle réfléchit (équation 1 et équation 2) :

\[ \text{NDVI} = \frac{\text{NIR} - \text{rouge}}{\text{NIR} + \text{rouge}} \tag{1}\]

Avec les données Sentinel-2 :

\[ \text{NDVI} = \frac{\text{B8} - \text{B4}}{\text{B8} + \text{B4}} \tag{2}\]

La chlorophylle absorbe en effet toutes les couleurs sauf le vert, et réfléchit également le proche infrarouge. Sous l’effet d’un stress, la quantité de chlorophylle diminue dans les plantes et une moindre quantité de lumière infrarouge est réflechie. Le NDVI permet ainsi d’évaluer l’état de la végétation. Pour chaque pixel de l’image, sa valeur est comprise entre -1 et +1 : plus l’indice est élevé, plus la quantité de chlorophyle est élevée et donc, plus la végétation est dense/saine.

## Calcul du NDVI
ndvi_pre <- (pre_mask$NIR1 - pre_mask$R) / (pre_mask$NIR1 + pre_mask$R)
ndvi_post <- (post_mask$NIR1 - post_mask$R) / (post_mask$NIR1 + post_mask$R)

L’indice d’humidité par différence normalisé (Normalized Difference Moisture Index, NDMI, Gao 1996) permet quant à lui de comparer la quantité de lumière absorbée dans l’infrarouge à ondes courtes avec la quantité réfléchit dans le proche infrarouge (équation 3 et équation 4) :

\[ \text{NDMI} = \frac{\text{NIR} - \text{SWIR}}{\text{NIR} + \text{SWIR}} \tag{3}\]

Avec les données Sentinel-2 :

\[ \text{NDMI} = \frac{\text{B8} - \text{B11}}{\text{B8} + \text{B11}} \tag{4}\]

La réfléctance dans l’infrarouge à ondes courtes est sensible à la teneur en eau de la végétation. Ainsi, plus les valeurs du NDMI sont basses, plus la teneur en eau de la végétation est faible. Des valeurs négatives tendent donc à indiquer un stress hydrique.

## Calcul du NDMI
ndmi_pre <- (pre_mask$NIR1 - pre_mask$SWIR1) / (pre_mask$NIR1 + pre_mask$SWIR1)
ndmi_post <- (post_mask$NIR1 - post_mask$SWIR1) / (post_mask$NIR1 + post_mask$SWIR1)

La visulalisation des valeurs obtenues avant (figure 7 (a), figure 7 (c)) et après (figure 7 (b), figure 7 (d)) l’incendie permet de constater l’impact du feu sur la végétation et son étendue.

ggplot2::ggplot() +
  ggspatial::layer_spatial(ndvi_pre) +
  khroma::scale_fill_PRGn(name = "NDVI") +
  ggplot2::coord_sf(expand = FALSE, datum = "EPSG:32630") +
  ggplot2::theme_bw() +
  ggplot2::theme(
    axis.text.y = ggplot2::element_text(angle = 90, vjust = 0, hjust = 0.5)
  )

ggplot2::ggplot() +
  ggspatial::layer_spatial(ndvi_post) +
  khroma::scale_fill_PRGn(name = "NDVI") +
  ggplot2::coord_sf(expand = FALSE, datum = "EPSG:32630") +
  ggplot2::theme_bw() +
  ggplot2::theme(
    axis.text.y = ggplot2::element_text(angle = 90, vjust = 0, hjust = 0.5)
  )

ggplot2::ggplot() +
  ggspatial::layer_spatial(ndmi_pre) +
  khroma::scale_fill_BuRd(name = "NDMI", reverse = TRUE) +
  ggplot2::coord_sf(expand = FALSE, datum = "EPSG:32630") +
  ggplot2::theme_bw() +
  ggplot2::theme(
    axis.text.y = ggplot2::element_text(angle = 90, vjust = 0, hjust = 0.5)
  )

ggplot2::ggplot() +
  ggspatial::layer_spatial(ndmi_post) +
  khroma::scale_fill_BuRd(name = "NDMI", reverse = TRUE) +
  ggplot2::coord_sf(expand = FALSE, datum = "EPSG:32630") +
  ggplot2::theme_bw() +
  ggplot2::theme(
    axis.text.y = ggplot2::element_text(angle = 90, vjust = 0, hjust = 0.5)
  )
(a) NDVI avant incendie.
(b) NDVI après incendie.
(c) NDMI avant incendie.
(d) NDMI après incendie.
Figure 7: Indices de végétation (NDVI) et d’humidité (NDMI).

Indice de brûlure normalisé

Calcul

L’indice de brûlure normalisé (Normalized Burn Ratio, NBR, Key et Benson 2006) est également calculé à partir des valeurs de reflectances dans le proche infrarouge et dans l’infrarouge à ondes courtes, mais n’utilise pas les mêmes bandes que le NDMI (équation 5 et équation 6) :

\[ \text{NBR} = \frac{\text{NIR} - \text{SWIR}}{\text{NIR} + \text{SWIR}} \tag{5}\]

Avec les données Sentinel-2 :

\[ \text{NBR} = \frac{\text{B8} - \text{B12}}{\text{B8} + \text{B12}} \tag{6}\]

La bande 12 (centrée sur 2194 nm) est en effet plus sensible aux conséquences de l’incendie que la bande 11 (centrée sur 1612 nm). Les surfaces brûlées (asséchées et couvertes de cendres) ont une faible réflectance dans le proche infrarouge et une réflectance élevée dans l’infrarouge à ondes courtes, à l’inverse de la végétation.

## Calcul du NBR
nbr_pre <- (pre_mask$NIR1 - pre_mask$SWIR2) / (pre_mask$NIR1 + pre_mask$SWIR2)
nbr_post <- (post_mask$NIR1 - post_mask$SWIR2) / (post_mask$NIR1 + post_mask$SWIR2)

Avant l’incendie (figure 8 (a)), la présence de la végétation entraîne des valeurs de réflectance élevées dans le proche infrarouge, tandis qu’on observe une reflectance faible dans l’infrarouge à ondes courtes du fait de l’absorption par l’eau. Après l’incendie (figure 8 (b)), la réflectance diminue dans le proche infrarouge et augmente dans l’infrarouge à ondes courtes.

Des valeurs élevée du NBR représentent ainsi des surfaces de végétation saines, tandis que les valeurs les plus faibles indiquent des surfaces dégradées par l’incendie.

## Avant incendie
ggplot2::ggplot() +
  ggspatial::layer_spatial(nbr_pre) +
  khroma::scale_fill_nightfall(name = "NBR", reverse = TRUE) +
  ggplot2::coord_sf(expand = FALSE, datum = "EPSG:32630") +
  ggplot2::theme_bw() +
  ggplot2::theme(
    axis.text.y = ggplot2::element_text(angle = 90, vjust = 0, hjust = 0.5)
  )

## Après incendie
ggplot2::ggplot() +
  ggspatial::layer_spatial(nbr_post) +
  khroma::scale_fill_nightfall(name = "NBR", reverse = TRUE) +
  ggplot2::coord_sf(expand = FALSE, datum = "EPSG:32630") +
  ggplot2::theme_bw() +
  ggplot2::theme(
    axis.text.y = ggplot2::element_text(angle = 90, vjust = 0, hjust = 0.5)
  )
(a) Avant incendie.
(b) Après incendie.
Figure 8: Indice de brûlure normalisé (NBR).

Comparaison

À fin de comparaison, il est possible de calculer la différence entre les valeurs de NBR avant et après l’incendie (équation 7) :

\[ \text{dNBR} = \text{NBR}_{avant} - \text{NBR}_{après} \tag{7}\]

Cette différence (differenced normalized burn ratio, dNBR) permet d’évaluer les conséquences de l’incendie. Une valeur de dNBR élevée indique des dommages plus importants, tandis que les zones présentant des valeurs de dNBR nulles ou négatives correspondent aux surfaces intactes (voire à une repousse après l’incendie ; figure 9).

## Calcul du dNBR
dnbr <- nbr_pre - nbr_post

## Visualisation
ggplot2::ggplot() +
  ggspatial::layer_spatial(dnbr) +
  khroma::scale_fill_sunset(name = "dNBR") +
  ggplot2::coord_sf(expand = FALSE, datum = "EPSG:32630") +
  ggplot2::theme_bw() +
  ggplot2::theme(
    axis.text.y = ggplot2::element_text(angle = 90, vjust = 0, hjust = 0.5)
  )
Figure 9: NBR différencié (dNBR).

Classification

La gravité d’un incendie est une mesure de l’ampleur des effets immédiats de l’incendie sur la végétation et les sols. Pour qualifier cette gravité, les valeurs de dNBR sont classées selon les seuils utilisés par le European Forest Fire Information System (EFFIS) et définis par Key et Benson (2006).

La fonction classify() pert d’attribuer les classes de gravité en fonction des valeurs de dNBR. Le dNBR est une variable continue, il donc est nécessaire de la discrétiser. Cette étape est réalisée grace à une table de correspondance, construite sous la forme d’une matrice à trois colonnes : la première colonne contient la borne inférieure de chaque classe, la deuxième colonne contient la borne supérieure et la troisième colonne contient la nouvelle valeur de classe à attribuer.

## Définition des classes pour la classification
## Matrice à trois colonnes :
##  - Borne inférieure (dNBR)
##  - Borne supérieure (dNBR)
##  - Classe
dnbr_classes <- matrix(
  data = c(
    -Inf, 0.10, 1, # Non brûlé ou repousse
    0.10, 0.27, 2, # Faible gravité
    0.27, 0.44, 3, # Gravité modérée à faible
    0.44, 0.66, 4, # Gravité modérée à élevée
    0.66,  Inf, 5  # Gravité élevée
  ),
  ncol = 3,
  byrow = TRUE
)

## Classification
severity <- terra::classify(dnbr, dnbr_classes, others = NA)

Le résultat de la classification peut ensuite être visualisé (figure 10).

## Définition des couleurs
dnbr_colors <- data.frame(
  value = c(1, 2, 3, 4, 5),
  color = c("darkgreen", "yellow", "orange", "red", "purple")
)
dnbr_levels <- c(
  "Non brûlé ou repousse", 
  "Faible gravité", 
  "Gravité modérée à faible", 
  "Gravité modérée à élevée",
  "Gravité élevée"
)

## Visualisation
terra::plot(
  severity,
  type = "classes",
  mar = c(1, 1, 1, 1) + 01,
  col = dnbr_colors,
  legend = "topright",
  plg = list(legend = dnbr_levels, bty = "o", bg = "white")
)
Figure 10: Classification du dNBR.

Bien évidemment, l’estimation du dNBR et les classes de gravité qui en découlent repose sur l’hypothèse que les changements observés sont le résultat du seul incendie, et non d’autres facteurs liés à l’évolution de la couverture et de l’occupation des sols. Il est donc préférable d’exclure les pixels hors du périmètre de l’incendie, en utilisant la base de données des zones brûlées en Europe fournie par l’EFFIS et téléchargeable au format Shapefile.

## Lire les données EFFIS
effis_wgs84 <- sf::st_read("modis.ba.poly.shp", quiet = TRUE)

## Reprojeter les données dans le même système de coordonnées que Sentinel-2
effis_utm30 <- sf::st_transform(effis_wgs84, crs = 32630)

## Sélectionner uniquement l'incendie de Gironde
effis_saumos <- subset(effis_utm30, id == 562583)

## Créer un masque
effis_mask <- terra::rasterize(terra::vect(effis_saumos), severity)

## Masquer les pixel hors du périmètre de l'incendie
severity_mask <- terra::mask(severity, effis_mask)

## Visualisation
## Image RVB
terra::plotRGB(
  x = pre_refl,
  stretch = "lin",
  mar = c(1, 1, 0, 0) + 0.1, 
  axes = TRUE
)

## Superposer la classification du dNBR
terra::plot(
  severity_mask,
  type = "classes",
  col = dnbr_colors,
  legend = "topright",
  plg = list(legend = dnbr_levels, bty = "o", bg = "white"),
  add = TRUE
)
Figure 11: Classification des valeurs de dNBR superposée à l’image RVB de la zone d’étude. Crédit : contient des données Copernicus Sentinel modifiées 2026.

Enfin, la fonction expanse() permet de calculer la surface correspondant à chaque classe de gravité (tableau 3) :

area <- terra::expanse(severity_mask, unit = "km", byValue = TRUE)
Table 3: Surface (km2) par classe de gravité de l’icendie.
Classe Surface
Non brûlé ou repousse 8
Faible gravité 27
Gravité modérée à faible 53
Gravité modérée à élevée 114
Gravité élevée 171
Note

Ce résultat a uniquement une valeur illustrative. Il est impératif de se fier aux seules données fournies par les autorités compétentes et vérifiées sur le terrain.

Retour au sommet

Session

R version 4.6.0 (2026-04-24)
Platform: x86_64-pc-linux-gnu
Running under: Ubuntu 24.04.4 LTS

Matrix products: default
BLAS:   /usr/lib/x86_64-linux-gnu/openblas-pthread/libblas.so.3 
LAPACK: /usr/lib/x86_64-linux-gnu/openblas-pthread/libopenblasp-r0.3.26.so;  LAPACK version 3.12.0

locale:
 [1] LC_CTYPE=fr_FR.UTF-8       LC_NUMERIC=C              
 [3] LC_TIME=fr_FR.UTF-8        LC_COLLATE=fr_FR.UTF-8    
 [5] LC_MONETARY=fr_FR.UTF-8    LC_MESSAGES=fr_FR.UTF-8   
 [7] LC_PAPER=fr_FR.UTF-8       LC_NAME=C                 
 [9] LC_ADDRESS=C               LC_TELEPHONE=C            
[11] LC_MEASUREMENT=fr_FR.UTF-8 LC_IDENTIFICATION=C       

time zone: Europe/Paris
tzcode source: system (glibc)

attached base packages:
[1] stats     graphics  grDevices utils     datasets  methods   base     

loaded via a namespace (and not attached):
 [1] gtable_0.3.6       jsonlite_2.0.0     dplyr_1.2.1        compiler_4.6.0    
 [5] tidyselect_1.2.1   Rcpp_1.1.1-1.1     tidyr_1.3.2        scales_1.4.0      
 [9] yaml_2.3.12        fastmap_1.2.0      ggplot2_4.0.3      R6_2.6.1          
[13] labeling_0.4.3     generics_0.1.4     classInt_0.4-11    khroma_1.17.0     
[17] sf_1.1-2           knitr_1.51         htmlwidgets_1.6.4  tibble_3.3.1      
[21] units_1.0-1        DBI_1.3.0          pillar_1.11.1      RColorBrewer_1.1-3
[25] rlang_1.2.0        terra_1.9-34       xfun_0.59          S7_0.2.2          
[29] otel_0.2.0         cli_3.6.6          withr_3.0.3        magrittr_2.0.5    
[33] class_7.3-23       digest_0.6.39      grid_4.6.0         rstudioapi_0.19.0 
[37] ggspatial_1.1.10   lifecycle_1.0.5    vctrs_0.7.3        KernSmooth_2.23-26
[41] proxy_0.4-29       evaluate_1.0.5     glue_1.8.1         farver_2.1.2      
[45] codetools_0.2-20   e1071_1.7-17       purrr_1.2.2        rmarkdown_2.31    
[49] tools_4.6.0        pkgconfig_2.0.3    htmltools_0.5.9   

Les références

Dunnington, Dewey. 2025. ggspatial: Spatial Data Framework for ggplot2. https://doi.org/10.32614/CRAN.package.ggspatial.
Frerebeau, Nicolas. 2025. khroma: Colour Schemes for Scientific Data Visualization. Université Bordeaux Montaigne. https://doi.org/10.5281/zenodo.1472077.
Gao, Bo-cai. 1996. « NDWI – A normalized difference water index for remote sensing of vegetation liquid water from space ». Remote Sensing of Environment 58 (3): 257‑66. https://doi.org/https://doi.org/10.1016/S0034-4257(96)00067-3.
Hijmans, Robert J., Andrew Brown, et Márcia Barbosa. 2026. terra: Spatial Data Analysis. https://doi.org/10.32614/CRAN.package.terra.
Key, Carl H., et Nathan C. Benson. 2006. « Landscape Assessment: Ground measure of severity, the Composite Burn Index; and Remote sensing of severity, the Normalized Burn Ratio ». In FIREMON: Fire effects monitoring and inventory system, édité par Duncan C. Lutes, Robert E. Keane, John F. Caratti, et al. Gen. Tech. Rep. RMRS-GTR-164-CD. U.S. Department of Agriculture, Forest Service, Rocky Mountain Research Station.
Pebesma, Edzer. 2018. « Simple Features for R: Standardized Support for Spatial Vector Data ». The R Journal 10 (1): 439‑46. https://doi.org/10.32614/RJ-2018-009.
Pebesma, Edzer, et Roger Bivand. 2023. Spatial Data Science: With applications in R. Chapman and Hall/CRC. https://doi.org/10.1201/9780429459016.
R Core Team. 2026. R: A Language and Environment for Statistical Computing. R Foundation for Statistical Computing. https://doi.org/10.32614/R.manuals.
Rouse, J. W., R. H. Haas, J. A. Schell, D. W. Deering, et J. C. Harlan. 1974. Monitoring the Vernal Advancement and Retrogradation (Greenwave Effect) of Natural Vegetation. Type III Final Report. NASA/GSFC.
Wickham, Hadley. 2016. ggplot2: Elegant Graphics for Data Analysis. Springer-Verlag New York. https://ggplot2.tidyverse.org.

Notes de bas de page

  1. L’appellation de “mégafeu” ne correspond à aucune définition scientifique.↩︎

Réutilisation

Citation

BibTeX
@online{frerebeau2026,
  author = {Frerebeau, N.},
  title = {Cartographier un “mégafeu” de forêt},
  date = {2026-07-28},
  url = {https://carnets.archeosciences-bordeaux.fr/datascience/20260728-saumos-nbr/},
  langid = {fr-FR}
}
Veuillez citer ce travail comme suit :
Frerebeau, N. 2026. “Cartographier un ‘mégafeu’ de forêt.” July 28. https://carnets.archeosciences-bordeaux.fr/datascience/20260728-saumos-nbr/.