PV Detection Pipeline
Detects existing photovoltaic (PV) panel installations on building rooftops from aerial orthophoto imagery using vision language models.
Part of the CELINE platform. Complements pv_estimation (which determines PV suitability) by identifying which buildings already have PV installed.
Detection Approach
The pipeline is building-driven: it queries known building footprints from pv_overture_buildings, fetches the corresponding aerial tile, crops each building's rooftop, and classifies it via a vision model.
pv_overture_buildings (Overture Maps, all Trentino)
|
v
Tile Provider (filesystem or WMS)
- Fetch aerial tile covering each building's bbox
- Crop rooftop using building polygon bounds
- Skip edge crops (<50% of building visible in tile)
|
v
Vision Model Detector (Ollama)
- Qwen2.5-VL 7B or similar vision-language model
- Prompt-based binary classification: has PV panels or not
- Outputs: has_pv (bool), confidence (0-1), reasoning (text)
|
v
raw.pv_predictions → dbt staging → silver → gold
- Silver: deduplicated per building (latest detection wins)
- Gold: joined with building geometry, GIST-indexed, GeoJSON
Model configuration
The detector is abstracted behind a Detector interface. The default OllamaDetector is configurable in flows/config.yaml:
- Model: any Ollama vision model (
qwen2.5vl:7b,llava:7b,minicpm-v:8b, etc.) - Host: local or remote Ollama instance
- Prompt: customizable classification prompt
- Threshold: confidence cutoff for positive classification
To swap models, change detector.ollama.model in config. To point to a remote GPU server, change detector.ollama.host. To add a completely different backend (API-based, PANEL CLIP, YOLO), implement a new Detector subclass.
Tile providers
- FilesystemProvider: loads pre-downloaded tiles from
data/tiles/. Each tile has a.jpgimage and.jpg.jsonmetadata sidecar with EPSG:25832 bbox and WGS84 centroid. - WmsProvider: (planned) fetches tiles from WMS endpoint centered on each building.
Phase 2 (planned)
Detection results from Phase 1 bootstrap a labeled dataset for fine-tuning YOLOv8, which replaces the LLM for faster production inference.
Quickstart
cd apps/pv_detection
# Install deps, start Ollama, pull vision model
task setup
# Download reference sample tiles
task download:samples
# Launch the Streamlit viewer (browse tiles, overlay buildings, run detection)
task viewer
Aerial Imagery & AGEA Copyright
Ownership model
All Italian aerial orthophotos at 20cm resolution are produced by AGEA (Agenzia per le Erogazioni in Agricoltura), which retains full copyright. AGEA grants usage rights to Regions and Autonomous Provinces through triennial conventions (Convenzione per la concessione della licenza d'uso dei prodotti aerofotogrammetrici). Each region then sub-licenses to local bodies under its own terms.
"Le ortofoto digitali sono di proprietà dell'Agenzia per le Erogazioni in Agricoltura (AGEA), pertanto l'uso deve sottostare al relativo copyright."
Per-region licensing
The downstream license terms vary significantly by region. The same AGEA 20cm dataset is available under different conditions depending on who publishes it:
| Region / Province | License | Commercial use | Derivatives / ML | Download | Reference |
|---|---|---|---|---|---|
| Provincia Autonoma di Trento | Institutional use only | Prohibited | Prohibited | Prohibited | Condizioni AGEA 2023 |
| Provincia Autonoma di Bolzano | CC BY 4.0 | Allowed | Allowed | Allowed | Ortofoto 2023 Alto Adige |
| Emilia-Romagna | CC BY-NC-ND 3.0 | Prohibited | Prohibited | WMS only | Geoportale ER |
| Sicilia | CC BY-NC-ND 3.0 IT | Prohibited | Prohibited | WMS only | SITR Sicilia |
| Veneto | Visualization only | Prohibited | Prohibited | Prohibited | IDT Veneto |
| Geoportale Nazionale (PCN) | CC BY-NC-ND 3.0 IT | Prohibited | Prohibited | WMS only | PCN |
Implications for this pipeline
For development and training: use the South Tyrol (Bolzano) CC BY 4.0 dataset. Same 20cm AGEA imagery, same building types, fully open for ML training, derivatives, and redistribution with attribution.
WMS: https://geoservices.buergernetz.bz.it/mapproxy/ows
Layer: p_bz-Orthoimagery:Aerial-2023-RGB
CRS: EPSG:25832
For Trentino production: requires formal authorization through the AGEA convention chain
- FBK (Fondazione Bruno Kessler) qualifies as Ente Strumentale of the Provincia Autonoma di Trento
- FBK contacts the Provincia (SIAT / Servizio Catasto) to formalize access
- SPXL (Spindox, CELINE coordinator) requests access through FBK for the declared CELINE project scope
- Scope: PV installation mapping for energy community planning — institutional research activity, not commercial use
Attribution
When using AGEA imagery, all outputs must carry:
Ortofoto 20 cm © 2023 AGEA - Agenzia per le Erogazioni in Agricoltura, Roma (www.agea.gov.it) - TUTTI I DIRITTI RISERVATI
When using South Tyrol CC BY 4.0 imagery:
Ortofoto 2023 - Provincia Autonoma di Bolzano - CC BY 4.0
Project Structure
apps/pv_detection/
├── flows/
│ ├── pipeline.py # Prefect flow
│ ├── providers.py # Tile providers (filesystem, WMS stub)
│ ├── detector.py # Vision model detector (Ollama)
│ └── config.yaml # Pipeline configuration
├── tools/
│ ├── viewer.py # Streamlit tile viewer + detection UI
│ ├── download_tiles.py # WMS tile downloader CLI
│ └── requirements.txt # Python dependencies
├── dbt/
│ └── models/ # staging → silver → gold
├── data/
│ └── tiles/ # Downloaded tiles + metadata + detection cache
├── docker-compose.yaml # Ollama with GPU
├── taskfile.yaml # Task runner commands
└── governance.yaml # Dataset catalog
Task Commands
| Command | Description |
|---|---|
task setup |
Install deps + start Ollama + pull model |
task ollama:up |
Start Ollama container |
task ollama:pull |
Pull/update the vision model |
task viewer |
Launch Streamlit tile viewer |
task download:samples |
Download reference sample tiles |
task download -- [args] |
Download tiles by coords or from DB |
task detect |
Run detection pipeline (Prefect) |
task dbt:run |
Run dbt models |
task dbt:test |
Run dbt tests |