Architectural Styles
Classification and analysis of French architectural styles using LiDAR data.
Overview
The IGN LiDAR HD dataset enables detailed analysis of architectural styles across French territories, supporting:
- Heritage preservation - Document historical buildings
- Urban planning - Understand architectural patterns
- Cultural mapping - Identify regional variations
- Building classification - Automated style recognition
Style Classification
Traditional French Styles
Haussmann (1853-1870)
Characteristic of central Paris, uniform height and façade organization.
from ign_lidar.styles import HaussmannDetector
detector = HaussmannDetector()
buildings = detector.classify(lidar_data, criteria={
'height_uniformity': 0.9, # Very uniform heights
'facade_alignment': 0.95, # Aligned street facades
'courtyard_ratio': 0.3, # Inner courtyards
'roof_type': 'mansard' # Characteristic roofs
})
Detection Features:
- Consistent building heights (6-7 stories)
- Aligned street frontages
- Internal courtyards
- Mansard roofs with dormers
- Continuous urban fabric
Art Nouveau (1890-1910)
Organic forms, decorative elements, innovative materials.
detector = ArtNouveauDetector()
buildings = detector.classify(lidar_data, criteria={
'facade_complexity': 'high',
'decorative_elements': True,
'asymmetric_composition': True,
'material_diversity': 'iron_glass_stone'
})
Detection Features:
- Irregular rooflines
- Curved architectural elements
- Glass and iron integration
- Asymmetrical compositions
- Ornamental details
Regional Vernacular
Traditional styles specific to French regions.
# Alsatian timber-framed houses
alsatian_config = {
'timber_framing': True,
'steep_roofs': 45, # degrees
'gable_orientation': 'street_facing',
'materials': ['timber', 'stone', 'render']
}
# Norman colombage
norman_config = {
'half_timbered': True,
'thatched_roofs': True,
'irregular_plan': True,
'courtyard_farms': True
}
# Provençal mas
provencal_config = {
'stone_construction': True,
'low_pitch_roofs': 30, # degrees
'tile_covering': 'terracotta',
'thick_walls': True
}
Modern Styles
Art Deco (1920-1939)
Geometric patterns, vertical emphasis, luxury materials.
detector = ArtDecoDetector()
buildings = detector.classify(lidar_data, criteria={
'geometric_patterns': True,
'vertical_emphasis': 'strong',
'setback_terraces': True,
'decorative_cornices': True
})
Modernist/Bauhaus (1920-1960)
Functional design, flat roofs, geometric forms.
detector = ModernistDetector()
buildings = detector.classify(lidar_data, criteria={
'flat_roofs': 0.8, # Mostly flat roofs
'geometric_forms': True,
'minimal_decoration': True,
'large_windows': True,
'white_facades': 0.6 # Often white/light colored
})
Brutalist (1950-1980)
Massive concrete structures, geometric forms.
detector = BrutalistDetector()
buildings = detector.classify(lidar_data, criteria={
'concrete_construction': True,
'massive_forms': True,
'minimal_windows': True,
'geometric_complexity': 'high',
'monumental_scale': True
})
Implementation
Style Detection Pipeline
from ign_lidar import Processor, StyleClassifier
class ArchitecturalAnalyzer:
def __init__(self):
self.processor = Processor()
self.classifier = StyleClassifier()
def analyze_buildings(self, tile_path):
"""Analyze architectural styles in a LiDAR tile."""
# Extract buildings
buildings = self.processor.extract_buildings(tile_path)
# Classify styles
styles = {}
for building_id, building in buildings.items():
style = self.classifier.predict_style(building)
styles[building_id] = style
return styles
def generate_style_map(self, tiles):
"""Generate architectural style map."""
style_map = {}
for tile in tiles:
tile_styles = self.analyze_buildings(tile)
style_map.update(tile_styles)
return self.create_visualization(style_map)
Feature Extraction
def extract_architectural_features(building_points):
"""Extract features relevant to architectural style."""
features = {
# Geometric features
'height': calculate_height(building_points),
'footprint_area': calculate_area(building_points),
'perimeter': calculate_perimeter(building_points),
'compactness': calculate_compactness(building_points),
# Roof features
'roof_type': classify_roof_type(building_points),
'roof_pitch': calculate_roof_pitch(building_points),
'roof_complexity': measure_roof_complexity(building_points),
# Facade features
'facade_complexity': analyze_facade(building_points),
'window_patterns': detect_openings(building_points),
'setbacks': detect_setbacks(building_points),
# Context features
'urban_context': analyze_context(building_points),
'alignment': check_street_alignment(building_points),
'density': calculate_local_density(building_points)
}
return features
Machine Learning Classification
from sklearn.ensemble import RandomForestClassifier
import numpy as np
class StyleClassifier:
def __init__(self):
self.model = RandomForestClassifier(
n_estimators=100,
random_state=42
)
self.feature_names = [
'height', 'area', 'compactness', 'roof_pitch',
'facade_complexity', 'window_regularity', 'setback_count'
]
def train(self, training_data):
"""Train the style classifier."""
features = []
labels = []
for building, style in training_data:
feature_vector = self.extract_features(building)
features.append(feature_vector)
labels.append(style)
X = np.array(features)
y = np.array(labels)
self.model.fit(X, y)
def predict_style(self, building):
"""Predict architectural style."""
features = self.extract_features(building)
style = self.model.predict([features])[0]
confidence = self.model.predict_proba([features]).max()
return {
'style': style,
'confidence': confidence,
'features': features
}
Regional Variations
Northern France
northern_styles = {
'flemish_baroque': {
'gabled_facades': True,
'brick_construction': True,
'ornate_details': True
},
'picard_traditional': {
'timber_framing': True,
'brick_infill': True,
'steep_roofs': True
}
}
Central France
central_styles = {
'loire_renaissance': {
'stone_construction': True,
'decorative_turrets': True,
'formal_gardens': True
},
'berry_vernacular': {
'limestone_walls': True,
'slate_roofs': True,
'agricultural_buildings': True
}
}
Southern France
southern_styles = {
'mediterranean': {
'flat_roofs': True,
'tile_roofs': True,
'stone_construction': True,
'courtyards': True
},
'basque': {
'timber_framing': True,
'white_walls': True,
'red_tile_roofs': True,
'mountain_adaptation': True
}
}
Validation and Quality Control
Ground Truth Comparison
def validate_classification(predictions, ground_truth):
"""Validate architectural style predictions."""
accuracy_metrics = {
'overall_accuracy': calculate_accuracy(predictions, ground_truth),
'style_precision': calculate_precision_by_style(predictions, ground_truth),
'style_recall': calculate_recall_by_style(predictions, ground_truth),
'confusion_matrix': create_confusion_matrix(predictions, ground_truth)
}
return accuracy_metrics
Expert Validation
def expert_review_pipeline(classified_buildings):
"""Submit classifications for expert review."""
# Prioritize uncertain classifications
uncertain = filter_by_confidence(classified_buildings, threshold=0.7)
# Generate review materials
review_package = {
'building_images': generate_building_views(uncertain),
'feature_summaries': create_feature_summaries(uncertain),
'context_maps': create_context_visualizations(uncertain)
}
return review_package
Applications
Heritage Documentation
def heritage_survey(region_tiles):
"""Survey heritage buildings in region."""
analyzer = ArchitecturalAnalyzer()
heritage_buildings = []
for tile in region_tiles:
styles = analyzer.analyze_buildings(tile)
# Identify heritage styles
heritage = {
building_id: style
for building_id, style in styles.items()
if style['style'] in HERITAGE_STYLES and
style['confidence'] > 0.8
}
heritage_buildings.extend(heritage)
return create_heritage_database(heritage_buildings)
Urban Evolution Analysis
def analyze_urban_evolution(historical_tiles):
"""Analyze architectural evolution over time."""
evolution_data = {}
for year, tiles in historical_tiles.items():
styles = analyze_architectural_styles(tiles)
evolution_data[year] = aggregate_style_statistics(styles)
trends = {
'style_progression': track_style_changes(evolution_data),
'densification_patterns': analyze_density_changes(evolution_data),
'preservation_status': assess_heritage_preservation(evolution_data)
}
return trends
Planning Support
def architectural_planning_analysis(planning_zone):
"""Support urban planning with architectural analysis."""
current_styles = analyze_existing_architecture(planning_zone)
recommendations = {
'compatible_styles': suggest_compatible_styles(current_styles),
'height_guidelines': recommend_height_limits(current_styles),
'density_limits': calculate_appropriate_density(current_styles),
'preservation_priorities': identify_preservation_candidates(current_styles)
}
return recommendations
Integration with Other Systems
QGIS Integration
def export_to_qgis(style_classifications):
"""Export style data to QGIS."""
# Create styled layer
layer = create_vector_layer(style_classifications)
# Apply style-based symbology
apply_architectural_styling(layer)
# Add attribute data
add_style_attributes(layer, style_classifications)
return layer
Database Integration
def store_architectural_data(classifications, database_connection):
"""Store classifications in heritage database."""
for building_id, classification in classifications.items():
record = {
'building_id': building_id,
'architectural_style': classification['style'],
'confidence': classification['confidence'],
'period': classification.get('period'),
'regional_variant': classification.get('variant'),
'conservation_status': assess_conservation_status(classification)
}
database_connection.insert_architectural_record(record)
Best Practices
Classification Guidelines
- Multi-scale Analysis: Consider building, block, and neighborhood scales
- Temporal Context: Account for construction periods and modifications
- Regional Adaptation: Adjust criteria for regional variations
- Expert Validation: Incorporate architectural expert knowledge
- Continuous Learning: Update models with new training data
Quality Assurance
- Cross-validation: Test on independent datasets
- Confidence Thresholds: Set appropriate confidence levels
- Manual Review: Review uncertain classifications
- Documentation: Maintain detailed classification rationale
- Version Control: Track model and criteria versions