Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Imagerie Parcellaire

Contexte

CerOps collecte des images satellite via l’API Copernicus (Sentinel-2) pour chaque parcelle agricole enregistrée. Ces images sont analysées pour produire des indices agronomiques (NDVI, stress hydrique, teneur en chlorophylle) qui permettent à l’agriculteur de suivre l’évolution de ses cultures dans le temps.

Objectif

Donner à l’agriculteur une vision temporelle de l’état de ses parcelles sans qu’il ait à commander une mission drone : les données satellite sont collectées automatiquement à chaque passage disponible (tous les 5 jours environ pour Sentinel-2), traitées en arrière-plan, et consultables depuis l’interface web.

Utilisateurs concernés

  • Agriculteur : consulte les cartes d’indices et l’historique de ses parcelles
  • Admin : supervise les acquisitions et relance les analyses en échec

Pipeline d’acquisition et d’analyse

Vue d’ensemble

Copernicus API
    │
    ▼ acquisition image brute
RustFS (S3)
    │
    ▼ message RabbitMQ
Worker d'analyse
    ├── calcule indices (NDVI, B04, B08…)
    ├── appende au cube Zarr de la parcelle (RustFS)
    └── met à jour les métadonnées en base

Acquisition

Les images brutes Sentinel-2 sont téléchargées depuis l’API Copernicus et stockées dans RustFS avant traitement. Ce stockage intermédiaire découple la récupération (réseau externe, latence variable, possible indisponibilité) du pipeline d’analyse.

Traitement asynchrone (RabbitMQ)

Chaque nouvelle image disponible publie un message dans RabbitMQ. Un worker consomme la queue, calcule les indices spectraux et met à jour le cube Zarr de la parcelle. Ce découplage permet de traiter les analyses sans bloquer l’API, et de scaler horizontalement en ajoutant des workers.

Stockage des données : cubes Zarr

C’est l’un des choix architecturaux les plus structurants du projet.

Le problème

Les données agronomiques sont intrinsèquement temporelles : chaque passage satellite produit une nouvelle tranche de données par parcelle. Accumulées sur une saison ou plusieurs années, elles forment une série temporelle volumineuse.

Stocker ça naïvement pose des problèmes :

  • En base de données (PostgreSQL) : une ligne par parcelle × date × indice crée des tables qui grossissent de façon incontrôlée, les requêtes “donne-moi le NDVI de cette parcelle sur 18 mois” deviennent coûteuses, et PostgreSQL n’est pas fait pour des tableaux numériques denses.
  • En fichiers individuels (GeoTIFF par date) : pour reconstituer une série temporelle, il faut lire N fichiers séquentiellement, ce qui est lent et peu pratique pour de l’analyse.

La solution : le cube Zarr

Zarr est un format de tableau N-dimensionnel chunké et compressé, conçu nativement pour les accès partiels sur stockage objet (S3).

Un cube Zarr par parcelle a trois dimensions :

cube[parcelle_id] → tableau 3D :
    ├── axe 0 : temps       (dates d'acquisition satellite)
    ├── axe 1 : x           (pixels longitude)
    └── axe 2 : y           (pixels latitude)
    ... par bande / indice (NDVI, B04, B08…)

Le cube est découpé en chunks (ex. 30 dates × 64px × 64px). Lire “le NDVI de janvier à mars” ne charge que les chunks correspondants, pas l’intégralité du cube. C’est le même principe qu’un index en base de données, mais pour des tableaux multidimensionnels.

Avantages concrets

BesoinApproche naïveZarr
Série temporelle d’une parcelleN requêtes SQL ou N fichiers1 lecture de chunks ciblés
Ajouter une nouvelle date d’acquisitionINSERT + gestion du schémaAppend d’un chunk sur l’axe temps
Analyse sur une fenêtre temporelleScan de table ou boucle fichiersSlice cube[t_start:t_end, :, :]
Stockage sur S3Peu adapté (fichiers plats)Natif, chaque chunk est un objet S3
Interopérabilité Python (xarray, numpy)Conversion nécessaireLecture directe

Flux de mise à jour

À chaque nouvelle acquisition Copernicus, le worker :

  1. Récupère l’image brute depuis RustFS
  2. Calcule les indices (NDVI, stress hydrique…)
  3. Appende la nouvelle tranche au cube Zarr de la parcelle dans RustFS
  4. Met à jour les métadonnées en base (dernière date disponible, couverture nuageuse)

La base de données ne contient jamais les valeurs pixel, uniquement les métadonnées. Les cubes Zarr sont la source de vérité pour toute l’analyse agronomique.

Cas limites

  • Couverture nuageuse : Sentinel-2 peut être inutilisable certains jours. La couverture nuageuse est stockée en métadonnée ; l’interface signale les lacunes à l’agriculteur.
  • Parcelle sans historique : à la création d’une parcelle, le cube Zarr est initialisé vide et se remplit au fil des acquisitions suivantes.
  • Échec du worker : RabbitMQ gère les relivraisons automatiques. Un message en échec répété passe en dead-letter queue pour traitement manuel.

Dépendances

  • RustFS : stockage des images brutes et des cubes Zarr
  • RabbitMQ : orchestration du pipeline d’analyse
  • Copernicus API : source des images Sentinel-2
  • Module Parcelles : les cubes sont indexés par parcelle_id