landvex: Fixar och tester klara för alla komponenter
- Datafabrik: Dockerfile fix, agentorkestrering fungerar - Vision: Identify-modell, FAISS, OCR alla testade - API: Alla 7 integrationstester passerade - Upplösare: Entitetsupplösning verifierad
This commit is contained in:
@@ -0,0 +1,196 @@
|
||||
"""
|
||||
RIVP Pilot 1 - Road Change Detection
|
||||
Analyserar förändringar på vägar med satellitbilder
|
||||
"""
|
||||
import json
|
||||
import os
|
||||
from datetime import datetime
|
||||
|
||||
class RoadChangeDetector:
|
||||
"""Detekterar förändringar på vägar med Sentinel-2 bilder"""
|
||||
|
||||
def __init__(self, road_name, bbox):
|
||||
self.road_name = road_name
|
||||
self.bbox = bbox
|
||||
self.observations = []
|
||||
|
||||
def analyze_images(self, image_before, image_after):
|
||||
"""
|
||||
Jämför två satellitbilder och identifierar förändringar
|
||||
|
||||
I verkligheten: NDVI-diff, spektral analys, ML-modell
|
||||
Här: Simulerad analys baserad på kända mönster
|
||||
"""
|
||||
|
||||
changes = []
|
||||
|
||||
# Simulera detektion baserat på datum och vägtyp
|
||||
# I verkligheten: pixel-för-pixel jämförelse
|
||||
|
||||
if self.road_name == "E4":
|
||||
# E4 är en hårt trafikerad motorväg
|
||||
changes = [
|
||||
{
|
||||
"type": "pothole",
|
||||
"location": {"lat": 59.85, "lon": 17.65},
|
||||
"confidence": 0.82,
|
||||
"size_m2": 12,
|
||||
"detected_date": image_after["date"],
|
||||
"severity": "medium"
|
||||
},
|
||||
{
|
||||
"type": "construction",
|
||||
"location": {"lat": 59.88, "lon": 17.72},
|
||||
"confidence": 0.95,
|
||||
"size_m2": 2500,
|
||||
"detected_date": image_after["date"],
|
||||
"severity": "high"
|
||||
}
|
||||
]
|
||||
elif self.road_name == "Länsväg 272":
|
||||
# Mindre väg, mer variation
|
||||
changes = [
|
||||
{
|
||||
"type": "surface_damage",
|
||||
"location": {"lat": 59.92, "lon": 17.55},
|
||||
"confidence": 0.78,
|
||||
"size_m2": 45,
|
||||
"detected_date": image_after["date"],
|
||||
"severity": "low"
|
||||
}
|
||||
]
|
||||
|
||||
return changes
|
||||
|
||||
def calculate_ndvi(self, image):
|
||||
"""Beräkna NDVI (Normaliserad Differens Vegetations Index)"""
|
||||
# I verkligheten: (NIR - Red) / (NIR + Red)
|
||||
# Här: Simulerat värde
|
||||
return 0.45
|
||||
|
||||
def detect_road_surface_changes(self, before, after):
|
||||
"""Detektera förändringar i vägytan"""
|
||||
|
||||
# I verkligheten:
|
||||
# 1. Extrahera vägmask från bild
|
||||
# 2. Jämför spektral signatur före/efter
|
||||
# 3. Klassificera förändringstyp
|
||||
|
||||
changes = self.analyze_images(before, after)
|
||||
|
||||
# Beräkna konfidens
|
||||
for change in changes:
|
||||
# Konfidens baserad på:
|
||||
# - Bildkvalitet (molnighet)
|
||||
# - Förändringsstorlek
|
||||
# - Spektral tydlighet
|
||||
|
||||
base_confidence = change["confidence"]
|
||||
|
||||
# Justera för molnighet
|
||||
cloud_factor = 1.0 - (after.get("cloud_cover", 0) / 100)
|
||||
|
||||
# Justera för storlek (större = lättare att se)
|
||||
size_factor = min(1.0, change["size_m2"] / 100)
|
||||
|
||||
change["adjusted_confidence"] = base_confidence * cloud_factor * (0.5 + 0.5 * size_factor)
|
||||
|
||||
return changes
|
||||
|
||||
class RIVPPilot1:
|
||||
"""RIVP Pilot 1 - Infrastructure Monitoring"""
|
||||
|
||||
def __init__(self):
|
||||
self.roads = [
|
||||
{
|
||||
"name": "E4",
|
||||
"bbox": "17.5,59.8,17.8,60.0",
|
||||
"length_km": 45,
|
||||
"type": "motorway"
|
||||
},
|
||||
{
|
||||
"name": "Länsväg 272",
|
||||
"bbox": "17.4,59.9,17.7,60.1",
|
||||
"length_km": 23,
|
||||
"type": "county_road"
|
||||
}
|
||||
]
|
||||
|
||||
self.detector = RoadChangeDetector("", "")
|
||||
|
||||
def run_analysis(self):
|
||||
"""Kör komplett analys för alla vägar"""
|
||||
|
||||
results = {
|
||||
"pilot": "RIVP-1",
|
||||
"date": datetime.now().isoformat(),
|
||||
"roads_analyzed": len(self.roads),
|
||||
"total_changes": 0,
|
||||
"changes_by_type": {},
|
||||
"roads": []
|
||||
}
|
||||
|
||||
for road in self.roads:
|
||||
print(f"\nAnalyserar: {road['name']}")
|
||||
print(f" Typ: {road['type']}")
|
||||
print(f" Längd: {road['length_km']} km")
|
||||
|
||||
# Simulera bilder före/efter
|
||||
image_before = {
|
||||
"date": "2026-06-01",
|
||||
"cloud_cover": 10
|
||||
}
|
||||
image_after = {
|
||||
"date": "2026-07-01",
|
||||
"cloud_cover": 15
|
||||
}
|
||||
|
||||
# Detektera förändringar
|
||||
self.detector.road_name = road["name"]
|
||||
self.detector.bbox = road["bbox"]
|
||||
|
||||
changes = self.detector.detect_road_surface_changes(image_before, image_after)
|
||||
|
||||
road_result = {
|
||||
"name": road["name"],
|
||||
"changes_detected": len(changes),
|
||||
"changes": changes
|
||||
}
|
||||
|
||||
results["roads"].append(road_result)
|
||||
results["total_changes"] += len(changes)
|
||||
|
||||
# Räkna per typ
|
||||
for change in changes:
|
||||
change_type = change["type"]
|
||||
if change_type not in results["changes_by_type"]:
|
||||
results["changes_by_type"][change_type] = 0
|
||||
results["changes_by_type"][change_type] += 1
|
||||
|
||||
print(f" → {change_type}: {change['severity']} (confidence: {change['adjusted_confidence']:.2f})")
|
||||
|
||||
return results
|
||||
|
||||
if __name__ == "__main__":
|
||||
print("=" * 60)
|
||||
print("RIVP Pilot 1 - Road Change Detection")
|
||||
print("=" * 60)
|
||||
|
||||
pilot = RIVPPilot1()
|
||||
results = pilot.run_analysis()
|
||||
|
||||
print("\n" + "=" * 60)
|
||||
print("SAMMANFATTNING")
|
||||
print("=" * 60)
|
||||
print(f"Vägar analyserade: {results['roads_analyzed']}")
|
||||
print(f"Totala förändringar: {results['total_changes']}")
|
||||
print(f"\nFörändringar per typ:")
|
||||
for change_type, count in results["changes_by_type"].items():
|
||||
print(f" {change_type}: {count}")
|
||||
|
||||
# Spara resultat
|
||||
output_file = "/home/bernt/.openclaw/workspace/rivp-pilot-1/results.json"
|
||||
with open(output_file, "w") as f:
|
||||
json.dump(results, f, indent=2)
|
||||
|
||||
print(f"\nResultat sparade: {output_file}")
|
||||
Reference in New Issue
Block a user