library(here)
library(sf)
library(terra)
library(dplyr)
library(tidyr)
library(ggplot2)
library(patchwork)
library(knitr)
library(tmap)
library(purrr)
library(leaflet)
# Flux WMTS
ortho_1950 <- "https://data.geopf.fr/wmts?SERVICE=WMTS&REQUEST=GetTile&VERSION=1.0.0&LAYER=ORTHOIMAGERY.ORTHOPHOTOS.1950-1965&STYLE=normal&FORMAT=image/png&TILEMATRIXSET=PM&TILEMATRIX={z}&TILEROW={y}&TILECOL={x}"
# Chargement zone test (utilisé pour toutes les cartes leaflet)
ext_test <- st_read(here("02_data/clean/PNR_norm_maine/lineaire_haies_HT_1950s_pnr_normand_test.gpkg"), quiet = TRUE)
ref_test <- st_read(here("02_data/clean/PNR_norm_maine/lineaire_haies_digit_1950s_pnr_normand_test.gpkg"), quiet = TRUE)
ref_test <- st_transform(ref_test, st_crs(ext_test))
# Versions WGS84 pour leaflet
ext_test_wgs <- ext_test %>% st_transform(4326)
ref_test_wgs <- ref_test %>% st_transform(4326)Validation de l’extraction du réseau de haies à partir des rasters binaires arborés
Années 45-50s : Comparaison avec la digitalisation manuelle du PNR Normandie Maine
1. Contexte
1.1 Extraction du linéaire de haies anciennes à partir d’orthophotos
L’extraction et la classification automatique des haies bocagères constituent un défi méthodologique majeur. Les outils et méthodes mobilisés ont connu une évolution technologique rapide, portée par une meilleure disponibilité et résolution des données sources : images satellites multitemporelles, images aériennes, données LiDAR et leurs dérivés. Le développement plus récent d’algorithmes d’intelligence artificielle et de deep learning a permis des avancées significatives en termes de performance (Wolstenholme et al., 2025 ; Pirbasti et al., 2024).
Notre approche est combinatoire et s’inspire de la démarche développée par Marquès et al. (2024) dans l’outil HedgeTools. Succinctement, l’outil opère en deux temps :
- Dans un premier temps, les objets arborés sont isolés par seuillage de hauteur via le Modèle Numérique de Hauteur (MNH) et par un seuillage de l’indice NDVI (Normalized Difference Vegetation Index).
- Dans un second temps, les haies sont isolées par un calcul d’indices morphométriques, basés sur les travaux de Touya et al. (2010).
Pour le cas de nos haies anciennes, les données de hauteur et les bandes infrarouges ne sont pas disponibles. Un modèle de deep learning visant à isoler la couche arborée par segmentation sémantique a été entraîné dans le cadre du projet Ecotones. La chaîne de traitement HedgeTools est ensuite appliquée ; plus de détails sur ce traitement sont disponibles ici.
Nous disposons des linéaires de haies bocagères aux dates et emprises géographiques suivantes (la résolution des orthophotos anciennes est commune : 50×50 cm) :
- Années 47-50s : Normandie entière
- Années 70s : Calvados et Manche
- Années 80s : Calvados, Manche et Orne
- Actuelles : Normandie entière. Par souci de comparabilité, nous n’utilisons pas le linéaire issu de la BD TOPO de l’IGN. La même chaîne de traitements a été appliquée sur le produit CoSIA (Couverture du Sol par Intelligence Artificielle, IGN) du dernier millésime disponible. Bien que cette donnée ne repose pas uniquement sur l’information panchromatique, elle est issue d’un processus de classification par apprentissage automatique et produite au format vecteur à partir d’un raster à 20 cm de résolution, ce qui la rend méthodologiquement comparable à nos autres extractions.
1.2 Données de référence
La digitalisation manuelle par photo-interprétation demeure la méthode communément admise dans la littérature pour produire des données de référence nécessaires à la validation de classifications et d’extractions automatiques (Fraser et Congalton, 2019). Ces données comportent toujours des incertitudes (Congalton, 1991) et l’apport de connaissances expertes du terrain en améliore la qualité (Foody et al., 2010). Elles constituent la vérité “terrain” (ground truth).
Nous disposons à ce titre du linéaire bocager digitalisé à partir des orthophotos historiques panchromatiques des années 47-50s, produit par les techniciens du PNR Normandie Maine selon un cahier des charges défini pour la construction d’un référentiel SIG du bocage bas-normand (PNR Normandie Maine, 2012). D’autres données de référence nous sont fournies à d’autres dates, notamment les différents bassins versants digitalisés dans le cadre des travaux de M. Guillemois portant sur les trajectoires paysagères du bocage et de son influence sur les connectivités hydrologiques (Guillemois, 2025).
1.3 Cartographie comparative
On peut cartographier les deux linéaires superposés sur la zone test pour se faire une idée générale des écarts entre extraction automatique et digitalisation manuelle :
leaflet() %>%
addTiles(urlTemplate = ortho_1950, group = "Ortho 1950") %>%
addPolylines(data = ext_test_wgs,
color = "yellow", weight = 3, opacity = 1,
group = "Linéaire extrait") %>%
addPolylines(data = ref_test_wgs,
color = "cyan", weight = 3, opacity = 1,
group = "Linéaire référence") %>%
addLayersControl(overlayGroups = c("Linéaire extrait", "Linéaire référence")) %>%
addLegend(colors = c("yellow", "cyan"),
labels = c("Extraction automatique", "Digitalisation PNR"),
position = "bottomright",
opacity = 1)L’approche visuelle rend compte d’un certain nombre d’incohérences entre les deux linéaires. Il s’agit maintenant de quantifier cette marge d’erreur.
2. Approche de validation
2.1 Métriques buffer-based
L’évaluation des extractions bocagères dans la littérature récente est majoritairement pixel-based : la validation repose sur l’exactitude de la position des pixels extraits par rapport aux pixels de référence (Wolstenholme et al., 2025). Cette approche est inadaptée à notre cas : notre donnée est un vecteur linéaire, et un décalage de quelques mètres gonflerait artificiellement le taux d’erreur en cas de rasterisation.
Nous mobilisons un cadre méthodologique issu de l’évaluation des extractions de réseaux routiers. Les travaux de Wiedemann et al. (1998) proposent des métriques simples qui ont fait date et sont encore largement utilisées (Lian et al., 2020). Cette approche par zones tampons a été considérée par Goodchild et Hunter (1997) comme applicable à tout type de linéaire (routes, traits de côte, et par extension, haies bocagères).
Le principe est le suivant : on applique une zone tampon de largeur \(d\) autour de chaque linéaire (extrait et de référence), au sein desquelles on mesure :
- La longueur extraite présente dans le buffer de la référence : Vrai Positif (TP) — haie correctement détectée
- La longueur extraite en dehors du buffer de référence : Faux Positif (FP) — haie mal détectée, non existante
- La longueur de référence hors du buffer de l’extraction : Faux Négatif (FN) — haie manquée
De ces mesures nous dérivons quatre indices :
\[ \begin{aligned} completeness &= \frac{\text{longueur de la référence dans le buffer de l'extrait}}{\text{longueur totale de la référence}} \\ &\approx \frac{TP}{TP + FN} \\ completeness &\in [0; 1] \end{aligned} \]
\[ \begin{aligned} correctness &= \frac{\text{longueur extraite dans le buffer de la référence}}{\text{longueur totale de l'extraction}} \\ &\approx \frac{TP}{TP + FP} \\ correctness &\in [0; 1] \end{aligned} \]
\[ \begin{aligned} quality &= \frac{TP}{TP + FP + FN} \\ quality &\in [0; 1] \end{aligned} \]
\[ \begin{aligned} F\text{-}score &= \frac{2 \times completeness \times correctness}{completeness + correctness} \\ F\text{-}score &\in [0; 1] \end{aligned} \]
Ces indices nous offrent des réponses aux questions suivantes :
- Complétude : quelle proportion du linéaire de référence a été effectivement identifiée par l’extraction ?
- Correction : quelle proportion du linéaire extrait correspond effectivement à une haie présente dans la référence ?
- Qualité : sur la totalité du linéaire concerné — haies bien détectées, fausses haies et haies manquées — quelle fraction représente les détections correctes ?
- F-score : c’est la moyenne harmonique entre complétude et correction. Elle synthétise les deux en un seul indice, en pénalisant fortement le déséquilibre — une extraction qui détecte tout mais invente beaucoup (complétude haute, correction basse) aura un F-score bas, et inversement.
À ces indices nous ajoutons des métriques de longueur totale et de densité linéaire (ml/ha). La largeur du tampon doit intégrer l’imprécision positionnelle inhérente aux deux sources de données (Goodchild et Hunter, 1997). Nous retenons un tampon de 15 m, cohérent avec la résolution des orthophotos historiques (50 cm), l’incertitude de la digitalisation manuelle, et l’emprise au sol moyenne d’une haie bocagère (10 m selon les déclarations PAC, jusqu’à 20 m selon l’IGN).
2.2 Résultats sur la zone test
On calcule ces métriques sur une zone réduite du PNR pour un premier aperçu :
buffer_dist <- 15
# Filtrage des haies < 15m
ext_15m_test <- ext_test %>% filter(longueur >= 15)
ref_15m_test <- ref_test %>% filter(long >= 15)
# Longueurs
L_ext_test <- sum(ext_15m_test$longueur)
L_ref_test <- sum(ref_15m_test$long)
# Buffers (union pour éviter le double comptage)
buff_ext_test <- st_buffer(ext_15m_test, buffer_dist) %>% st_union()
buff_ref_test <- st_buffer(ref_15m_test, buffer_dist) %>% st_union()
# TP : extraction dans le buffer de la référence
TP <- st_intersection(ext_15m_test, buff_ref_test) %>% st_length() %>% as.numeric() %>% sum()
FP <- L_ext_test - TP
# Référence détectée
ref_det <- st_intersection(ref_15m_test, buff_ext_test) %>% st_length() %>% as.numeric() %>% sum()
FN <- L_ref_test - ref_det
# Indices
completude <- ref_det / L_ref_test
correction <- TP / L_ext_test
fscore <- 2 * completude * correction / (completude + correction)
qualite <- TP / (TP + FP + FN)
# Surface de la zone test
zone <- st_read(here("02_data/clean/PNR_norm_maine/zone_test.gpkg"), quiet = TRUE)
zone <- st_transform(zone, st_crs(ext_test))
surface_ha <- as.numeric(st_area(zone)) / 10000
tibble(
L_ext_km = round(L_ext_test / 1000, 2),
L_ref_km = round(L_ref_test / 1000, 2),
surface_ha = round(surface_ha, 1),
dens_ext_ml_ha = round(L_ext_test / surface_ha, 1),
dens_ref_ml_ha = round(L_ref_test / surface_ha, 1),
TP_km = round(TP / 1000, 2),
FP_km = round(FP / 1000, 2),
FN_km = round(FN / 1000, 2),
completude = round(completude, 2),
correction = round(correction, 2),
fscore = round(fscore, 2),
qualite = round(qualite, 2)
) %>% kable(
caption = "Métriques de validation buffer-based (tampon = 15m) — zone test",
col.names = c("L ext (km)", "L ref (km)", "Surface (ha)",
"Densité ext (ml/ha)", "Densité ref (ml/ha)",
"VP (km)", "FP (km)", "FN (km)",
"Complétude", "Correction", "F-score", "Qualité")
)| L ext (km) | L ref (km) | Surface (ha) | Densité ext (ml/ha) | Densité ref (ml/ha) | VP (km) | FP (km) | FN (km) | Complétude | Correction | F-score | Qualité |
|---|---|---|---|---|---|---|---|---|---|---|---|
| 692.74 | 637.72 | 3307.9 | 209.4 | 192.8 | 594.64 | 98.1 | 49.46 | 0.92 | 0.86 | 0.89 | 0.8 |
- Pour cette petite zone test les résultats sont plus que satisfaisant :
- La longueur totale ainsi que la densité extraite est supérieure de quelques dizaines de km.
- Les scores des indices de complétude et de correction sont très proches et tendent vers le maximum, respectivement 0.92 et 0.86. En d’autres termes, 92% des haies digitalisées ont été retrouvées par l’extraction, .86% des haies extraites correspondent effectivement à des haies digitalisées. Ce qui nous donne des scores F et un indice de qualité aussi très haut.
2.3 Échantillonnage spatial systématique
Les résultats obtenus sur la zone test apparaissent plus que satisfaisants. Néanmoins, il est nécessaire d’augmenter l’échantillonnage pour renforcer la robustesse de la validation. Il ne nous est pas envisageable de procéder à ces mesures sur l’ensemble du réseau de haies du PNR, le temps de calcul étant prohibitif et les itérations ultérieures rendant cette approche impraticable.
Nous proposons un échantillonnage spatial systématique, en répartissant de manière régulière au sein des limites du PNR des disques de rayon constant (inspiré de la méthodologie mise en place par la DREAL Normandie pour le suivi statistique régional du bocage). Seuls les disques entièrement inclus dans le PNR sont conservés.
# Chargement des données du PNR en Lambert-93
ext <- st_read(here("02_data/clean/PNR_norm_maine/lineaire_haies_HT_1950s_pnr_normand.gpkg"), quiet = TRUE) %>%
st_transform(2154)
ref <- st_read(here("02_data/clean/PNR_norm_maine/lineaire_haies_digit_1950s_pnr_normand.gpkg"), quiet = TRUE) %>%
st_transform(2154)
# Limites du PNR
zone_pnr <- st_read(here("02_data/clean/PNR_norm_maine/limite_pnr_normand.gpkg"), quiet = TRUE) %>%
st_union() %>%
st_sf() %>%
st_transform(2154)
# Grille régulière (pas de 4 km)
grille <- st_make_grid(zone_pnr, cellsize = 4000, what = "centers") %>%
st_as_sf() %>%
st_filter(zone_pnr)
# Disques de 1 km de rayon, entièrement dans le PNR
disques <- st_buffer(grille, 1000)
disques <- disques[st_within(disques, zone_pnr, sparse = FALSE),]
disques$id <- 1:nrow(disques)
ggplot() +
geom_sf(data = zone_pnr, fill = NA, color = "black", linewidth = 1) +
geom_sf(data = disques, fill = NA, color = "red") +
labs(title = paste(nrow(disques), "disques d'échantillonnage (r = 1 km, pas = 4 km)")) +
theme_minimal()2.4 Résultats sur les disques du PNR
La chaîne de calcul des métriques développée sur la zone test est formalisée en fonction, puis appliquée à chaque disque d’échantillonnage.
# Fonction de calcul des métriques par disque
calcul_metriques_validation <- function(ext_d, ref_d, surface_ha, buffer_dist = 15) {
ext_f <- ext_d %>% filter(longueur >= 15)
ref_f <- ref_d %>% filter(long >= 15)
if (nrow(ext_f) < 5 | nrow(ref_f) < 5) {
return(tibble(L_ext_km = NA, L_ref_km = NA, dens_ext = NA, dens_ref = NA,
completude = NA, correction = NA, fscore = NA, qualite = NA))
}
L_ext <- sum(ext_f$longueur)
L_ref <- sum(ref_f$long)
buf_ref <- st_buffer(ref_f, buffer_dist) %>% st_union()
buf_ext <- st_buffer(ext_f, buffer_dist) %>% st_union()
TP <- st_intersection(ext_f, buf_ref) %>% st_length() %>% as.numeric() %>% sum()
ref_det <- st_intersection(ref_f, buf_ext) %>% st_length() %>% as.numeric() %>% sum()
FP <- L_ext - TP
FN <- L_ref - ref_det
completude <- ref_det / L_ref
correction <- TP / L_ext
tibble(
L_ext_km = round(L_ext / 1000, 2),
L_ref_km = round(L_ref / 1000, 2),
dens_ext = round(L_ext / surface_ha, 1),
dens_ref = round(L_ref / surface_ha, 1),
completude = round(completude, 4),
correction = round(correction, 4),
fscore = round(2 * completude * correction / (completude + correction), 4),
qualite = round(TP / (TP + FP + FN), 4)
)
}
surface_disque <- as.numeric(st_area(disques[1,])) / 10000
# Découpage des linéaires par disque
disques_ext <- map_dfr(1:nrow(disques), ~{
st_intersection(ext, disques[.x,]) %>% mutate(id_disque = .x)
})
disques_ref <- map_dfr(1:nrow(disques), ~{
st_intersection(ref, disques[.x,]) %>% mutate(id_disque = .x)
})
# Calcul par disque
resultats <- map_dfr(1:nrow(disques), ~{
cat("Disque", .x, "/", nrow(disques), "\r")
calcul_metriques_validation(
disques_ext %>% filter(id_disque == .x),
disques_ref %>% filter(id_disque == .x),
surface_ha = surface_disque
) %>% mutate(id_disque = .x, .before = 1)
})# Tableau résumé
resultats %>%
filter(!is.na(fscore)) %>%
summarise(
n_disques = n(),
L_ext_km_tot = round(sum(L_ext_km), 2),
L_ref_km_tot = round(sum(L_ref_km), 2),
dens_ext_moy = round(mean(dens_ext), 1),
dens_ref_moy = round(mean(dens_ref), 1),
completude_moy = round(mean(completude), 4),
correction_moy = round(mean(correction), 4),
fscore_moy = round(mean(fscore), 4),
qualite_moy = round(mean(qualite), 4)
) %>% kable(
caption = "Métriques moyennes sur l'ensemble des disques (tampon = 15m)",
col.names = c("N disques", "L ext (km)", "L ref (km)",
"Densité ext (ml/ha)", "Densité ref (ml/ha)",
"Complétude", "Correction", "F-score", "Qualité")
)| N disques | L ext (km) | L ref (km) | Densité ext (ml/ha) | Densité ref (ml/ha) | Complétude | Correction | F-score | Qualité |
|---|---|---|---|---|---|---|---|---|
| 68 | 3350.89 | 3201.48 | 156.9 | 149.9 | 0.8021 | 0.735 | 0.7592 | 0.631 |
La longueur totale du linéaire extrait au sein des disques représente 3351 km contre 3201 km pour la référence. Les densités sont relativement proches avec des valeurs respectives de 157 et 150 ml/ha. Sur ces seules mesures, l’extraction, bien que légèrement supérieure, apparaît comme réaliste.
L’indice de complétude est égal à 0.80 : 80 % du linéaire de référence est retrouvé à moins de 15 m d’un linéaire extrait. Les 20 % restants correspondent à des haies présentes dans la référence mais non détectées par l’extraction (faux négatifs). L’indice de correction est plus faible (0.73) : seuls 73 % du linéaire extrait se situent à proximité d’une haie de référence. Les 27 % restants correspondent à du linéaire détecté à tort — vergers, lisières forestières ou alignements d’arbres hors bocage (faux positifs).
Le F-score (0.76) est globalement satisfaisant mais témoigne d’un déséquilibre entre complétude et correction. L’indice de qualité (0.63) est plus sévère : sur l’ensemble des vrais positifs, faux positifs et faux négatifs, seuls 63 % des haies sont correctement extraites.
Ce déséquilibre entre complétude et correction pointe vers un nombre trop important de faux positifs. Il s’agit alors de filtrer ces détections erronées après classification.
3. Constat visuel et filtrage morphométrique
3.1 Constat visuel des erreurs
L’exploration visuelle des résultats révèle un certain nombre d’erreurs récurrentes et identifiables :
- Les vergers sont parfois identifiés comme des haies. Cela témoigne du bon fonctionnement de la chaîne HedgeTools — ce sont effectivement des arbres alignés — mais le contexte spatial d’un verger, reconnaissable à l’œil, n’est pas pris en compte par notre pipeline.
- Certaines portions forestières ont été classifiées comme des haies.
De manière générale, ces erreurs présentent des formes caractéristiques : les linéaires correspondants dessinent des virages serrés et des trajectoires sinueuses, contrastant avec la forme rectiligne ou faiblement courbée des haies véritables.
3.2 L’indice ACA (Bíl et al., 2018)
Il s’agit d’éliminer ces faux positifs présentant une géométrie caractéristique. Nous nous inspirons de la bibliographie traitant de l’extraction automatique des routes en adaptant pour nos haies un indice de sinuosité issu de la métrique Average Cumulative Angle (Bíl et al., 2018). Pour une même longueur, un verger présente davantage de changements de direction qu’une haie. On quantifie cette tortuosité par la somme des changements de direction divisée par la longueur du segment de haie considéré :
\[ACA = \frac{\sum_{i=1}^{n-2} |\alpha_i|}{L}\]
où :
- \(\alpha_i\) représente le changement d’angle (en radians) entre le segment reliant les vertices \(i-1\) et \(i\), et le segment reliant les vertices \(i\) et \(i+1\)
- \(n\) correspond au nombre de vertices de la polyligne
- \(L\) désigne la longueur totale du linéaire (en mètres)
L’ACA est exprimé en rad/m. Les valeurs élevées caractérisent des formes tortueuses (vergers, lisières forestières), tandis que les valeurs faibles indiquent des structures plus rectilignes (haies bocagères). Cet indice a été calculé au préalable sur l’ensemble du linéaire extrait, après simplification géométrique, à toutes les dates.
On peut visualiser la distribution spatiale de l’ACA sur la zone test :
# Renommer ACA si nécessaire sur la version test
ext_test_aca <- ext_test_wgs
if ("giration" %in% names(ext_test_aca) & !"ACA" %in% names(ext_test_aca)) {
ext_test_aca <- ext_test_aca %>% rename(ACA = giration)
}
ext_test_aca <- ext_test_aca %>% filter(!is.na(ACA))
pal_aca <- colorNumeric("viridis", ext_test_aca$ACA, reverse = TRUE, na.color = "transparent")
leaflet() %>%
addTiles(urlTemplate = ortho_1950, group = "Ortho 1950") %>%
addPolylines(data = ext_test_aca,
color = ~pal_aca(ACA),
weight = 3, opacity = 1,
label = ~paste("ACA :", round(ACA, 3), "rad/m")) %>%
addLegend(pal = pal_aca, values = ext_test_aca$ACA,
title = "ACA (rad/m)",
position = "bottomright",
opacity = 1)3.3 Distribution et choix de la gamme de seuils
La distribution de l’ACA est calculée sur l’ensemble du linéaire extrait du PNR (et non uniquement sur la zone test) :
# Renommer ACA sur l'objet PNR si nécessaire
if ("giration" %in% names(ext) & !"ACA" %in% names(ext)) {
ext <- ext %>% rename(ACA = giration)
}
ext_f <- ext %>% filter(longueur >= 15)
ggplot(ext_f, aes(x = ACA)) +
geom_histogram(bins = 50, fill = "steelblue", color = "white") +
labs(x = "ACA (rad/m)", y = "Nombre de linéaires",
title = "Distribution de l'indice ACA") +
theme_minimal()ext_f %>%
st_drop_geometry() %>%
summarise(
min = round(min(ACA), 4),
Q25 = round(quantile(ACA, 0.25), 4),
median = round(median(ACA), 4),
mean = round(mean(ACA), 4),
Q75 = round(quantile(ACA, 0.75), 4),
Q90 = round(quantile(ACA, 0.90), 4),
Q95 = round(quantile(ACA, 0.95), 4),
max = round(max(ACA), 4)
) %>% kable(caption = "Statistiques descriptives de l'ACA (rad/m)")| min | Q25 | median | mean | Q75 | Q90 | Q95 | max |
|---|---|---|---|---|---|---|---|
| 0 | 0 | 0.0176 | 0.0269 | 0.0414 | 0.0702 | 0.0893 | 0.6329 |
La majorité des linéaires présentent un ACA quasi nul, la moitié se situant sous 0.017 rad/m. Tester des seuils inférieurs au troisième quartile (0.041 rad/m) risquerait d’éliminer des haies légitimes. La gamme de seuils est donc définie entre le Q75 et la valeur maximale.
3.4 Détermination du seuil optimal d’ACA
Pour chaque valeur de seuil testée, les linéaires dont l’ACA dépasse cette valeur sont écartés, puis les métriques de validation sont recalculées sur l’ensemble des disques. Le seuil retenu est celui qui maximise le F-score, soit le meilleur compromis entre complétude et correction.
seuils <- seq(0.04, 0.10, by = 0.02)
resultats_aca <- map_dfr(seuils, function(s) {
cat("Seuil ACA :", s, "\r")
res <- map_dfr(1:nrow(disques), ~{
ext_d <- disques_ext %>% filter(id_disque == .x, longueur >= 15, ACA <= s)
ref_d <- disques_ref %>% filter(id_disque == .x, long >= 15)
if (nrow(ext_d) < 5 | nrow(ref_d) < 5) return(NULL)
L_ext <- sum(ext_d$longueur)
L_ref <- sum(ref_d$long)
buf_ref <- st_buffer(ref_d, 15) %>% st_union()
buf_ext <- st_buffer(ext_d, 15) %>% st_union()
TP <- st_intersection(ext_d, buf_ref) %>% st_length() %>% as.numeric() %>% sum()
ref_det <- st_intersection(ref_d, buf_ext) %>% st_length() %>% as.numeric() %>% sum()
tibble(TP = TP, L_ext = L_ext, L_ref = L_ref, ref_det = ref_det)
})
tibble(
seuil_ACA = s,
n_disques = nrow(res),
dens_ext = round(sum(res$L_ext) / (nrow(res) * surface_disque), 1),
dens_ref = round(sum(res$L_ref) / (nrow(res) * surface_disque), 1),
completude = sum(res$ref_det) / sum(res$L_ref),
correction = sum(res$TP) / sum(res$L_ext),
fscore = 2 * (sum(res$ref_det) / sum(res$L_ref)) * (sum(res$TP) / sum(res$L_ext)) /
((sum(res$ref_det) / sum(res$L_ref)) + (sum(res$TP) / sum(res$L_ext)))
)
})# Seuil optimal
seuil_opt <- resultats_aca %>% slice_max(fscore, n = 1)
seuil_opt %>% kable(
caption = "Seuil ACA optimal",
col.names = c("Seuil ACA", "N disques", "Densité ext (ml/ha)", "Densité ref (ml/ha)",
"Complétude", "Correction", "F-score"),
digits = 4
)| Seuil ACA | N disques | Densité ext (ml/ha) | Densité ref (ml/ha) | Complétude | Correction | F-score |
|---|---|---|---|---|---|---|
| 0.08 | 68 | 146.8 | 149.9 | 0.8261 | 0.7858 | 0.8055 |
# Graphique
ggplot(resultats_aca, aes(x = seuil_ACA)) +
geom_line(aes(y = completude, color = "Complétude"), linewidth = 1) +
geom_line(aes(y = correction, color = "Correction"), linewidth = 1) +
geom_line(aes(y = fscore, color = "F-score"), linewidth = 1.2) +
geom_vline(xintercept = seuil_opt$seuil_ACA, linetype = "dashed") +
labs(x = "Seuil ACA (rad/m)", y = "Score", color = NULL,
title = paste("Seuil optimal :", seuil_opt$seuil_ACA, "rad/m")) +
theme_minimal()On observe sur ce graphique qu’en augmentant la valeur seuil d’ACA, l’indice de complétude augmente tandis que l’indice de correction tend à diminuer. Le F-score croît jusqu’à atteindre un plateau lorsque les deux premiers indices divergent. En d’autres termes :
- Quand la valeur seuil d’ACA augmente, davantage de haies issues de la digitalisation sont retrouvées par l’extraction (hausse de la complétude).
- En revanche, de plus en plus de haies extraites ne correspondent pas à la référence (baisse de la correction).
- Le F-score est maximal à 0.08 rad/m. Toutefois, on observe une forte divergence entre complétude et correction pour cette valeur. À 0.06 rad/m, le F-score n’est que très faiblement diminué, tout en conservant un équilibre entre sur-détection et sous-détection. C’est cette valeur qui sera retenue.
3.5 Cartographie après filtrage
On applique les filtres retenus (longueur ≥ 15 m et ACA ≤ 0.06 rad/m) sur la zone test pour visualiser l’effet du post-traitement :
ext_test_filtre <- ext_test_aca %>% filter(longueur >= 15, ACA <= 0.06)
ref_test_filtre <- ref_test_wgs %>% filter(long >= 15)
leaflet() %>%
addTiles(urlTemplate = ortho_1950, group = "Ortho 1950") %>%
addPolylines(data = ext_test_filtre,
color = "yellow", weight = 3, opacity = 1,
group = "Extraction filtrée") %>%
addPolylines(data = ref_test_filtre,
color = "cyan", weight = 3, opacity = 1,
group = "Référence PNR") %>%
addLayersControl(overlayGroups = c("Extraction filtrée", "Référence PNR")) %>%
addLegend(colors = c("yellow", "cyan"),
labels = c("Extraction filtrée (L ≥ 15m, ACA ≤ 0.06)", "Digitalisation PNR"),
position = "bottomright",
opacity = 1)4. Conclusion
L’évaluation buffer-based sur l’ensemble des disques d’échantillonnage montre que l’extraction automatique du linéaire bocager à partir des orthophotos historiques atteint des niveaux de complétude et de correction satisfaisants. Le filtrage par longueur minimale (15 m) et par seuil d’ACA permet d’éliminer l’essentiel des faux positifs, i.e. vergers et lisières forestières. Le seuil retenu (ACA ≤ 0.06 rad/m), déterminé au point d’équilibre entre complétude et correction pour un F-score de l’ordre de 0.80, constitue un compromis robuste et reproductible.
Nous calculerons cette valeur seuil d’ACA pour chacune de nos dates, en nous basant sur les données de référence disponibles. Dans notre cas, nous disposons des digitalisations précises de différents bassins versants en Normandie, fournies par les travaux de Mathilde Guillemois (2025).
Certaines limites doivent être mentionnées. La largeur du tampon (15 m) absorbe une part d’imprécision positionnelle inhérente aux deux sources de données (Goodchild et Hunter, 1997), ce qui peut masquer des décalages locaux. L’ACA seul ne filtre pas les erreurs rectilignes, comme certaines lisières forestières droites. Enfin, la digitalisation de référence comporte elle-même toujours des incertitudes liées à la photo-interprétation manuelle (Congalton, 1991 ; Fraser et Congalton, 2019) : il est nécessaire de ne considérer aucune donnée de référence comme exempte d’erreur tout en la considérant comme la meilleure référence disponible.
Références
- Bíl, M., Andrášik, R., Sedoník, J. (2018). ROCA – An ArcGIS toolbox for road alignment identification and horizontal curve radii computation. PLOS ONE, 13(12), e0208407.
- Congalton, R.G. (1991). A review of assessing the accuracy of classifications of remotely sensed data. Remote Sensing of Environment, 37(1), 35-46.
- Foody, G.M. (2010). Assessing the accuracy of land cover change with imperfect ground reference data. Remote Sensing of Environment, 114(10), 2271-2285.
- Fraser, B.T., Congalton, R.G. (2019). Evaluating the Effectiveness of Unmanned Aerial Systems (UAS) for Collecting Thematic Map Accuracy Assessment Reference Data. Forests, 10(1), 24.
- Goodchild, M.F., Hunter, G.J. (1997). A simple positional accuracy measure for linear features. International Journal of Geographical Information Science, 11(3), 299-306.
- Guillemois, M. (2025). Trajectoires des paysages bocagers de la Normandie au Grand Ouest : approche géo-historique et modélisation des connectivités hydrologiques pour contribuer à la gestion intégrée des bassins versants. Thèse de doctorat, Normandie Université. ⟨NNT : 2025NORMC028⟩. ⟨tel-05509423⟩.
- Lian, R., Wang, W., Mustafa, N., Huang, L. (2020). Road Extraction Methods in High-Resolution Remote Sensing Images: A Comprehensive Review. IEEE Journal of Selected Topics in Applied Earth Observations and Remote Sensing, 13, 5489-5507.
- Marquès, G., Villierme, L., Boissonnat, J.-B. et al. (2024). HedgeTools : un outil d’analyse spatiale dédié à l’évaluation de la multifonctionnalité des haies. Mappemonde, 138.
- Pirbasti, M.A., McArdle, G., Akbari, V. (2024). Hedgerows Monitoring in Remote Sensing: A Comprehensive Review. IEEE Access, 12, 156184-156207.
- PNR Normandie Maine (2012). BD Bocage : construction d’un référentiel SIG du Bocage des PNR bas-normands. Cahier des Clauses Techniques Particulières, SER2012-16.
- Touya, G. (2010). Généralisation et intégration pour un fond vert commun entre l’IFN et l’IGN. Revue internationale de géomatique, 20(3), 299-320.
- Wiedemann, C., Heipke, C., Mayer, H., Jamet, O. (1998). Empirical evaluation of automatically extracted road axes. In Empirical Evaluation Techniques in Computer Vision, IEEE Computer Society Press, pp. 172-187.
- Wolstenholme, J.M., Cooper, F., Thomas, R.E. et al. (2025). Automated Identification of Hedgerows and Hedgerow Gaps Using Deep Learning. Remote Sensing in Ecology and Conservation, 11(4), 411-424.