Correction orientation nord + filtrage ReturnNumber=0 pour fichiers corrompus
- Inversion axe Y du DTM pour orientation nord correcte - Fallback filters.range pour fichiers LAZ avec ReturnNumber=0 - Flèche nord vectorielle noire au-dessus de la légende - 9/9 fichiers traités avec succès Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
99
analyze_and_fix.py
Executable file
99
analyze_and_fix.py
Executable file
@ -0,0 +1,99 @@
|
||||
#!/usr/bin/env python3
|
||||
"""
|
||||
Script pour analyser et corriger les fichiers LAZ avec ReturnNumber=0
|
||||
"""
|
||||
|
||||
import sys
|
||||
import json
|
||||
import subprocess
|
||||
from pathlib import Path
|
||||
|
||||
def analyze_return_numbers(laz_file):
|
||||
"""Analyse les valeurs ReturnNumber dans un fichier LAZ"""
|
||||
print(f"Analyse de {laz_file}...")
|
||||
|
||||
# Pipeline PDAL pour extraire les statistiques ReturnNumber
|
||||
stats_pipeline = [
|
||||
{
|
||||
"type": "readers.las",
|
||||
"filename": str(laz_file)
|
||||
},
|
||||
{
|
||||
"type": "filters.stats",
|
||||
"dimensions": "ReturnNumber,NumberOfReturns"
|
||||
}
|
||||
]
|
||||
|
||||
stats_json = json.dumps(stats_pipeline)
|
||||
stats_file = Path("/tmp/analyze_stats.json")
|
||||
with open(stats_file, 'w') as f:
|
||||
f.write(stats_json)
|
||||
|
||||
result = subprocess.run(['pdal', 'pipeline', str(stats_file)],
|
||||
capture_output=True, text=True)
|
||||
|
||||
if result.returncode == 0:
|
||||
data = json.loads(result.stdout)
|
||||
stats = data.get('stats', {}).get('statistic', [])
|
||||
print(f" Statistiques ReturnNumber:")
|
||||
for stat in stats:
|
||||
if stat.get('name') == 'ReturnNumber':
|
||||
counts = stat.get('counts', {})
|
||||
for val, count in counts.items():
|
||||
if count > 0:
|
||||
pct = count / stat.get('total', 1) * 100
|
||||
print(f" ReturnNumber={val}: {count} points ({pct:.1f}%)")
|
||||
else:
|
||||
print(f" Erreur: {result.stderr}")
|
||||
|
||||
def fix_return_numbers(laz_file, output_file):
|
||||
"""Corrige les valeurs ReturnNumber=0 en utilisant une approche différente"""
|
||||
print(f"Tentative de correction de {laz_file}...")
|
||||
|
||||
# Approche: utiliser filters.python pour modifier les valeurs
|
||||
fix_pipeline = [
|
||||
{
|
||||
"type": "readers.las",
|
||||
"filename": str(laz_file)
|
||||
},
|
||||
{
|
||||
"type": "filters.python",
|
||||
"script": """
|
||||
def filter(ins, args):
|
||||
for point in ins:
|
||||
if point.ReturnNumber == 0:
|
||||
point.ReturnNumber = 1
|
||||
if point.NumberOfReturns == 0:
|
||||
point.NumberOfReturns = 1
|
||||
return True
|
||||
"""
|
||||
},
|
||||
{
|
||||
"type": "writers.las",
|
||||
"filename": str(output_file),
|
||||
"extra_dims": "all"
|
||||
}
|
||||
]
|
||||
|
||||
fix_json = json.dumps(fix_pipeline, indent=2)
|
||||
fix_file = Path("/tmp/fix_pipeline.json")
|
||||
with open(fix_file, 'w') as f:
|
||||
f.write(fix_json)
|
||||
|
||||
result = subprocess.run(['pdal', 'pipeline', str(fix_file)],
|
||||
capture_output=True, text=True)
|
||||
|
||||
if result.returncode == 0:
|
||||
print(f" ✓ Correction réussie: {output_file}")
|
||||
return True
|
||||
else:
|
||||
print(f" ✗ Erreur correction: {result.stderr}")
|
||||
return False
|
||||
|
||||
if __name__ == "__main__":
|
||||
laz_file = sys.argv[1] if len(sys.argv) > 1 else "/data/input/LHD_FXX_1000_6882_PTS_LAMB93_IGN69.copc.laz"
|
||||
|
||||
analyze_return_numbers(laz_file)
|
||||
|
||||
output_file = laz_file.replace(".laz", "_fixed.laz").replace("/input/", "/temp/")
|
||||
fix_return_numbers(laz_file, output_file)
|
||||
Reference in New Issue
Block a user