Skip to main content

ASPRS Classification Reference

Comprehensive guide to ASPRS LAS 1.4 classification codes and IGN-specific extensions for French topographic data.


🎯 Overview

This library implements the ASPRS LAS Specification 1.4 classification system with extensions for BD TOPO® integration, providing:

  • Standard ASPRS classes (0-31) - Official LAS 1.4 specification
  • Extended classes (32-255) - Custom classes for BD TOPO® features
  • IGN-specific fixes - Handle non-standard classes (Class 67)
  • Automatic remapping - Convert between classification schemes

Reference: ASPRS LAS 1.4 Specification R15


📊 Standard ASPRS Classes (0-31)

Core Classification Codes

CodeNameDescriptionTypical Use
0Created, Never ClassifiedPoints with no classification appliedInitial state
1UnclassifiedPoints not yet classifiedDefault for unknown
2GroundBare earth surfaceDTM generation
3Low VegetationVegetation < 0.5m heightGrass, low shrubs
4Medium VegetationVegetation 0.5-2.0mBushes, hedges
5High VegetationVegetation > 2.0mTrees, forests
6BuildingBuilding structuresRoofs, walls
7Low Point (Noise)Noise or outliersBelow ground
8ReservedModel Key-point (deprecated)-
9WaterWater surfacesRivers, lakes, sea
10RailRailway tracks and infrastructureTrain lines
11Road SurfaceRoad surfacesStreets, highways
12ReservedWire - Guard (deprecated)-
13Wire - GuardShield wirePower lines
14Wire - ConductorPhase wirePower lines
15Transmission TowerPower transmission structuresPylons
16Wire-structure ConnectorInsulatorsPower lines
17Bridge DeckBridge surfacesElevated structures
18High NoiseNoise or outliersAbove expected
19Overhead StructureElevated non-bridge structuresCanopies
20Ignored GroundBreakline proximityDTM exclusion
21SnowSnow coverSeasonal
22Temporal ExclusionTemporary featuresTime-specific

Reserved Codes

  • 23-31: Reserved for future ASPRS use

🇫🇷 BD TOPO® Extended Classes (32-255)

Road Infrastructure (32-49)

CodeNameBD TOPO® AttributeDescription
32Motorwaynature='Autoroute'Highway/motorway
33Primary Roadnature='Départementale'Main roads
34Secondary Roadnature='Route à 1 chaussée'Secondary roads
35Tertiary Roadnature='Route empierrée'Minor roads
36Residentialnature='Chemin'Residential streets
37Service Roadpos_sol='0'Service roads
38Pedestriannature='Sentier'Pedestrian paths
39Cyclewaynature='Piste cyclable'Bike paths
40Parkingnature='Parking'Parking areas
41Road Bridgepos_sol='1'Elevated roads
42Road Tunnelpos_sol='-1'Underground roads
43Roundaboutnature='Rond-point'Traffic circles

Building Types (50-69)

CodeNameBD TOPO® AttributeDescription
50Residential Buildingnature='Indifférencié'Houses, apartments
51Commercial Buildingnature='Commercial'Shops, offices
52Industrial Buildingnature='Industriel'Factories, warehouses
53Religious Buildingnature='Religieux'Churches, temples
54Public Buildingnature='Administratif'Government buildings
55Agricultural Buildingnature='Agricole'Barns, silos
56Sports Buildingnature='Sportif'Gyms, stadiums
57Historic Buildingnature='Remarquable'Monuments, heritage
58Building Roof-Roof surfaces
59Building Wall-Wall surfaces
60Building Facade-Facade elements
61Chimney-Chimneys
62Balcony-Balconies, terraces

Vegetation Types (70-79)

CodeNameBD TOPO® LayerDescription
70Treezone_de_vegetationIndividual trees
71Bushzone_de_vegetationShrubs, bushes
72Grasszone_de_vegetationGrassland
73Hedgezone_de_vegetationHedgerows
74Forestzone_de_vegetationForest areas
75VineyardRPGVineyards
76OrchardRPGOrchards

Water Features (80-89)

CodeNameBD TOPO® LayerDescription
80Riversurface_hydrographiqueRivers
81Lakesurface_hydrographiqueLakes
82Pondsurface_hydrographiquePonds
83Canalsurface_hydrographiqueCanals
84ReservoirreservoirWater tanks
85Swimming Pool-Pools

Special Features (90-99)

CodeNameBD TOPO® LayerDescription
90CemeterycimetiereCemeteries
91Sports Facilityterrain_de_sportSports grounds
92Power Lineligne_electriquePower line corridors
93Wind Turbine-Wind turbines
94Solar Panel-Solar installations

⚠️ IGN-Specific Issues

Class 67 Fix

Problem: Class 67 appears in some IGN LiDAR HD tiles but is not part of the ASPRS specification.

Solution: Automatically remapped to Class 1 (Unclassified) during preprocessing.

preprocess:
normalize_classification: true # Enable automatic fix
strict_class_normalization: false # Only fix known issues

Impact Example:

Tile: LHD_FXX_0650_6860.laz
- Class 67 points: 4,380 (0.02%)
- Remapped to: Class 1 (Unclassified)
- Status: ✅ Fixed automatically

Known IGN Classes

Original ClassRemapped ToStatusNotes
671 (Unclassified)✅ HandledNon-standard IGN class
641 (Unclassified)✅ HandledRare, non-standard
651 (Unclassified)✅ HandledRare, non-standard

🔄 Classification Mappings

BD TOPO® → ASPRS Mapping

Automatic mapping from BD TOPO® features to ASPRS classes:

BD_TOPO_TO_ASPRS = {
# Buildings
'batiment': 6, # ASPRS Building

# Roads
'troncon_de_route': 11, # ASPRS Road Surface

# Railways
'troncon_de_voie_ferree': 10, # ASPRS Rail

# Water
'surface_hydrographique': 9, # ASPRS Water
'reservoir': 9, # ASPRS Water

# Vegetation
'zone_de_vegetation': 5, # ASPRS High Vegetation

# Infrastructure
'ligne_electrique': 14, # ASPRS Wire - Conductor
'terrain_de_sport': 6, # ASPRS Building
'cimetiere': 6, # ASPRS Building
}

ASPRS → LOD2 Mapping

Conversion from ASPRS to LOD2 building-focused classes:

ASPRS_TO_LOD2 = {
0: 14, # Never classified → other
1: 14, # Unclassified → other
2: 9, # Ground → ground
3: 10, # Low Vegetation → vegetation_low
4: 10, # Medium Vegetation → vegetation_low
5: 11, # High Vegetation → vegetation_high
6: 0, # Building → wall (requires refinement)
7: 10, # Low Point → vegetation_low
9: 12, # Water → water
10: 14, # Rail → other
11: 14, # Road Surface → other
67: 14, # Unknown → other
}

ASPRS → LOD3 Mapping

Conversion from ASPRS to LOD3 detailed building classes:

ASPRS_TO_LOD3 = {
0: 29, # Never classified → other
1: 29, # Unclassified → other
2: 23, # Ground → ground
3: 24, # Low Vegetation → vegetation_low
4: 24, # Medium Vegetation → vegetation_low
5: 25, # High Vegetation → vegetation_high
6: 0, # Building → wall_plain (requires refinement)
7: 24, # Low Point → vegetation_low
9: 26, # Water → water
10: 29, # Rail → other
11: 23, # Road Surface → ground
67: 29, # Unknown → other
}

⚙️ Configuration

Enable ASPRS Classification

# config.yaml (V5)
defaults:
- base/processor
- base/features
- base/data_sources
- base/output
- base/monitoring
- _self_

# Classification mode
classification:
mode: asprs # Use ASPRS classification

# Class normalization
normalize_classes: true
strict_normalization: false # Only fix known issues

# Extended classes
use_extended_classes: true # Enable BD TOPO® extensions (32-255)

# Class-specific parameters
planarity_ground: 0.95
planarity_building: 0.85
planarity_vegetation: 0.5
planarity_road: 0.75

data_sources:
bd_topo:
enabled: true
features:
- buildings # → Class 6
- roads # → Class 11
- railways # → Class 10
- water # → Class 9
- vegetation # → Class 3-5 (by height)
- power_lines # → Class 14

Preset Configuration

# Use ASPRS classification preset
ign-lidar-hd process \
--config-name asprs_classification \
input_dir=data/tiles/ \
output_dir=output/asprs/

💻 Python API

Check Classification Codes

from ign_lidar.asprs_classes import ASPRSClass, ASPRS_CLASS_NAMES
import laspy

# Load tile
las = laspy.read("tile.laz")
classes = las.classification

# Get unique classes
unique_classes = np.unique(classes)
print("Classes found:")
for cls in unique_classes:
name = ASPRS_CLASS_NAMES.get(cls, "Unknown")
count = np.sum(classes == cls)
percent = 100 * count / len(classes)
print(f" {cls:3d}: {name:25s} - {count:8d} pts ({percent:5.2f}%)")

Remap Non-Standard Classes

from ign_lidar.asprs_classes import remap_non_standard_classes

# Fix Class 67 and other non-standard classes
classes_fixed = remap_non_standard_classes(classes)

# Verify fix
assert 67 not in classes_fixed
print(f"Remapped {np.sum(classes == 67)} Class 67 points to Class 1")

Apply BD TOPO® Classification

from ign_lidar.io.wfs_ground_truth import IGNGroundTruthFetcher
from ign_lidar.asprs_classes import BD_TOPO_TO_ASPRS

# Fetch BD TOPO® data
fetcher = IGNGroundTruthFetcher()
ground_truth = fetcher.fetch_all_features(
bbox=tile_bbox,
include_buildings=True,
include_roads=True,
include_water=True
)

# Classify points with ASPRS codes
labels = fetcher.label_points_with_ground_truth(
points=points,
ground_truth_features=ground_truth,
class_mapping=BD_TOPO_TO_ASPRS # Use ASPRS codes
)

# Verify ASPRS compliance
assert all(0 <= cls <= 255 for cls in labels)
print(f"All {len(labels)} points have valid ASPRS classes")

Export Classification Report

from ign_lidar.asprs_classes import generate_classification_report

# Generate detailed report
report = generate_classification_report(
las_file="tile.laz",
output_format="markdown"
)

print(report)

Output:

# Classification Report: tile.laz

## Summary

- Total points: 18,234,567
- Unique classes: 7
- ASPRS compliant: ✅ Yes

## Class Distribution

| Code | Name | Count | Percentage |
| ---- | ----------------- | --------- | ---------- |
| 1 | Unclassified | 668,890 | 3.67% |
| 2 | Ground | 7,982,345 | 43.79% |
| 3 | Low Vegetation | 237,049 | 1.30% |
| 4 | Medium Vegetation | 506,921 | 2.78% |
| 5 | High Vegetation | 6,784,123 | 37.21% |
| 6 | Building | 2,047,207 | 11.23% |
| 9 | Water | 8,032 | 0.04% |

## Issues

- ⚠️ No Class 67 (fixed during preprocessing)

📊 Class Statistics

Typical Distribution in IGN LiDAR HD

Based on analysis of French urban and rural tiles:

ClassUrban AreasRural AreasForest Areas
Ground (2)35-45%45-55%15-25%
Low Veg (3)1-3%3-5%1-2%
Med Veg (4)2-4%4-8%2-4%
High Veg (5)15-25%25-40%60-75%
Building (6)15-25%5-10%1-3%
Road (11)5-10%2-5%0.5-1%
Water (9)0-2%0-5%0-1%

Quality Indicators

Good classification quality:

  • Ground (2): > 30%
  • High Vegetation (5): 10-60% (depends on area)
  • Building (6): 5-30% (urban areas)
  • Unclassified (1): < 5%
  • Noise (7, 18): < 1%

🔍 Validation

Verify ASPRS Compliance

from ign_lidar.asprs_classes import validate_asprs_compliance
import laspy

# Load and validate
las = laspy.read("tile.laz")
is_valid, issues = validate_asprs_compliance(las)

if is_valid:
print("✅ ASPRS LAS 1.4 compliant")
else:
print("❌ Issues found:")
for issue in issues:
print(f" - {issue}")

Check for Non-Standard Classes

# CLI validation
ign-lidar-hd verify \
tile.laz \
--check-asprs-compliance \
--report-non-standard-classes

📚 See Also


💡 Best Practices

  1. Always normalize classes - Enable normalize_classification to fix Class 67
  2. Validate before processing - Check for non-standard classes
  3. Use extended classes wisely - Only when BD TOPO® data is available
  4. Document custom classes - If adding new codes beyond 99
  5. Respect ASPRS spec - Don't overwrite reserved codes (23-31)
  6. Test classification - Verify output with QGIS or CloudCompare
  7. Export metadata - Include class descriptions in output files

Standard: ASPRS LAS 1.4 R15
Updated: October 17, 2025 - V5 Configuration