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 Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@ -131,13 +131,19 @@ Exemples:
|
||||
parser.add_argument(
|
||||
"--quality",
|
||||
type=int,
|
||||
default=85,
|
||||
help="Qualité WebP (1-100, défaut: 85). Utilisez 100 pour lossless."
|
||||
default=98,
|
||||
help="Qualité image (1-100, défaut: 98). Utilisez 100 pour lossless."
|
||||
)
|
||||
parser.add_argument(
|
||||
"--lossless",
|
||||
action="store_true",
|
||||
help="Forcer la compression WebP lossless (équivalent à --quality 100)"
|
||||
help="Forcer la compression lossless (équivalent à --quality 100)"
|
||||
)
|
||||
parser.add_argument(
|
||||
"--format",
|
||||
choices=["webp", "avif"],
|
||||
default="avif",
|
||||
help="Format de sortie : avif (défaut, meilleure qualité) ou webp"
|
||||
)
|
||||
parser.add_argument(
|
||||
"--only",
|
||||
@ -194,6 +200,13 @@ Exemples:
|
||||
|
||||
try:
|
||||
quality = 100 if args.lossless else args.quality
|
||||
# Parse --only and --skip: accept comma-separated values
|
||||
only_viz = None
|
||||
if args.only:
|
||||
only_viz = [v.strip() for item in args.only for v in item.split(',')]
|
||||
skip_viz = None
|
||||
if args.skip:
|
||||
skip_viz = [v.strip() for item in args.skip for v in item.split(',')]
|
||||
pipeline = LidarArchaeoPipeline(
|
||||
input_dir=args.input,
|
||||
output_dir=args.output,
|
||||
@ -204,8 +217,9 @@ Exemples:
|
||||
force_classify=args.force_classification,
|
||||
keep_tif=args.keep_tif,
|
||||
quality=quality,
|
||||
only_viz=args.only,
|
||||
skip_viz=args.skip,
|
||||
only_viz=only_viz,
|
||||
skip_viz=skip_viz,
|
||||
output_format=args.format,
|
||||
)
|
||||
|
||||
# If --file is specified, process only matching files
|
||||
@ -270,9 +284,15 @@ def _kill_orphan_pdal(signum=None, frame=None):
|
||||
"""Kill orphan PDAL processes on interrupt or exit."""
|
||||
import subprocess
|
||||
try:
|
||||
subprocess.run(["pkill", "-f", "pdal"], capture_output=True, timeout=5)
|
||||
subprocess.run(["pkill", "-9", "-f", "pdal"], capture_output=True, timeout=3)
|
||||
except Exception:
|
||||
pass
|
||||
if signum is not None:
|
||||
logger.info("Interruption — nettoyage des processus PDAL")
|
||||
logger.info("Interruption — nettoyage des processus")
|
||||
# Force-kill all child processes immediately
|
||||
try:
|
||||
import os
|
||||
os.killpg(os.getpgrp(), signal.SIGKILL)
|
||||
except Exception:
|
||||
pass
|
||||
sys.exit(130)
|
||||
Reference in New Issue
Block a user