Big Data LiDAR : Traitement à l'Échelle du Téraoctet

Quand la RAM ne suffit plus : Architectures logicielles pour nuages de points massifs.
Expert
90 min
Dask, PDAL, Multiprocessing
Vue du dessus d'une fenêtre de dalle LiDAR HD : le sol, la végétation et les toitures se distinguent par leur classe
Une fenêtre de 140 mètres dans une dalle de 39 millions de points. C'est l'unité de travail dont parle cet article.
"Traiter un fichier de 100 Mo est trivial. Traiter une campagne LiDAR aéroportée de 500 Go nécessite un changement de paradigme : du 'In-Memory' vers le 'Streaming' et le 'Out-of-Core'."

1. Le Goulot d'Étranglement Mémoire

Un point LiDAR standard (X, Y, Z, Intensité, R, G, B, GPS Time) pèse environ 32 à 64 octets non compressé. Un milliard de points représente donc ~50 Go de RAM brute. Charger cela dans un script Python naïf provoquera un MemoryError immédiat sur la plupart des workstations.

Ce qu'il faut savoir : Python ajoute un overhead significatif aux objets. Une liste de listes Python [[x,y,z], ...] consomme jusqu'à 5x plus de mémoire qu'un array NumPy contigu.

2. Stratégie 1 : Le Chunking avec Laspy

La bibliothèque laspy permet de lire les fichiers .LAZ par morceaux (chunks) sans tout charger. C'est la première ligne de défense.

chunk_processor.py
import laspy
import numpy as np

def process_massive_file(filepath, chunk_size=1_000_000):
    with laspy.open(filepath) as f:
        # Itérateur sur les points par paquets de 1 million
        for chunk in f.chunk_iterator(chunk_size):
            points = np.column_stack((chunk.x, chunk.y, chunk.z))
            
            # Traitement local (ex: filtrage hauteur)
            mask = points[:, 2] > 50.0
            # Sauvegarde incrémentale ou aggregation de statistiques
            save_result(points[mask])

Cette méthode garde l'empreinte mémoire constante (égale à chunk_size), quelle que soit la taille totale du fichier.

3. Stratégie 2 : Le Tiling Spatial (Tuilage)

Pour des opérations contextuelles (calcul de normales, maillage), le chunking séquentiel ne suffit pas car il brise la continuité spatiale. Nous devons découper le nuage en tuiles géographiques (Tiles) avec un buffer de recouvrement.

Quatre tuiles carrées adjacentes ; l'une d'elles est active et s'entoure d'une bande de recouvrement qui mord sur ses voisines tuile (n, m) 1 km de côté recouvrement 20 m pris chez les voisines Sans lui, tout calcul de voisinage se trompe au bord de chaque tuile.
Le tuilage, et la bande qui le rend juste. Chaque tuile est traitée seule, dans son propre processus. Mais un point situé au bord n'a pas tous ses voisins dans sa tuile : normales, densité et segmentation y seraient fausses. On lit donc une bande de recouvrement chez les tuiles adjacentes, et on la jette après calcul.

PDAL (Point Data Abstraction Library) est l'outil roi pour générer ces tuiles via la ligne de commande ou son binding Python.

pdal_tiling.json
[
    "input.laz",
    {
        "type": "filters.splitter",
        "length": 100.0,
        "buffer": 2.0
    },
    {
        "type": "writers.las",
        "filename": "tile_#.laz"
    }
]

4. Stratégie 3 : Multiprocessing (Parallélisme)

Une fois les données tuilées (ou chunkées), nous pouvons saturer les cœurs du CPU. Le GIL Python nous empêche d'utiliser des Threads efficacement pour le calcul pur, nous utilisons donc multiprocessing.

parallel_engine.py
from multiprocessing import Pool, cpu_count

def worker_task(tile_path):
    # Processus isolé : Charge, Traite, Sauvegarde
    pcd = load(tile_path)
    result = heavy_algorithm(pcd)
    return result.status

if __name__ == "__main__":
    files = glob.glob("tiles/*.laz")
    # Utilisation de tous les cœurs disponibles
    with Pool(processes=cpu_count()) as pool:
        results = pool.map(worker_task, files)
Le relevé de Florent : Sur un Ryzen 9 5950X (16 cœurs), le traitement parallèle de tuiles réduit le temps de calcul d'un facteur 12x par rapport au séquentiel (pas 16x à cause de l'overhead des I/O disque).

5. Memory Mapping (Memmap)

Pour les cas où l'accès aléatoire est nécessaire sur le dataset entier, numpy.memmap permet de mapper un fichier binaire sur le disque dur comme s'il était en RAM. L'OS gère le paging automatiquement.

Méthode Vitesse Accès Capacité Max Complexité
RAM (Standard) Extrême (~50 GB/s) Limité par RAM physique Faible
HDD (Seek/Read) Lente (~150 MB/s) Illimitée Moyenne
Memmap (NVMe) Haute (~3-7 GB/s) Limité par Disque Moyenne

Synthèse : L'Architecture Idéale

Pour traiter une ville entière :

  1. Split : PDAL pour découper en tuiles de 100 m de côté, avec recouvrement.
  2. Process : Script Python Multiprocessing lançant un worker par tuile.
  3. Merge : Fusion des résultats légers (vecteurs, métadonnées) dans une base de données spatiale (PostGIS).

Sur ce sujet : Le programme de la formation, module par module.

Devenez Architecte Big Data 3D

Savoir coder est une chose, concevoir des architectures scalables en est une autre. Notre module "Infrastructure" vous attend.

Recevoir le guide gratuit Passer le test (10 min)

Le programme et les tarifs →