Rewrite README and docs in English for GitHub, add MIT license, remove internal files
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
512
README.md
512
README.md
@ -1,318 +1,256 @@
|
||||
# Pipeline LiDAR Archéologique
|
||||
<div align="center">
|
||||
|
||||
Workflow automatisé pour générer des visualisations exploitables à partir de données LiDAR HD (IGN) pour la détection de structures archéologiques. Tourne en Docker avec accélération GPU optionnelle (NVIDIA/CuPy).
|
||||
# lidar_rendu
|
||||
|
||||
## Visualisations (18 par fichier)
|
||||
**See through the forest.** Turn France's open LiDAR HD point clouds into seamless,
|
||||
archaeology-grade relief maps — served as a fast slippy map, reusable XYZ tiles
|
||||
and print-ready PDF field sheets.
|
||||
|
||||
### Relief orienté (couche par défaut)
|
||||
Une seule image fusionne le micro-relief et l'orientation des pentes : la **clarté** porte le relief local (openness positive sur MNT détendancé, rayons 5–20 m, plus un léger ombrage), la **teinte** porte l'orientation (aspect, cercle CIELAB à clarté constante : aucune couleur ne crée de faux relief). Échelle fixe : les dalles voisines se raccordent sans couture.
|
||||
[](LICENSE)
|
||||

|
||||

|
||||
-76B900?logo=nvidia&logoColor=white)
|
||||

|
||||

|
||||
|
||||
C'est la **seule couche produite et affichée par défaut** (`PANEL_VIZ` dans `index.py`) : un traitement sans `--only`, la génération lancée depuis la carte et la carte elle-même (panneau, tuiles XYZ, TileJSON, WMTS) se limitent au relief orienté. Les visualisations ci-dessous restent calculables explicitement (`--only slope aspect ...`).
|
||||
<img src="docs/img/neuf-brisach.png" alt="Neuf-Brisach fortress in oriented relief" width="900">
|
||||
|
||||
### Visualisations principales
|
||||
| # | Visualisation | Utilité archéologique |
|
||||
|---|--------------|----------------------|
|
||||
| 1 | **Hillshade multidirectionnel** | Murs, terrasses, structures linéaires, routes |
|
||||
| 2 | **Pente (Slope)** | Murs de soutènement, talus, changements brusques |
|
||||
| 3 | **Aspect (Orientation)** | Direction des pentes, exposition |
|
||||
| 4 | **Courbure (Curvature)** | Fossés, terrasses, talus, concavité/convexité |
|
||||
| 5 | **Sky-View Factor** | Structures, tumulus, fondations (ray-tracing 16 azimuts) |
|
||||
| 6 | **Local Relief Model** | Micro-reliefs, fossés, levées de terrain |
|
||||
| 7 | **Positive Openness** | Élévations, tumulus, bâtiments (ray-tracing 8 directions) |
|
||||
| 8 | **Negative Openness** | Cavités, fossés, souterrains (ray-tracing 8 directions) |
|
||||
<sub>Neuf-Brisach (Haut-Rhin), Vauban's star fortress (UNESCO World Heritage), rendered from one 1 km LiDAR HD tile.
|
||||
Every bastion, moat and ravelin reads at a glance; buildings are black (no ground points).</sub>
|
||||
|
||||
### Visualisations avancées
|
||||
| # | Visualisation | Description | Détection |
|
||||
|---|--------------|-------------|-----------|
|
||||
| 9 | **MSRM** | Multi-Scale Relief Model (sigma 5/10/25/50/100m) | Tumulus, fossés, murs à toutes les échelles |
|
||||
| 10 | **TPI multi-échelle** | Topographic Position Index (5m + 100m) | Crêtes, vallées, plateformes |
|
||||
| 11 | **Dépressions** | Remplissage cuvettes + différence | Dolines, sinkholes, zones inondables |
|
||||
| 12 | **SAILORE** | LRM adaptatif (noyau = f(pente)) | Terrain hétérogène, tout relief |
|
||||
| 13 | **Rugosité** | Écart-type de l'élévation | Surfaces anthropiques vs naturelles |
|
||||
| 14 | **Anomalies statistiques** | Z-score + Local Moran's I | Anomalies topographiques significatives |
|
||||
| 15 | **Ondelette Mexican Hat** | CWT 2D multi-échelle | Tumulus, fossés circulaires |
|
||||
| 16 | **Accumulation de flux** | Algorithme D8 hydrologique | Fossés d'enceinte, routes antiques |
|
||||
</div>
|
||||
|
||||
### Cartes de référence IGN
|
||||
| # | Visualisation | Source |
|
||||
|---|--------------|--------|
|
||||
| 17 | **Photographie aérienne IGN** | Orthophotographie WMTS |
|
||||
| 18 | **Carte topographique IGN** | Plan IGN V2 WMTS |
|
||||
---
|
||||
|
||||
## Classification du sol
|
||||
## Why
|
||||
|
||||
Le pipeline classifie automatiquement les points sol à partir du nuage de points bruit. Le pré-traitement suit le workflow recommandé par PDAL :
|
||||
The French mapping agency (IGN) publishes **LiDAR HD**: a nationwide airborne laser
|
||||
scan, ~10 points/m², free under the *Licence Ouverte 2.0*. Hidden under forest
|
||||
canopy and fields are hollow ways, trenches, burial mounds, field systems and
|
||||
forgotten walls — but raw point clouds are hard to read, and naïve DEM renderings
|
||||
show seams at every tile edge, stripes from the flight lines and colour blotches
|
||||
that look like relief but aren't.
|
||||
|
||||
1. **Filtre ReturnNumber** — élimine les points avec numéros de retour invalides
|
||||
2. **Réinitialisation Classification** — remet toutes les classifications à 0
|
||||
3. **ELM** (Extended Local Minimum) — marque les points bas aberrants comme bruit (Classification=7)
|
||||
4. **Outlier statistique** — supprime les points isolés (mean_k=8, multiplier=3.0)
|
||||
5. **Classification sol** — SMRF, PMF ou CSF
|
||||
6. **Extraction** — ne conserve que les points Classification=2
|
||||
`lidar_rendu` is an end-to-end pipeline that solves exactly that:
|
||||
|
||||
### Méthodes de classification
|
||||
- **One command** from an IGN tile ID to a browsable map.
|
||||
- **One carefully designed layer** — *oriented relief* — instead of fifteen
|
||||
colormaps to flip through.
|
||||
- **Seamless at any scale**: fixed scales, no per-tile statistics, 100 m
|
||||
overlap borrowed from the eight neighbouring tiles.
|
||||
- **Measurement-aware**: a companion *precision* layer shows where the terrain is
|
||||
measured and where it is interpolated, so you never mistake a gap for a feature.
|
||||
|
||||
| Méthode | Mode | Usage | Vitesse |
|
||||
|---------|------|-------|---------|
|
||||
| **SMRF** | Auto (défaut) | Terrain naturel, forêt, rocaille | Rapide |
|
||||
| **PMF** | Auto (si urbain) | Zones urbaines, bâtiments, routes | Rapide |
|
||||
| **CSF** | Manuel uniquement | Terrain très complexe, falaises | Lent |
|
||||
## Gallery
|
||||
|
||||
L'auto-détection analyse le ratio de retours uniques du nuage de points : ratio > 0.6 = milieu urbain → PMF, sinon → SMRF.
|
||||
<table>
|
||||
<tr>
|
||||
<td width="50%"><img src="docs/img/hartmannswillerkopf.png" alt="Hartmannswillerkopf battlefield"></td>
|
||||
<td width="50%"><img src="docs/img/neuf-brisach-a4.png" alt="A4 PDF field sheet of Neuf-Brisach"></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><b>Hartmannswillerkopf</b> (tile 1011_6760) — the WWI battlefield of 1915 under dense
|
||||
forest: roads, trench lines and shell craters appear on the slope.</td>
|
||||
<td><b>PDF field sheet</b> exported from the map (A4 landscape, 1:5,000): Lambert 93 grid,
|
||||
true-north arrow, scale bar, legend and data-quality inset.</td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
### Pré-traitement ELM (terrain calcaire)
|
||||
## Highlights
|
||||
|
||||
Les paramètres ELM sont adaptés au terrain calcaire rocailleux avec végétation basse :
|
||||
- `cell=5.0m` — résolution fine pour capturer le relief rocheux
|
||||
- `threshold=2.0m` — seuil élevé pour ne pas marquer les affleurements comme bruit
|
||||
| | |
|
||||
|---|---|
|
||||
| **Oriented relief** | A single RGB image: CIELAB *lightness* carries local openness (bumps light, hollows dark), *hue* carries slope orientation at constant lightness — so colour never fakes relief. |
|
||||
| **Flight-strip calibration** | Each tile mixes several passes, sometimes offset by a few cm. The pipeline estimates per-strip offsets, per-scan-line shift and roll, and a per-beam cross-track profile, then removes them before rasterising. No more stripes. |
|
||||
| **Honest gap filling** | At 0.2 m, ~80 % of pixels contain no point. Gaps are closed morphologically within the point envelope, with a radius that follows local point spacing — nothing is extrapolated outward. |
|
||||
| **Seamless tiles** | DTMs are built on the nominal 1 km tile plus a 100 m buffer taken from the neighbours (downloaded automatically), then cropped back exactly. |
|
||||
| **Fast** | GPU (CuPy) when available, numba otherwise. Ground extraction straight from IGN classes with laspy (~5 s per tile), relief kernel ~5 s on a 12-core CPU, AVIF encoding in 0.6 s. |
|
||||
| **Slippy map** | Built-in Leaflet UI: tile selection with IGN metadata, relief / precision / side-by-side compare, adjustable intensity, light & dark themes, mobile bottom sheet, shareable links. |
|
||||
| **Standard tiles** | `/tiles/{layer}/{z}/{x}/{y}.png` in the OpenStreetMap scheme, plus TileJSON, WMTS and a JOSM imagery file — drop it into QGIS, JOSM, iD, uMap or MapLibre. |
|
||||
| **Generate from the map** | Draw a rectangle: the tiles are downloaded from IGN, processed, and appear on the map row by row as they finish. |
|
||||
| **Print** | Vector PDF sheets (A4/A3, 1:1,000 – 1:10,000) with grid, WGS84 corners, meridian convergence, legend and point-density inset. |
|
||||
| **Runs on a Raspberry Pi** | A lightweight image (no PDAL, no GPU) serves the map and delegates generation to a worker machine; it keeps working offline. |
|
||||
|
||||
## Architecture modulaire
|
||||
## Quick start
|
||||
|
||||
Requirements: Docker with Compose ≥ 2.24. An NVIDIA GPU is optional.
|
||||
|
||||
```bash
|
||||
git clone https://github.com/<you>/lidar_rendu.git && cd lidar_rendu
|
||||
|
||||
./start.sh # build the image, start the map on http://localhost:8973/
|
||||
./start.sh process --fetch-tiles 1037,6779 # download one IGN tile (Neuf-Brisach) and process it
|
||||
./start.sh logs # follow the server log
|
||||
./start.sh stop # stop everything
|
||||
```
|
||||
|
||||
`start.sh` creates `input/` and `output/` owned by you and checks whether Docker
|
||||
can reach a GPU; if not, it adds `docker-compose.cpu.yml` and everything runs on
|
||||
the CPU (slower, same output).
|
||||
|
||||
Tile IDs are the IGN grid coordinates in km (Lambert 93): `1037,6779` is the tile
|
||||
whose top-left corner is at X = 1,037 km, Y = 6,779 km. You can also skip the
|
||||
command line entirely: open the map, go to the **Génération** tab and draw a
|
||||
zone.
|
||||
|
||||
> The user interface and log messages are in French; code identifiers are in English.
|
||||
|
||||
## How it works
|
||||
|
||||
```mermaid
|
||||
flowchart LR
|
||||
A[IGN LiDAR HD<br/>COPC .laz tile] --> B[Ground points<br/>IGN classes, laspy]
|
||||
N[8 neighbour tiles<br/>100 m buffer] --> B
|
||||
B --> C[Strip & scan-line<br/>calibration]
|
||||
C --> D[DTM 0.2 m<br/>+ bounded gap fill]
|
||||
D --> E[Oriented relief<br/>+ precision layer]
|
||||
E --> F[AVIF tiles<br/>cropped to 1 km]
|
||||
F --> G[Inventory +<br/>XYZ pyramid]
|
||||
G --> H[Map · XYZ/WMTS · PDF]
|
||||
```
|
||||
|
||||
1. **Download** — the COPC tile and, if missing, its eight neighbours from the IGN
|
||||
Géoplateforme. Tiles are processed north to south, so the map fills top down.
|
||||
2. **Ground** — IGN's ground class (2) extracted directly with laspy; PDAL (SMRF /
|
||||
CSF) remains available. See [ground classification](docs/GROUND_CLASSIFICATION.md).
|
||||
3. **Calibration** — robust per-strip vertical offsets, then a joint least-squares
|
||||
adjustment of every scan line (offset + roll) against the other strips, plus a
|
||||
per-beam angular profile. Results are written to a JSON sidecar next to the DTM.
|
||||
4. **DTM** — rasterised at 0.2 m on the tile + buffer; small gaps closed within the
|
||||
point envelope; ground density saved alongside.
|
||||
5. **Render** — oriented relief (openness at 5 / 10 / 20 m on a detrended DTM,
|
||||
16 directions, plus 35 % hillshade) and precision (16 log-scale density levels).
|
||||
Fixed scales everywhere: identical terrain gives identical colour on every tile.
|
||||
6. **Publish** — AVIF quadrants encoded once from the source raster, inventory
|
||||
refreshed after every tile, XYZ pyramid pre-generated in the background.
|
||||
|
||||
## The map
|
||||
|
||||
- **Click a tile** to select it: extent, IGN acquisition date, sensors, point count,
|
||||
download link, and the calibration applied to each flight strip.
|
||||
- **Three view modes** — relief, precision, or *compare* with a draggable split bar.
|
||||
- **Relief intensity** slider (0.5×–2×), remembered per browser and carried in the link.
|
||||
- **Share** — the URL encodes position, mode, comparison and intensity.
|
||||
- **Use in JOSM / QGIS** button — copies the tile URL for the current layer.
|
||||
- Keyboard: `1`–`5` tabs, `P` next view mode, `Esc` deselect / collapse.
|
||||
- Works on phones: the panel becomes a three-height bottom sheet; GPS centring over HTTPS.
|
||||
|
||||
Full reference: [docs/MAPS.md](docs/MAPS.md).
|
||||
|
||||
## Use the tiles anywhere
|
||||
|
||||
| Client | URL |
|
||||
|---|---|
|
||||
| QGIS, iD, uMap, Leaflet, MapLibre | `http://<host>:8973/tiles/relief_oriente/{z}/{x}/{y}.png` |
|
||||
| JOSM (TMS) | `http://<host>:8973/tiles/relief_oriente/{zoom}/{x}/{y}.png` |
|
||||
| JOSM (all layers at once) | `http://<host>:8973/tiles/josm.imagery.xml` |
|
||||
| TileJSON 3.0 | `http://<host>:8973/tiles/relief_oriente.json` |
|
||||
| WMTS 1.0 | `http://<host>:8973/tiles/wmts.xml` |
|
||||
|
||||
256 px PNG, EPSG:3857, transparent outside coverage, CORS enabled, zoom 5–19
|
||||
(19 ≈ 0.2 m/px, one screen pixel per LiDAR pixel).
|
||||
|
||||
## Command line
|
||||
|
||||
The processing pipeline is `python3 -m lidar_pipeline`; with Docker Compose,
|
||||
`./start.sh process [options]` runs it on `input/` → `output/`.
|
||||
|
||||
| Option | Default | Purpose |
|
||||
|---|---|---|
|
||||
| `--fetch-tiles COL,ROW …` | — | Download these LiDAR HD tiles from IGN first |
|
||||
| `--file NAME …` | all of `input/` | Process only these tiles (name without `.laz`) |
|
||||
| `-r RES` | `0.2` | Resolution in m/px (comma-separated for several) |
|
||||
| `-g [GPU]` | CPU | GPU(s): `-g`, `-g 0`, `-g 0,2`, `-g all` |
|
||||
| `-w N` | `auto` | Parallel workers (bounded by free VRAM per GPU) |
|
||||
| `--only VIZ …` / `--skip VIZ …` | map layers | Choose visualisations |
|
||||
| `--edge-buffer M` | `100` | Buffer borrowed from neighbour tiles (0 = off) |
|
||||
| `--ground-classification` | `ign` | `ign`, `auto`, `smrf`, `csf` |
|
||||
| `--no-strip-align` | on | Disable flight-strip calibration |
|
||||
| `--format`, `--quality` | `avif`, `60` | Output encoding |
|
||||
| `-f`, `--force` | off | Regenerate even if outputs exist |
|
||||
| `--rebuild-index` | — | Rebuild the tile inventory only |
|
||||
| `-v`, `--debug` | — | Verbose / debug logging |
|
||||
|
||||
By default only the map layers are produced (`relief_oriente`, `densite_sol`).
|
||||
Classic visualisations remain one flag away, e.g.
|
||||
`./start.sh process --only hillshade slope svf pos_open`:
|
||||
|
||||
| Key | Visualisation | | Key | Visualisation |
|
||||
|---|---|---|---|---|
|
||||
| `hillshade` | Multi-directional hillshade | | `svf` | Sky-View Factor |
|
||||
| `slope` | Slope | | `roughness` | Roughness |
|
||||
| `aspect` | Aspect | | `wavelet` | Mexican-hat wavelet (multi-scale) |
|
||||
| `mslrm` | Multi-scale relief model | | `flow_acc` | D8 flow accumulation |
|
||||
| `sailore` | Slope-adaptive local relief | | `solar` | Solar illumination |
|
||||
| `pos_open` / `neg_open` | Positive / negative openness | | `anomaly` | Statistical anomalies |
|
||||
| `ortho` / `topo` | IGN orthophoto / topographic map | | | |
|
||||
|
||||
## Deployment
|
||||
|
||||
| Setup | Command | Port |
|
||||
|---|---|---|
|
||||
| All-in-one (map + generation) | `docker compose up -d --build serve` (or `./start.sh`) | 8973 |
|
||||
| Processing worker for remote maps | `docker compose -f docker-compose.worker.yml up -d --build` | 8973 |
|
||||
| Lightweight map (Raspberry Pi, no PDAL/GPU) | `docker compose -f docker-compose.maps.yml up -d --build` | 8975 |
|
||||
|
||||
The lightweight map mirrors the worker's tiles, delegates generation to it, and
|
||||
keeps serving from disk when the worker is off. Tokens (`LIDAR_API_TOKEN`) and a
|
||||
network allow-list (`LIDAR_REGEN_CIDR`, private ranges by default) protect the
|
||||
generation API. Step-by-step guide: [docs/DEPLOY_WEBAPP.md](docs/DEPLOY_WEBAPP.md).
|
||||
|
||||
Always pass `--build`: the code is baked into the image, and the build is
|
||||
near-instant thanks to the layer cache.
|
||||
|
||||
## Project layout
|
||||
|
||||
```
|
||||
lidar_pipeline/
|
||||
├── __init__.py # Exports publics
|
||||
├── __main__.py # Point d'entrée: python -m lidar_pipeline
|
||||
├── cli.py # argparse + logging + main()
|
||||
├── gpu.py # CuPy/numpy abstraction (HAS_GPU, to_gpu, to_cpu, xp_*)
|
||||
├── dtm.py # Classification PDAL (SMRF/PMF/CSF + auto) + génération DTM
|
||||
├── visualizations.py # Fonctions generate_* (19 visualisations)
|
||||
├── ign.py # Téléchargement tuiles IGN + overlay
|
||||
├── rendering.py # Colormaps, tif_to_png, rapport PDF
|
||||
├── pipeline.py # LidarArchaeoPipeline (orchestration + registry)
|
||||
└── tests/ # Tests unitaires (pytest)
|
||||
├── cli.py command line
|
||||
├── pipeline.py orchestration, worker pool, VRAM-aware GPU slots
|
||||
├── fetch_ign.py IGN catalogue and downloads
|
||||
├── dtm.py ground extraction, strip calibration, DTM, gap filling
|
||||
├── visualizations.py generate_* functions (relief, openness, SVF, …)
|
||||
├── rendering.py colormaps, GeoTIFF → AVIF, 1 km crop
|
||||
├── index.py catalogue, thumbnails, sub-tiles, inventory, layer registry
|
||||
├── quality.py per-tile quality sidecar (density, acquisition dates)
|
||||
├── tiles.py XYZ pyramid: reprojection, cache, background maintenance
|
||||
├── mapserve.py FastAPI server: map, tiles, TileJSON/WMTS, generation API
|
||||
├── export_pdf.py PDF field sheets (Pillow + pyproj + reportlab)
|
||||
├── gpu.py CuPy / NumPy abstraction with CPU fallback
|
||||
├── web/ map UI (HTML, CSS, JS)
|
||||
└── tests/ ~400 pytest tests
|
||||
```
|
||||
|
||||
Ajouter une visualisation = 1 fonction + 1 entrée dans `VIZ_STEPS` + 1 entrée dans `COLORMAPS`.
|
||||
|
||||
## Exemples
|
||||
|
||||
Relief orienté sur deux dalles LiDAR HD, rendues par ce pipeline (`./start.sh process --fetch-tiles 1037,6779 1011,6760 ...`).
|
||||
|
||||
**Neuf-Brisach** (dalle 1037_6779) — l'enceinte bastionnée de Vauban, ses fossés et ses demi-lunes ; en noir, les bâtiments (aucun point sol).
|
||||
|
||||

|
||||
|
||||
**Hartmannswillerkopf** (dalle 1011_6760) — versant forestier du champ de bataille de 1915 : chemins, tranchées et trous d'obus sous le couvert.
|
||||
|
||||

|
||||
|
||||
**Planche PDF** exportée depuis la carte (onglet PDF, A4 paysage, 1:5 000) : quadrillage Lambert 93, légende, encart qualité des données.
|
||||
|
||||

|
||||
|
||||
## Démarrage rapide
|
||||
## Development
|
||||
|
||||
```bash
|
||||
git clone <ce dépôt> && cd lidar_rendu
|
||||
./start.sh # construit l'image, démarre la carte sur http://localhost:8973/
|
||||
./start.sh process --fetch-tiles 1037,6779 --file LHD_FXX_1037_6779_PTS_LAMB93_IGN69.copc.laz
|
||||
# télécharge une dalle IGN et la traite
|
||||
./start.sh logs # journal du serveur
|
||||
./start.sh stop # arrêt
|
||||
./run.sh --test # rebuild the image and run the full test suite
|
||||
docker run --rm lidar-lidar python3 -m pytest -v --pyargs lidar_pipeline.tests.test_tiles
|
||||
```
|
||||
|
||||
`start.sh` crée `input/` et `output/` à votre nom et détecte le GPU : sans GPU
|
||||
NVIDIA utilisable par Docker, il ajoute `docker-compose.cpu.yml` et le
|
||||
traitement tourne sur le CPU (plus lent). Docker Compose ≥ 2.24 requis.
|
||||
Adding a visualisation takes four edits: a `generate_X()` in `visualizations.py`,
|
||||
an entry in `VIZ_STEPS` (`pipeline.py`), a colormap in `rendering.py`, and a legend
|
||||
in `VIZ_LEGENDS` (`index.py`). Design decisions and conventions are documented in
|
||||
[AGENTS.md](AGENTS.md) (French).
|
||||
|
||||
## Installation Docker
|
||||
Contributions are welcome: open an issue or a pull request.
|
||||
|
||||
```bash
|
||||
cd /votre/dossier/lidar
|
||||
mkdir -p input
|
||||
## Documentation
|
||||
|
||||
# Copiez vos fichiers .laz dans input/
|
||||
cp /chemin/vos/fichiers/*.laz input/
|
||||
- [docs/MAPS.md](docs/MAPS.md) — map UI, tile contract, cache, PDF export, environment variables
|
||||
- [docs/DEPLOY_WEBAPP.md](docs/DEPLOY_WEBAPP.md) — two-machine deployment (Raspberry Pi + worker)
|
||||
- [docs/GROUND_CLASSIFICATION.md](docs/GROUND_CLASSIFICATION.md) — ground filters benchmark and literature
|
||||
|
||||
# Build l'image Docker
|
||||
docker build -t lidar-lidar .
|
||||
```
|
||||
## Data and licences
|
||||
|
||||
## Utilisation
|
||||
- **Code**: [MIT](LICENSE).
|
||||
- **LiDAR HD, orthophotos, maps**: © IGN, [Licence Ouverte 2.0](https://www.etalab.gouv.fr/licence-ouverte-open-licence/).
|
||||
Attribution is required and is shown on every map, tile endpoint and PDF.
|
||||
- **Base map**: © [OpenStreetMap](https://www.openstreetmap.org/copyright) contributors.
|
||||
Before using these renderings as a tracing source in OpenStreetMap, check the
|
||||
community's position on the source.
|
||||
|
||||
### Traitement complet avec GPU (recommandé)
|
||||
```bash
|
||||
./run.sh -g
|
||||
```
|
||||
|
||||
### Traitement standard (CPU seul)
|
||||
```bash
|
||||
./run.sh
|
||||
```
|
||||
|
||||
### Options du script run.sh
|
||||
```
|
||||
./run.sh [options]
|
||||
-r RESOLUTION Résolution en m/px (défaut: 0.5)
|
||||
-w WORKERS Nombre de workers parallèles (défaut: 1)
|
||||
-g Activer l'accélération GPU NVIDIA
|
||||
-v Mode verbeux (timestamps + niveaux)
|
||||
--debug Mode debug (détails internes fichier:ligne)
|
||||
-f / --force Régénérer tous les fichiers même si les WebP existent
|
||||
--force-classification Reclassifier le sol même si le fichier .las existe déjà
|
||||
--ground-classification Méthode de classification: ign, auto, smrf, csf (défaut: ign — imposé par la carte)
|
||||
--edge-buffer M Raccord des bords avec les dalles voisines (défaut: 100 m — imposé par la carte)
|
||||
--file NOM... Traiter un ou plusieurs fichiers LAZ spécifiques
|
||||
--test Exécuter les tests unitaires
|
||||
-h Afficher l'aide
|
||||
```
|
||||
|
||||
### Exemples
|
||||
```bash
|
||||
# Traitement standard avec GPU
|
||||
./run.sh -g
|
||||
|
||||
# GPU + mode verbeux
|
||||
./run.sh -g -v
|
||||
|
||||
# GPU + 4 workers parallèles
|
||||
./run.sh -g -w 4
|
||||
|
||||
# Haute résolution (0.2m/px)
|
||||
./run.sh -g -r 0.2
|
||||
|
||||
# Forcer la régénération de tous les fichiers
|
||||
./run.sh -g --force
|
||||
|
||||
# Reclassifier le sol seulement (sans régénérer les visualisations)
|
||||
./run.sh -g --force-classification
|
||||
|
||||
# Forcer la classification PMF au lieu de l'auto-détection
|
||||
./run.sh -g --ground-classification pmf
|
||||
|
||||
# Forcer la classification CSF (lent mais robuste sur terrain complexe)
|
||||
./run.sh -g --ground-classification csf
|
||||
|
||||
# Traiter un fichier spécifique (test rapide)
|
||||
./run.sh -g --file LHD_FXX_1000_6882_PTS_LAMB93_IGN69.copc
|
||||
|
||||
# Traiter deux fichiers spécifiques
|
||||
./run.sh -g --file LHD_FXX_1000_6881_PTS_LAMB93_IGN69.copc LHD_FXX_1000_6882_PTS_LAMB93_IGN69.copc
|
||||
|
||||
# Exécuter les tests unitaires
|
||||
./run.sh --test
|
||||
```
|
||||
|
||||
### Utilisation directe Docker
|
||||
```bash
|
||||
# Traitement standard
|
||||
docker run --rm -v $(pwd)/input:/data/input:ro -v $(pwd)/output:/data/output lidar-lidar
|
||||
|
||||
# Avec GPU + classification forcée
|
||||
docker run --rm --gpus all -v $(pwd)/input:/data/input:ro -v $(pwd)/output:/data/output \
|
||||
lidar-lidar python3 -m lidar_pipeline /data/input -o /data/output \
|
||||
--ground-classification pmf
|
||||
|
||||
# Forcer la reclassification du sol
|
||||
docker run --rm --gpus all -v $(pwd)/input:/data/input:ro -v $(pwd)/output:/data/output \
|
||||
lidar-lidar python3 -m lidar_pipeline /data/input -o /data/output \
|
||||
--force-classification
|
||||
|
||||
# Mode verbeux
|
||||
docker run --rm --gpus all -v $(pwd)/input:/data/input:ro -v $(pwd)/output:/data/output \
|
||||
lidar-lidar python3 -m lidar_pipeline /data/input -o /data/output -v
|
||||
```
|
||||
|
||||
## Structure des dossiers
|
||||
|
||||
```
|
||||
.
|
||||
├── input/ # Fichiers .laz (monté en read-only dans Docker)
|
||||
├── output/ # Résultats générés
|
||||
│ ├── DTM/ # Modèles numériques de terrain (GeoTIFF)
|
||||
│ ├── temp/ # Fichiers temporaires (classification .las)
|
||||
│ ├── visualisations/ # Images WebP par fichier LAZ
|
||||
│ │ ├── fichier_6881/ # Un sous-dossier par fichier LAZ
|
||||
│ │ │ ├── ..._hillshade_multi.webp
|
||||
│ │ │ ├── ..._svf.webp
|
||||
│ │ │ ├── ..._mslrm.webp
|
||||
│ │ │ └── ... (19 visualisations)
|
||||
│ │ └── fichier_6882/
|
||||
│ │ └── ...
|
||||
│ └── rapports/ # Rapports PDF A3 par fichier
|
||||
│ ├── fichier_6881_rapport.pdf
|
||||
│ └── fichier_6882_rapport.pdf
|
||||
├── lidar_pipeline/ # Package Python modulaire
|
||||
│ ├── cli.py # Arguments CLI + logging
|
||||
│ ├── gpu.py # Abstraction CuPy/numpy
|
||||
│ ├── dtm.py # Classification sol + DTM
|
||||
│ ├── visualizations.py # 19 fonctions generate_*
|
||||
│ ├── ign.py # Tuiles IGN
|
||||
│ ├── rendering.py # Colormaps, WebP, PDF
|
||||
│ ├── pipeline.py # Orchestration
|
||||
│ └── tests/ # Tests unitaires
|
||||
├── process_lidar.py # Point d'entrée compatible
|
||||
├── Dockerfile
|
||||
├── run.sh
|
||||
└── README.md
|
||||
```
|
||||
|
||||
## Paramètres
|
||||
|
||||
| Paramètre | Option | Défaut | Description |
|
||||
|-----------|--------|--------|-------------|
|
||||
| Résolution | `-r` | 0.5 | Résolution en mètres par pixel |
|
||||
| Workers | `-w` | 1 | Nombre de CPU pour traitement parallèle |
|
||||
| GPU | `-g` | off | Activer l'accélération NVIDIA GPU |
|
||||
| Classification sol | `--ground-classification` | ign | Méthode : ign, auto, smrf, csf (la carte impose ign) |
|
||||
| Forcer classification | `--force-classification` | off | Reclassifier le sol même si .las existe |
|
||||
| Output | `-o` | /data/output | Dossier de sortie |
|
||||
| Force | `-f/--force` | off | Régénérer même si les WebP existent |
|
||||
| File | `--file` | tous | Traiter un ou plusieurs fichiers LAZ |
|
||||
| Verbose | `-v` | off | Mode verbeux (timestamps + niveaux) |
|
||||
| Debug | `--debug` | off | Mode debug (détails internes) |
|
||||
|
||||
### Résolution recommandée
|
||||
- `0.2` — Très fine, bâtiments individuels (lent)
|
||||
- `0.5` — Recommandée archéologie (équilibre vitesse/détail)
|
||||
- `1.0` — Rapide, grandes structures uniquement
|
||||
|
||||
## Interprétation archéologique
|
||||
|
||||
### Pour détecter les cavités et souterrains
|
||||
1. **Negative Openness** — Zones sombres = creux profonds
|
||||
2. **Dépressions** — Carte spécifique des dolines et sinkholes
|
||||
3. **Local Relief Model** — Zones bleues = dépressions
|
||||
4. **Hillshade** — Ombres inhabituelles en forme de trous
|
||||
|
||||
### Pour détecter structures et bâtiments anciens
|
||||
1. **MSRM** — Détection multi-échelle de tous les reliefs
|
||||
2. **Sky-View Factor** — Structures géométriques claires
|
||||
3. **SAILORE** — LRM adaptatif pour terrain hétérogène
|
||||
4. **Anomalies statistiques** — Anomalies topographiques significatives
|
||||
|
||||
### Pour hydrologie et fossés
|
||||
1. **Accumulation de flux** — Fossés d'enceinte, routes antiques
|
||||
2. **Dépressions** — Zones de collecte d'eau, dolines
|
||||
3. **Negative Openness** — Fossés et tranchées
|
||||
|
||||
## Tests
|
||||
|
||||
```bash
|
||||
./run.sh --test
|
||||
```
|
||||
|
||||
Les tests tournent dans le conteneur Docker et couvrent la classification du sol (SMRF/PMF/CSF), l'auto-détection, le rendu, et les visualisations.
|
||||
|
||||
## Dépannage
|
||||
|
||||
```bash
|
||||
# Vérifier Docker
|
||||
docker --version
|
||||
|
||||
# Shell dans le conteneur
|
||||
docker run --rm -it -v $(pwd)/input:/data/input -v $(pwd)/output:/data/output \
|
||||
--entrypoint bash lidar-lidar
|
||||
|
||||
# Reconstruire l'image
|
||||
docker build --no-cache -t lidar-lidar .
|
||||
|
||||
# Nettoyer
|
||||
docker system prune -a
|
||||
```
|
||||
|
||||
### Erreur mémoire
|
||||
Augmenter la mémoire Docker à 16Go+ pour les gros fichiers LiDAR HD.
|
||||
|
||||
### Données LiDAR HD (IGN)
|
||||
Les fichiers COPC (.laz) de l'IGN sont supportés directement. Le pipeline détecte automatiquement la méthode de classification du sol (SMRF/PMF) en analysant le ratio de retours uniques du nuage de points.
|
||||
Built on [PDAL](https://pdal.io), [laspy](https://laspy.readthedocs.io),
|
||||
[rasterio](https://rasterio.readthedocs.io), [CuPy](https://cupy.dev),
|
||||
[numba](https://numba.pydata.org), [FastAPI](https://fastapi.tiangolo.com),
|
||||
[Leaflet](https://leafletjs.com) and [reportlab](https://www.reportlab.com).
|
||||
|
||||
Reference in New Issue
Block a user