Technologie
Les coulisses du modèle
Du jeu de données à l'inférence : comment le modèle est réellement construit, entraîné et exécuté. Pour les curieux et les techniques.
Tout le pipeline repose sur un petit ensemble d’outils en ligne de commande
(uv run piss-…). Voici les trois grandes étapes.
1. Générer le jeu de données d’entraînement
Pour apprendre, le modèle a besoin de paires (image, masque) : une photo aérienne et le contour des piscines qu’elle contient. On les fabrique automatiquement à partir des tuiles aériennes et des piscines déjà connues d’OpenStreetMap.
Chaque échantillon fait 256 × 256 pixels. Le générateur produit trois sortes d’échantillons, savamment dosées :
- Positifs (~60 %) — des tuiles contenant une piscine. Autour de chaque piscine connue, on prend plusieurs cadrages décalés (centré, sur un bord, dans un coin) pour que le modèle apprenne à la reconnaître dans toutes les positions.
- Négatifs (~25 %) — des tuiles sans aucune piscine (masque tout noir), pour apprendre au modèle à ne rien détecter là où il n’y a rien.
- Négatifs difficiles (~15 %) — les pièges : bassins et étangs, courts de tennis, panneaux solaires, serres… des objets qui ressemblent à une piscine mais n’en sont pas.
Deux détails de qualité : le découpage train / validation / test se fait par blocs géographiques (80/10/10), pour qu’une même zone ne se retrouve jamais à la fois dans l’entraînement et dans le test (pas de « triche »). Et comme les contours d’OpenStreetMap sont un peu imprécis, on recale légèrement chaque contour sur l’eau réelle et on ignore une fine bande autour des bords.
# Générer un dataset sur deux villages, en utilisant les corrections humaines
uv run piss-dataset --area bbox:4.89,45.58,5.02,45.67 --zoom 19 \
--out data/dataset/marennes-chaponnay-v1 --seed 42 --use-curated
L’option --use-curated applique les validations faites par les humains dans
l’interface de revue : elle écarte les fausses détections et les tuiles sans
piscine, pour un jeu de données plus propre.
2. Lancer un entraînement
On entraîne ensuite le modèle sur ce jeu de données. Chaque passage complet sur les données s’appelle une epoch ; le modèle s’améliore à chaque passage.
uv run piss-train --dataset data/dataset/marennes-chaponnay-v1 \
--epochs 40 --device mps
Les principaux réglages :
| Réglage | Défaut | Rôle |
|---|---|---|
--encoder | resnet18 | Ossature du réseau (resnet18 ou resnet34) |
--epochs | 40 | Nombre de passages sur les données |
--batch | 32 | Nombre d’images traitées d’un coup |
--lr | 3e-4 | Vitesse d’apprentissage |
--device | auto | cuda (GPU NVIDIA), mps (Mac), cpu |
--seed | 42 | Graine aléatoire, pour des résultats reproductibles |
L’entraînement produit un dossier data/models/unet-resnet18-vXXX/ contenant le
modèle, un rapport de métriques (précision, rappel, F1, courbes) et des journaux
TensorBoard pour suivre la progression.
On exporte enfin le meilleur modèle au format ONNX — un fichier autonome qui embarque architecture et poids, exécutable sans PyTorch, y compris dans un navigateur :
uv run piss-export \
--ckpt data/models/unet-resnet18-vXXX/best.ckpt \
--out data/models/unet-resnet18-vXXX/model.onnx
3. Lancer une inférence (un scan)
Le scan tourne sur le fichier .onnx (via onnxruntime, sans PyTorch). Il
analyse une zone et renvoie les piscines détectées au format GeoJSON.
# Scan d'un village, avec un rapport HTML illustré
uv run piss-scan --dry-run \
--area bbox:4.89,45.58,5.02,45.67 \
--model data/models/unet-resnet18-vXXX/model.onnx \
--report /tmp/scan.md --report-html /tmp/scan.html
--dry-runrenvoie les détections en GeoJSONL (une ligne par piscine), chargeable dans QGIS ou geojson.io.--report/--report-htmlproduisent un rapport avec les vignettes des détections (image + masque superposé).
C’est exactement ce calcul qui, dans l’application, tourne dans votre navigateur plutôt que sur un serveur.
Architecture & choix techniques
- Architecture : un réseau U-Net avec un encodeur ResNet-18 pré-entraîné sur ImageNet. Le U-Net est conçu pour la segmentation : il compresse l’image pour la « comprendre », puis la reconstruit pixel par pixel en carte de probabilités.
- Entrée / sortie : tuiles de 256 × 256 pixels ; sortie = une carte de probabilité « piscine » par pixel.
- Fonction de coût : moitié BCE, moitié Dice, avec une bande d’ignore de 2 pixels autour des contours (les tracés OSM sont imprécis au pixel près).
- Augmentation des données : symétries et rotations (une piscine n’a pas d’orientation), légères variations de luminosité. On évite les gros décalages de teinte — le bleu est le signal — et les changements d’échelle.
- Réglage du seuil : le modèle sort des probabilités ; un seuil décide où couper. Seuil bas → plus de détections (meilleur rappel, moins de précision) ; seuil haut → l’inverse.

- Exécution : le modèle exporté en ONNX (57 Mo) tourne directement dans le navigateur — voir la page Technologie.
Envie de contribuer ?
Prêtez votre puissance de calcul ou validez des piscines dès maintenant.
Participer