Commit Graph

47 Commits

Author SHA1 Message Date
90dbe61f3b Borner le comblement du MNT à l'enveloppe des points, ajouter la couche précision et un affichage relief/précision, encoder les sous-tuiles une seule fois en q75
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-27 15:07:04 +02:00
d32502b74e Recaler les lignes de balayage des passes et accélérer le rendu
Troisième passe du calage vertical : chaque ligne de balayage (décalage et
inclinaison due au roulis) est recalée contre le consensus des autres
faisceaux, à toutes les échelles, avec un profil d'étalonnage par faisceau
et par degré d'angle qui retire les écarts non linéaires en travers de la
fauchée. Les lignes sans recouvrement sont corrigées contre leur propre
faisceau. Efface les lignes en creux et la marche au bord de fauchée
mesurées sur LHD_FXX_0999_6882 (validé sur des blocs jamais vus). Calcul
vectorisé, CuPy si GPU ; la gigue par fenêtres de temps devient inutile
quand scan_angle existe.

Rendu plus rapide : encodage AVIF speed 9 (0,6 s au lieu de 4 s par dalle),
classification IGN par extraction directe laspy au lieu de PDAL (4,9 s au
lieu de 13,5 s), comblement des trous et gradients sur GPU, cache numba
persistant dans l'image.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-27 01:57:04 +02:00
0d3c3ba8bc Ajouter la couche relief orienté et une échelle d'openness fixe
Nouvelle visualisation relief_oriente : une image RGB unique qui fusionne
l'openness positive locale (MNT détendancé σ 10 m, rayons 5/10/20 m,
16 directions) portée par la clarté CIELAB et l'orientation des pentes
portée par la teinte. Échelle log fixe et support de 40 m sous la bande
de raccord de 100 m : dalles jointives. Calcul sur grille décimée à 0,8 m,
noyau dédié (CuPy RawKernel, numba parallèle, repli numpy) et colorisation
par table L* × teinte : ~8 s par dalle sur CPU au lieu de ~50 s.

L'openness positive et négative est normalisée par des références figées
mesurées sur 15 dalles au lieu d'un z-score par dalle, qui rendait
l'échelle de couleur non jointive.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-27 00:05:40 +02:00
3a374a3ab4 AVIF q60 par défaut et sélecteur de mode de fusion par couche 2026-09-19 21:26:13 +02:00
5f018fe2b6 Raccorder les bords de tuiles voisines et encadrer les rendus en cours
Le MNT de chaque dalle s'étend d'une bande de 100 m remplie avec les
points sol des 8 tuiles voisines (option « Raccord des bords ») : les
rendus à grand noyau (openness, SVF, LRM) deviennent continus d'une
dalle à l'autre, les images restent recadrées sur le kilomètre exact.

Pendant une génération, la carte encadre les dalles du run : orange
pulsant en cours de rendu, rouge en échec — les coins WGS84 sont portés
par /api/status pour toutes les dalles non terminées.

La file de génération trie les dalles du nord au sud et passe à 10
workers GPU.
2026-09-19 20:44:44 +02:00
796e68c870 Supprimer le code mort (imports inutilisés, variable _xp, conseil GPU inatteignable) 2026-09-18 21:31:19 +02:00
91d31bcdf9 Numéroter les zones après tri, lire le journal par la fin et corriger l'aide -g 2026-09-18 21:24:57 +02:00
5e13151998 Fermer les images PIL et borner le cache de cartes de localisation 2026-09-18 21:20:14 +02:00
476f246fe7 Masquer le nodata avant étalonnage colormap et colorbar en unités réelles 2026-09-18 21:05:55 +02:00
3c19dc4226 Blinder la normalisation terrain contre les tuiles d'altitude constante 2026-09-18 21:04:13 +02:00
8d29f03191 Rendre l'échelle de rugosité jointive entre tuiles
Le z-score par tuile et le vmax au percentile 98 par tuile donnaient une
échelle de couleur non jointive (écart-type variant de 0,05 a 0,58 m selon
la dalle). Références de normalisation figées (médianes mesurées sur 20
dalles réelles) et vmax fixe 3,8 (p98 médian) : même rugosité physique =
même couleur partout.
2026-09-16 20:33:56 +02:00
68272cabf0 Tuiles visibles en direct après régénération et déploiement webapp distante
- URLs images versionnées (?v=mtime) : une tuile recalculée change d'URL et
  force le rechargement navigateur (cache heuristique contourné), y compris
  en plein run via /api/tiles ; veille permanente 15 s sur la carte
- simulation locale du mode deux machines (docker-compose.local-2m.yml) :
  worker GPU :8974 + webapp légère :8973 au cache séparé output-webapp/
- override webapp pour le Pi 5 (192.168.3.3) : volume /srv/lidar/output,
  rsync vers le worker, labels Traefik (proxy/websecure/myresolver)
- purge 0,5 m : worker/process et politique générale passés à 0,2 m seul
- intègre le travail parallèle non commité : export mosaïque multi-dalles
  (export.py + /api/export), sous-tuilage intégral des couches, légendes
  VIZ_LEGENDS, docs et tests associés (213 tests verts)
2026-09-12 17:48:37 +02:00
74580a922b Fix NaN artifacts in tif_to_crop tile rendering
Replace NaN values with 0 before colormap application so no-data
zones render as the darkest color instead of undefined pixels.
2026-09-07 21:15:29 +02:00
422f58d772 Split webapp for Raspberry Pi deployment, remote generation API and sync
La webapp (carte + vignettes) et la génération de tuiles se déploient sur
deux machines : image légère Dockerfile.webapp (FastAPI + Pillow AVIF
natif + pyproj) sur Raspberry Pi, pipeline complet sur la machine de
traitement. LIDAR_GENERATION_URL délègue /api/generate, /api/preview et
/api/status ; /api/sync ramène les tuiles par rsync puis régénère
vignettes et index localement. Token partagé optionnel
(LIDAR_API_TOKEN/LIDAR_REMOTE_TOKEN). Retire du dépôt les journaux
internes (.swival, audit-findings) et les données (data/, notebooks/).
Doc : docs/DEPLOY_WEBAPP.md.
2026-09-02 19:44:39 +02:00
ed3e90ea89 Add visualization picker to zone generation and unify tile colors
- Web map: multi-select picker in the generation bar (aspect, slope,
  positive openness, anisotropic openness, wavelet) passed to the API;
  the layer panel is restricted to the same shortlist (PANEL_VIZ) and
  a refresh button rebuilds the index when new layers appear on disk;
  jobs started outside the UI are now adopted into the visible queue
- Uniform colors across tiles: openness/anisotropic/sailore now store
  local z-scores, and all renderers use fixed ranges (0-3 sigma, SVF
  0-1 physical, slope 0-30 deg) instead of per-tile percentile stretches
- Ray-tracing falls back to CPU when VRAM is exhausted so openness and
  SVF no longer fail silently on shared GPUs
- build_index merges visualizations available at only one resolution
  into the displayed tile so in-progress layers stay visible
- 11 new tests (142 passing)
2026-08-31 19:02:14 +02:00
8ca65155db Add web map with zone generation API, side job queue, and restore historical DTM hole rendering
- webapp.py: FastAPI serving the continuous map (port 8973) with
  /api/preview, /api/generate and /api/status; tiles are downloaded
  from IGN and processed in a logged subprocess, tracked live in a
  side "File de génération" panel that survives page reloads
- fetch_ign.py: download missing 1 km LiDAR HD tiles from the IGN
  geoplateforme before processing
- index.py: tile thumbnails and 500 m subtiles are now invalidated by
  mtime so regenerating a tile refreshes its cached images; progress
  logging per tile
- dtm.py: back to the historical gap handling (small gaps filled by
  fillnodata only, larger holes left as nodata rendered black);
  lowest-return floor only via --bare-earth, IGN class selection via
  --ign-classes
- cli.py: positional input now optional (--rebuild-index works alone)
- docker-compose.yml: serve (GPU, port 8973) and process services;
  launch via docker compose only (documented in AGENTS.md/AGENTS.md)
- tests: 131 passing, incl. regressions for thumbnail staleness,
  --rebuild-index without input, and nodata rendering
2026-08-31 18:07:14 +02:00
3d79a5ee72 carte continue: cropped images + continuous map + PDF download via jsPDF 2026-07-28 23:37:40 +02:00
8478106e51 Fix GPU bugs, restore aspect viz, fix anomaly mask, revert flow_acc to vectorized D8
GPU: num_gpus() returns real count via _gpu_candidates (was always 0/1),
available_gpu_ids() added. Pipeline: round-robin on real GPU host indices
instead of file enumerate index. _process_file_standalone signature simplified.

Restore generate_aspect using SharedDEM gradient (dy, dx). Colormap twilight
0-360 fixed range. VIZ_STEPS back to 16.

Flow accumulation: revert to vectorized numpy D8 direction + module-level
numba accumulator (cached, top-down sort) with Python fallback. Priority-flood
NaN-aware. Log1p transform.

Anomaly mask: replace RMS+fixed 2sigma threshold (was blank) with weighted
sum of |z-score| + adaptive percentile threshold. Absolute z-score captures
both positive and negative deviations. 6% signal detected vs 0% before.
2026-06-01 23:03:19 +02:00
89f3333b65 Add anomaly mask: automatic threshold detection across all viz layers 2026-05-31 18:34:45 +02:00
65631b18b0 Fix colormap legends: remove (deg) on normalized openness, correct flow_acc YlGn direction, remove LRM references, fix wavelet norm mode 2026-05-31 17:33:01 +02:00
929fac9aa0 Remove LRM, TPI, aspect, curvature, paths + add flow accumulation, directional Gabor wavelets, multi-radius ray-tracing 2026-05-31 17:19:31 +02:00
266214fe3e Fix 12 bugs: D8 flow accumulation, PDF AVIF support, GPU memory leaks, dead code, SAILORE sigma scaling 2026-05-31 15:13:11 +02:00
30122c71ed Performance optimizations and rendering improvements
GPU multi-processing fix:
- gpu.py: revert to CUDA_VISIBLE_DEVICES approach with lazy CuPy init
  (Device.use() caused CUDA_ERROR_NO_BINARY_FOR_GPU on GPU 1)
- CuPy is imported lazily on first to_gpu() call, allowing
  CUDA_VISIBLE_DEVICES to be set before CUDA context creation
- nvidia-smi used for GPU count detection (no CUDA import needed)
- pipeline.py: add tip message suggesting -w N when multiple GPUs detected

Rendering improvements:
- Title: split into bold title (14pt) + italic description (10pt)
- North arrow: moved inside data area (top-right) with transparent
  background — no longer overlaps title
- Colorbar: full height (compass gap removed), ScalarFormatter with
  useOffset=False to prevent scientific notation on small values

Performance:
- rendering.py: save matplotlib figure to BytesIO instead of temp PNG
  file — eliminates disk I/O between matplotlib and PIL
- visualizations.py: cap max_dist at 300 for ray-tracing (SVF,
  openness, aniso_open) — avoids 500+ iterations at 0.2m resolution
- pipeline.py: deduplicate n_gpus calculation in parallel path
2026-05-15 12:32:51 +02:00
a3f7b44874 Fix multi-GPU with lazy CuPy init + rendering improvements
GPU fix:
- Revert to CUDA_VISIBLE_DEVICES approach but with lazy CuPy init
- gpu.py: CuPy is no longer imported at module level; _init_gpu()
  imports it lazily on first to_gpu() call. This allows workers to
  set CUDA_VISIBLE_DEVICES before CuPy creates a CUDA context.
- gpu.py: detect GPU count via nvidia-smi (no CUDA context needed)
- pipeline.py: each worker sets CUDA_VISIBLE_DEVICES=N before CuPy
  init, so each process uses only its assigned GPU

Rendering improvements:
- Title: split into bold title (14pt) + italic description (10pt)
  instead of single 15pt bold block
- North arrow: moved inside data area (top-right corner) with
  semi-transparent white background for readability over data
- Colorbar: full height (no gap for compass rose), added
  ScalarFormatter(useOffset=False) to avoid scientific notation
- Colorbar compass rose gap removed since north arrow is now
  inside the data area
2026-05-15 12:24:57 +02:00
b4a0e384c9 Change minimap zoom to level 10 for wider view and faster download
Zoom 10 gives ~150m/px with 30km context (274px image), ideal for a
small inset. Much faster to download than zoom 12 (1100px).
2026-05-15 12:03:19 +02:00
9e89686ac5 Reduce location map context to 30km and use zoom 12
The 80km context made the red LiDAR zone rectangle too small to see.
30km (15km radius) at zoom 12 gives a clear view where the 1km data
zone is visible as a distinct red rectangle in the inset map.
2026-05-15 12:01:37 +02:00
5af53a390f Add multi-GPU support and fix scale bar / location map overlap
Multi-GPU:
- gpu.py: lazy CuPy initialization so CUDA_VISIBLE_DEVICES takes
  effect before context creation in worker processes
- gpu.py: detect GPU count via nvidia-smi (no CUDA import needed)
- gpu.py: add set_active_gpu() to assign workers to specific GPUs
- pipeline.py: distribute files across GPUs (file % num_gpus) in
  parallel mode so both GPUs are used simultaneously
- pipeline.py: log GPU count when multiple GPUs detected

Layout fixes:
- rendering.py: move scale bar left of location map to avoid overlap
  (scale bar ends at fig_x=0.78, map starts at 0.82)
- rendering.py: expand location map inset to 0.16x0.13 fig coords
- rendering.py: return bounds from _download_location_map so imshow
  extent matches the actual IGN tile coverage (80km context)
- ign.py: add min_zoom parameter to download_ign_tiles, fixing the
  location map that was broken (zoom 10 blocked by hardcoded min_zoom=15)
2026-05-15 12:00:34 +02:00
4848f25326 Upgrade colormaps to Crameri scientific palette and fix IGN location map
- Replace RdBu_r with Crameri roma for all 6 relief-family colormaps
  (curvature, mslrm, lrm, tpi, sailore, aniso_open): perceptually
  uniform, CVD-friendly, dark center makes near-zero values visible
- Replace hsv with twilight for aspect: perceptually uniform cyclic
  colormap with no hue discontinuity
- Add cmcrameri dependency (falls back to RdBu_r if unavailable)
- Fix IGN location map: pass min_zoom=8 to download_ign_tiles so zoom
  10 context maps work (was hardcoded to min_zoom=15, blocking the
  loop entirely for zoom_level=10)
- Expand location map context from 3x extent to 80km fixed radius for
  better regional context at zoom 10
- Remove dead code: flow colormap entry, _nice_scale dead loop,
  aspect='auto' in location map imshow, outdated PDF report order list
- Fix SVF docstring: 8 directions → 16 directions
2026-05-15 11:50:15 +02:00
c634db573a Fix corrupted COPC detection, add CSF→SMRF fallback, improve MSRM colormap, add SVF and anisotropic openness
- validate_laz: verify point data accessibility (not just headers) to detect
  corrupted COPC files that pass header checks but fail on data reads
- classify_ground: fallback from CSF to SMRF when CSF produces no ground
  points or PDAL errors (fixes 2/9 failing tiles)
- MSRM: preserve sign in weighted combination so RdBu_r colormap shows
  both red (elevated) and blue (depressed) instead of red only
- Add Sky-View Factor (SVF) visualization: cos²(horizon angle) over 16
  directions, excellent for archaeological earthwork detection
- Add Anisotropic Openness: directional weighting (NW-SE/NE-SW) enhances
  linear feature detection aligned with common settlement patterns
- Remove anomalies and flow visualizations (replaced by SVF + aniso_open)
- Location inset: use IGN topographic map at zoom 10 instead of simplified
  France outline, with red rectangle marker and fallback
- Remove flow (hydrological accumulation) from VIZ_STEPS
2026-05-15 01:38:09 +02:00
da454bd23e Improve visualizations: adaptive scales, revert z-score to std normalization
- MSRM/TPI/roughness/anomalies: revert z-score (x-mean)/std to std normalization x/std
  to preserve contrast and visibility of linear features (paths, ditches, trenches)
- MSRM: adaptive scales based on resolution, archaeological weight combination
- TPI: extend from 2 to 4 scales (3m/15m/50m/200m) with weighted combination
- Hillshade: 8 directions instead of 4, altitude 35° instead of 30°
- LRM: adaptive sigma based on resolution
- Openness: doubled radius (100m instead of 50m)
- Roughness: multi-scale (3m fine + 15m broad) instead of single 5x5 window
- Anomalies: uses MSRM multi-scale relief instead of single LRM 15m
- Wavelet: 8 adaptive scales, std normalization, archaeological weights
- Remove svf (Sky-View Factor) and local_dominance visualizations
- Add AVIF format support (default), quality 98
- Add multi-resolution support (-r 0.5,0.2)
- Improve Ctrl+C handling for immediate process termination
- Update rendering.py descriptions for all modified visualizations
2026-05-14 23:12:08 +02:00
6aef7b8af3 Add WebP quality control and selective visualization (--only / --skip)
- WebP output now uses quality=85 by default (down from lossless),
  reducing file size by ~75% (35MB → 5-8MB per visualization)
- Added --quality N (1-100) and --lossless flags in CLI and run.sh
- Added --only and --skip to select/exclude specific visualizations
  (e.g., --only hillshade,svf,lrm or --skip ortho,topo)
- VIZ_STEPS filtering is done in LidarArchaeoPipeline.__init__
- SharedDEM is skipped when all selected visualizations already exist
- Invalid visualization names are validated at startup with clear error
2026-05-14 21:15:21 +02:00
f97e41eaea Remove RRIM and Multi-Hillshade RGB, fix DTM resolution reuse bug, add --init to docker run
- Remove generate_rrim, generate_multi_hillshade, _compute_openness_both
- Remove corresponding VIZ_STEPS entries, COLORMAPS, RGB_LEGENDS, and tests
- Fix DTM resolution mismatch: existing DTM at different resolution is now
  regenerated instead of silently reused
- Propagate actual DTM resolution to visualizations and rendering
- Add --init to docker run commands for proper signal handling on Ctrl+C
- Add .playwright-mcp/ to .gitignore
2026-05-14 02:19:42 +02:00
989bb71497 Add RRIM, Multi-Hillshade RGB, and Local Dominance visualizations
Three new visualizations complementing existing SVF/openness/LRM/MSRM:

- RRIM (Red Relief Image Map): RGB composite combining positive openness
  (R), inverted slope (G), negative openness (B). Uses ray-tracing
  to compute both openness values in a single pass.

- Multi-Hillshade RGB: 3 azimuths (315°, 135°, 45°) mapped to R/G/B
  channels with slope blending. Color reveals structure orientation.

- Local Dominance: (dem - local_min) / (local_max - local_min) using
  min/max filters. Measures local height position — complements openness.

Also adds:
- _compute_openness_both() helper for shared ray-tracing (used by RRIM)
- xp_maximum_filter() in gpu.py (GPU/CPU abstraction)
- Entries in COLORMAPS, RGB_LEGENDS, VIZ_STEPS, and is_rgb detection
- All NaN handling follows existing patterns (nan_mask restoration)
2026-05-14 01:03:47 +02:00
15cd77456d Fix bugs and improve pipeline flexibility
- Fix gpu_cleanup import missing in visualizations.py (NameError in workers)
- Fix t_pdf referenced before assignment when PDF is skipped
- Skip classification+DTM when DTM exists regardless of --force
- --force now only regenerates WebP/PDF, not classification/DTM
- --force-classification forces reclassification when needed
- Add laspy repair fallback for corrupt LAZ files (EVLR errors)
- Keep DTM TIF by default for reuse (--no-keep-tif to delete)
- Increase space between image and bottom cartouche (0.12→0.19)
2026-05-14 00:08:25 +02:00
a1a5078e8b Skip ground classification when DTM already exists
If the DTM .tif exists and --force is not set, skip both ground
classification and DTM generation entirely. Previously, the pipeline
would spend 3+ minutes reclassifying ground even when the DTM was
already present and would be reused anyway.

Also includes: SharedDEM cache, enhanced WebP cartouche (compass rose,
adaptive scale bar, enriched info bar), removed COG/viewer, UTF-8
fix for parallel workers, skip logic for DTM and PDF.
2026-05-13 23:41:21 +02:00
a37b8848ab Interface web cartographique: COG + TiTiler + viewer MapLibre
- Ajout de convert_to_cog() et generate_cog_metadata() dans rendering.py
- Nouveau module viewer.py: génération HTML MapLibre GL JS avec couches et opacité
- Nouveau module server.py: serveur FastAPI avec TiTiler pour tuiles COG
- Pipeline: étapes 5 (COGs) et 6 (viewer web) après le rapport PDF
- CLI: flag --no-viewer pour désactiver la génération du viewer
- run.sh: commande 'serve' pour démarrer le serveur sur port 8000
- Dockerfile: ajout de rio-cogeo, titiler.core, fastapi, uvicorn, piexif
- setup.py: point d'entrée lidar-server
2026-05-10 17:15:37 +02:00
5c155e4999 Layout uniforme WebP: axes fixes + aspect='equal' pour superposition géolocalisée
- Positions d'axes fixes (data_left/bottom/width/height_frac) pour alignement
  pixel-parfait entre terrain et ortho/topo
- aspect='equal' au lieu de 'auto' pour conserver les proportions géographiques
- Colorbar descriptive pour les visualisations RGB (ortho/topo)
- Comblage des petits trous DTM (< 1m) via rasterio.fill.fillnodata
- Suppression de la visualisation "dépressions"
- Hillshade composite: 0.7*hillshade + 0.3*cos(slope)
- D8 flow accumulation accéléré par numba JIT (fallback Python)
- Flag --keep-tif pour conserver les TIFF intermédiaires
- --force supprime aussi les TIF existants avant régénération
- ETA affiché pendant la génération des visualisations
- Répertoires temp dans temp/ pour traitement parallèle
2026-05-10 14:46:31 +02:00
a88e430f02 Audit: corrections de bugs identifiés
- rendering.py: colorbar cassée quand NaN mask actif — créer un
  ScalarMappable avec le cmap sauvegardé au lieu de rely sur
  l'image RGBA qui n'a plus de cmap
- rendering.py: nettoyage du PNG temporaire avec try/finally et
  missing_ok=True pour éviter les fichiers orphelins
- gpu.py: to_gpu() convertit en float32 au lieu de float64 pour
  réduire la consommation mémoire GPU
- dtm.py: utiliser _file_basename() de pipeline.py au lieu de
  dupliquer la logique d'extraction du basename
- pipeline.py: docstring corrigé (18 visualisations, pas 19)
- cli.py: --file supporte aussi les noms sans .copc
  (recherche .copc.laz et .copc.las en plus de .laz et .las)
2026-05-10 12:11:13 +02:00
e73cf75060 Rendu: zones NaN transparentes au lieu d'interpolation DTM
L'interpolation fillnodata du DTM générait des artefacts visuels
(zones lissées artificielles). Revenu au DTM avec NaN conservés.

Nouvelle approche pour le rendu:
- NaN remplacés par la médiane des valeurs valides (valeur neutre)
- Après application de la colormap, un masque alpha rend les zones
  NaN transparentes au lieu de les afficher
- interpolation='bilinear' sur imshow pour un rendu lisse
- Figure adaptative: 20-40 pouces selon la taille des données
- DPI 200 pour les images > 3000px
2026-05-10 11:56:11 +02:00
62038b2d5b Fix crash quand valid_data est vide dans _apply_colormap
np.percentile crash avec IndexError quand valid_data est vide
(TIF entièrement NaN). Ajout d'un guard qui retourne une
colormap par défaut si aucune donnée valide n'existe.
2026-05-10 11:42:21 +02:00
c5e9a60fee Amélioration du rendu: interpolation DTM et affichage haute résolution
- DTM: interpolation des NaN avec rasterio.fill.fillnodata après
  binned_statistic_2d — comble les trous entre les cellules sans données
- Rendering: interpolation='bilinear' sur imshow pour lisser le
  sous-échantillonnage des données haute résolution
- Rendering: fig_width adaptatif (20-40 pouces) selon la taille des données
- Rendering: DPI 200 pour les images > 3000px de large
2026-05-10 11:34:41 +02:00
ba6fb64754 Suppression de la visualisation Texture GLCM
- Suppression de generate_texture() de visualizations.py
- Suppression de l'entrée 'texture' de VIZ_STEPS et COLORMAPS
- Suppression du test TestTexture
- Mise à jour README (19 → 18 visualisations)
- Mise à jour AGENTS.md (17 → 16 fonctions generate_*)
2026-05-10 03:30:07 +02:00
67151c6409 Fix numpy warnings: MaskedArray partition et Mean of empty slice
- Convert MaskedArray to ndarray avant np.percentile() via
  np.asarray(data.compressed()) et np.ma.filled(data, np.nan)
- Supprimer RuntimeWarning "Mean of empty slice" dans MSRM et
  ondelette avec warnings.catch_warnings()
- Ajout import warnings dans visualizations.py
2026-05-10 03:02:36 +02:00
67380d0424 Pipeline LiDAR: classification sol auto + pré-traitement ELM + fix warnings
- Ajout classification automatique du sol (SMRF/PMF/CSF) avec détection
  heuristique (ratio retours uniques > 0.6 → PMF urbain, sinon SMRF)
- Pré-traitement PDAL recommandé avant classification: ELM + outlier
  removal (cell=5.0, threshold=2.0 adapté au calcaire rocailleux)
- Options CLI: --ground-classification {auto,smrf,pmf,csf} et
  --force-classification pour forcer la reclassification
- Fix double logging (logger.propagate = False)
- Fix --force non transmis dans run.sh (réécriture parsing arguments)
- Fix warning numpy 'partition will ignore mask': conversion MaskedArray
  en ndarray avant np.percentile()
- Ajout liblaszip8 + lazrs pour support LAZ dans Docker et laspy
- Tests unitaires pour PMF, CSF et auto-détection
2026-05-10 03:00:33 +02:00
c6d0065eca Fix PDF report: lire WebP via PIL au lieu de matplotlib.imread
matplotlib ne supporte pas WebP. Remplace plt.imread() par
PILImage.open().convert('RGB') dans generate_pdf_report.
2026-05-10 01:06:21 +02:00
e734c9c472 Suppression éclairage solaire, GPU accéléré, --file multi, tests unitaires
- Suppression de generate_solar (éclairage solaire) des visualisations
- Accélération GPU de hillshade, slope, aspect, curvature, depressions,
  anomalies, roughness, texture GLCM, flow (sink filling)
- Nettoyage mémoire GPU entre visualisations (gpu_cleanup)
- Correction OOM texture GLCM: calcul entropie bin par bin au lieu d'un
  tableau 3D massif sur GPU
- Correction bug: xp_minimum_filter manquant dans imports visualizations
- Option --file accepte plusieurs noms complets sans extension
- run.sh affiche l'aide si appelé sans arguments
- Option --test pour exécuter les tests unitaires dans Docker
- Filtre ReturnNumber>=1 intégré dans le pipeline PDAL (plus d'erreur SMRF)
- 60 tests unitaires: GPU, visualisations, rendering, DTM, pipeline, CLI
- Ajout pytest au Dockerfile
2026-05-10 00:57:39 +02:00
405b0d20f8 Refactor pipeline en modules + logging verbose/debug + options CLI
- Découpage du monolithe process_lidar.py (~2750 lignes) en package
  lidar_pipeline/ avec 9 modules (gpu, dtm, visualizations, ign,
  rendering, pipeline, cli, __init__, __main__)
- Logging configurable: -v (verbose avec timestamps) et --debug
  (détails internes fichier:ligne)
- Option --force pour régénérer tous les fichiers (par défaut skip
  les WebP existants)
- Option --file NOM pour traiter un seul fichier LAZ (tests rapides)
- ProcessPoolExecutor avec répertoires temporaires uniques par worker
- Suppression du code mort (geomorphons, hillshade_ne, nodata_mask)
- Aucun fichier TIFF résiduel après conversion WebP
- setup.py pour installation pip, stub process_lidar.py compatible
2026-05-10 00:15:29 +02:00