Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Binary file added data/.DS_Store
Binary file not shown.
59 changes: 59 additions & 0 deletions data/generate_pv_masks.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
import numpy as np
from PIL import Image
from pathlib import Path

def extract_pv_masks(
src_dir: Path,
dst_dir: Path,
pv_class: int = 0,
background_value: int = 255
):
"""
Extract masks that contain PV modules (class 0) and save a cleaned PV-only mask.

Parameters
----------
src_dir : Path
Directory containing original RID superstructure masks.
dst_dir : Path
Output directory for pv-only masks.
pv_class : int, optional
Class index representing PV modules (default: 0).
background_value : int, optional
Value used for non-PV pixels in the output mask (default: 255 for easy visualization).
"""
dst_dir.mkdir(parents=True, exist_ok=True)

mask_files = list(src_dir.glob("*.png"))

print(f"Found {len(mask_files)} masks to inspect...")
count_saved = 0

for mask_path in mask_files:
mask = np.array(Image.open(mask_path))

# Check whether PV class exists
if pv_class not in np.unique(mask):
continue # skip masks without PV

# Create PV-only mask
pv_mask = np.where(mask == pv_class, pv_class, background_value).astype(np.uint8)

# Save to new directory
out_path = dst_dir / mask_path.name
Image.fromarray(pv_mask).save(out_path)
count_saved += 1

print(f"Saved {count_saved} PV-only masks to: {dst_dir}")

if __name__ == "__main__":
BASE_DIR = Path(__file__).resolve().parent
SRC_MASK_DIR = BASE_DIR / "masks_superstructures_reviewed"
DST_PV_MASK_DIR = BASE_DIR / "masks_pv_modules_only"

extract_pv_masks(
src_dir=SRC_MASK_DIR,
dst_dir=DST_PV_MASK_DIR,
pv_class=0,
background_value=255, # white background for visualization
)
85 changes: 85 additions & 0 deletions data/load_rid_data.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
#!/usr/bin/env python3
"""
Minimal setup script for the RID dataset.

Place this script in your `data/` directory and run:

python setup_rid_data_minimal.py

It will:
- rsync ONLY:
- images_roof_centered_geotiff
- masks_superstructures_reviewed
from the TUM server
- download them directly into THIS folder (data/)
- skip downloading if the folder already exists and is non-empty
"""

import subprocess
from pathlib import Path

SERVER = "rsync://m1655470@dataserv.ub.tum.de/m1655470"
BASE_DIR = Path(__file__).resolve().parent # data/
DATA_DIR = BASE_DIR

FOLDERS = [
"images_roof_centered_geotiff",
"masks_superstructures_reviewed",
]


def folder_has_data(path: Path) -> bool:
"""Return True if folder exists and contains at least one file."""
return path.exists() and any(path.iterdir())


def rsync_folder(remote_name: str):
"""Rsync a single folder from the server into DATA_DIR."""
dst = DATA_DIR / remote_name

# Skip if already present and non-empty
if folder_has_data(dst):
print(f"✔ Skipping '{remote_name}' — folder already exists and is not empty.")
return

# Ensure directory exists
dst.mkdir(parents=True, exist_ok=True)

src = f"{SERVER}/{remote_name}/"
cmd = [
"rsync",
"-av",
"--progress",
src,
str(dst) + "/", # ensure trailing slash
]

print(f">>> Downloading '{remote_name}' from server...")
print(" ", " ".join(cmd))
print(">>> You may be asked for the password (m1655470).")

try:
subprocess.run(cmd, check=True)
except FileNotFoundError:
raise SystemExit("ERROR: rsync not found. Please install rsync and try again.")
except subprocess.CalledProcessError as e:
raise SystemExit(f"ERROR: rsync for {remote_name} failed with exit code {e.returncode}.")


def main():
print("=== Minimal RID dataset setup (only 2 folders, with existence check) ===")
print(f"Data directory: {DATA_DIR}")
print()

for folder in FOLDERS:
rsync_folder(folder)
print()

print("=== Done! ===")
print("Folders now present:")
for folder in FOLDERS:
print(" •", DATA_DIR / folder)


if __name__ == "__main__":
main()
Binary file added notebooks/meta_training_loss.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added notebooks/predicted_masks.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
130 changes: 130 additions & 0 deletions notebooks/rid_roof_segments.ipynb

Large diffs are not rendered by default.

442 changes: 317 additions & 125 deletions notebooks/try_few_shot.ipynb

Large diffs are not rendered by default.

225 changes: 191 additions & 34 deletions notebooks/tutorial_few_shot_learning.ipynb

Large diffs are not rendered by default.

Binary file added presentation/figures/Geneva_grid_map.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
163 changes: 163 additions & 0 deletions presentation/tutorial-new-tutorial-group-1-NARRATIVE.qmd
Original file line number Diff line number Diff line change
@@ -0,0 +1,163 @@
---
title: "Few-Shot Learning for Rooftop Detection in Satellite Imagery"
subtitle: "Deep Learning Tutorial"
author: "Giorgio Coppala, Nadine Daum, Elena Dreyer, Nico Reichardt"
bibliography: refs.bib


resources:
- img/**

format:
revealjs:
theme: dimmery.scss
slide-number: true
default-image-width: 70%
preview-links: auto
logo: ""
footer: ""
transition: slide
background-transition: fade
self-contained: true
html-math-method:
method: mathjax
url: https://cdn.jsdelivr.net/npm/mathjax@4/tex-mml-chtml.js
include-in-header: include.html
resources:
- img/**
---


## Policy Relevance

- Many public auhorities face the problem of **limited labeled data**
(annotation is expensive, slow, or requires domain expertise)

- **Applications:**
- medical sector: **rare disease detection**
- emergency management: **flood extent mapping**
- climate & energy: **solar PV rooftop assessment**
- urban planning: **building footprints & infrastructure mapping**

- **Few-shot learning (FSL)** can help:
- Learns to **generalize** from *1–5 labeled support examples per class*
- (in our case) learns a **feature embedding** and constructs **class prototypes**
- Enables segmentation in a **new city** with *minimal additional annotation*



## Problem Setting

::: {.columns}

::: {.column width="55%"}

- Goal of the tutorial: apply **Prototypical Networks** to
rooftop segmentation using only a few labeled tiles

- **Few-shot segmentation** allows the model to learn characteristic
rooftop shapes and textures from a small Geneva subset

- Demonstrates how rooftop maps can be produced for solar potential estimation in a **new geographic setting** with limited labels

:::

::: {.column width="45%"}
![](figures/picture_use_case.png){width="100%" style="margin-top: 1rem;"}

<div style="font-size: 0.75rem; color:#666; text-align:center; margin-top:0.2rem;">
Demonstration use case (self-made visualization)
</div>
:::

:::


## Dataset: [Roofs of Geneva](https://huggingface.co/datasets/raphaelattias/overfitteam-geneva-satellite-images)

- **Size**: 1,050 labeled image-mask pairs

- **Task**: Binary segmentation masks (rooftop vs background)

- **Geographic splits**: 3 grids/ neighborhoods (North, Center, South)

- **Image size**: 250x250 pixels

- **Categories**: Industrial, Residential


## Inside the dataset

<div style="text-align:center;">
![](figures/grids_animation.gif){width="50%"}
</div>

<div style="font-size:0.75rem; text-align:center; color:#666; margin-top:0.5rem;">
Geneva Animation: raw image → overlay rooftop → binary mask
</div>


## Discussion

**Room for improvement:**

- Fine-tune / tweak model parameters
- Add regularization
- Increase number of epochs

- Implement rough approximation of solar potential
- e.g. based on IoU over roof area


**Open for discussion:**

- Try a different encoder ?
- e.g. ResNet-50

- Change train / test split strategy ?
- e.g. random shuffle regardless of geographic regions



<div style="text-align:center; margin-top:3.5em; font-size:1.1em;">
<a href="https://github.com/hertie-data-science-lab/tutorial-new-tutorial-group-1/tree/main"
target="_blank"
style="text-decoration:none;">
GitHub Repo
</a>
</div>



## References

::: {.refs-super-small}

- **Alsentzer, E., Li, M. M., Kobren, S. N., Noori, A., Undiagnosed Diseases Network, Kohane, I. S., & Zitnik, M.** (2025). Few shot learning for phenotype-driven diagnosis of patients with rare genetic diseases. *npj Digital Medicine, 8*(1), 380. https://doi.org/10.1038/s41746-025-01749-1

- **Castello, R., Walch, A., Attias, R., Cadei, R., Jiang, S., & Scartezzini, J.-L.** (2021). Quantification of the suitable rooftop area for solar panel installation from overhead imagery using convolutional neural networks. *Journal of Physics: Conference Series, 2042*(1), 012002. https://doi.org/10.1088/1742-6596/2042/1/012002

- **Chen, Y., Wei, C., Wang, D., Ji, C., & Li, B.** (2022). Semi-supervised contrastive learning for few-shot segmentation of remote sensing images. *Remote Sensing, 14*(17), 4254. https://doi.org/10.3390/rs14174254

- **Ding, H., Zhang, H., & Jiang, X.** (2022). Self-regularized prototypical network for few-shot semantic segmentation. *Pattern Recognition, 132*, 109018. https://doi.org/10.1016/j.patcog.2022.109018

- **Finn, C., Abbeel, P., & Levine, S.** (2017). Model-agnostic meta-learning for fast adaptation of deep networks. In *International Conference on Machine Learning* (pp. 1126–1135). https://doi.org/10.48550/arXiv.1703.03400

- **Ge, Z., Fan, X., Zhang, J., & Jin, S.** (2025). SegPPD-FS: Segmenting plant pests and diseases in the wild using few-shot learning. *Plant Phenomics*, 100121. https://doi.org/10.1016/j.plaphe.2025.100121

- **Hu, Y., Liu, C., Li, Z., Xu, J., Han, Z., & Guo, J.** (2022). Few-shot building footprint shape classification with relation network. *ISPRS International Journal of Geo-Information, 11*(5), 311. https://doi.org/10.3390/ijgi11050311

- **Jadon, S.** (2021). COVID-19 detection from scarce chest X-ray image data using few-shot deep learning. In *Medical Imaging 2021* (pp. 161–170). https://doi.org/10.1117/12.2581496

- **Lee, G. Y., Dam, T., Ferdaus, M. M., Poenar, D. P., & Duong, V.** (2025). Enhancing Few-Shot Classification of Benchmark and Disaster Imagery with ATTBHFA-Net. *arXiv preprint* arXiv:2510.18326. https://doi.org/10.48550/arXiv.2510.18326

- **Li, X., He, Z., Zhang, L., Guo, S., Hu, B., & Guo, K.** (2025). CDCNet: Cross-domain few-shot learning with adaptive representation enhancement. *Pattern Recognition, 162*, 111382. https://doi.org/10.1016/j.patcog.2025.111382

- **Puthumanaillam, G., & Verma, U.** (2023). Texture based prototypical network for few-shot semantic segmentation of forest cover: Generalizing for different geographical regions. *Neurocomputing, 538*, 126201. https://doi.org/10.1016/j.neucom.2023.03.062

- **Snell, J., Swersky, K., & Zemel, R.** (2017). Prototypical networks for few-shot learning. *Advances in Neural Information Processing Systems, 30*. https://doi.org/10.48550/arXiv.1703.05175

- **Sung, F., Yang, Y., Zhang, L., Xiang, T., Torr, P. H., & Hospedales, T. M.** (2018). Learning to compare: Relation network for few-shot learning. In *CVPR* (pp. 1199–1208). https://doi.org/10.1109/CVPR.2018.00131
:::


2 changes: 1 addition & 1 deletion presentation/tutorial-new-tutorial-group-1.qmd
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,9 @@ subtitle: "Deep Learning Tutorial"
author: "Giorgio Coppola, Nadine Daum, Elena Dreyer, Nico Reichardt"
bibliography: refs.bib


resources:
- img/**
- figures/**

format:
revealjs:
Expand Down
15 changes: 15 additions & 0 deletions tutorial-new-tutorial-group-1.Rproj
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
Version: 1.0

RestoreWorkspace: Default
SaveWorkspace: Default
AlwaysSaveHistory: Default

EnableCodeIndexing: Yes
UseSpacesForTab: Yes
NumSpacesForTab: 2
Encoding: UTF-8

RnwWeave: Sweave
LaTeX: pdfLaTeX

BuildType: Makefile
Loading