91.9 mIoU on Sen1Floods11 from Sentinel-2 alone, tying the best published result (an unreleased Sentinel-1+2 TerraMind-Tiny variant), and 89.7 mIoU on the held-out Bolivia split, above the best published result (Prithvi-CAFE, 88.9).
Introduction
Blue Marble Flood is a family of five flood and surface-water segmentation models for Sentinel-2 imagery, from 32k to 13.5M parameters. Every model is under 15M parameters and runs fully in int8 on the Qualcomm Dragonwing QCS8275 NPU (Arduino VENTUNO Q).

Highlights
- 91.9 mIoU on Sen1Floods11 test with Blue Marble nano (0.19M parameters, released checkpoint); best published model under 15M: 91.9, TerraMind-Tiny, patch 4 (unreleased; S1+S2).
- 89.7 mIoU on Sen1Floods11 Bolivia (held-out) with Blue Marble nano (0.19M parameters, released checkpoint); best published model under 15M: 83.0, Segformer-B0 (3.7M); best published of any size: 88.9, Prithvi-CAFE (frozen Prithvi 2.0 600M backbone).
- 3.4 ms per 512x512 tile (nano) on the Arduino VENTUNO Q NPU, int8, every layer on the NPU.
Model Downloads
| Model | Params | int8 size | VENTUNO Q latency | Ops on NPU | Sen1Floods11 test: fp32 / int8 | Download |
|---|---|---|---|---|---|---|
| Blue-Marble-Flood-pico | 0.032M | 0.14 MB | 2.8 ms | 61/61 | 91.0 / 90.9 | pico/ |
| Blue-Marble-Flood-nano | 0.19M | 0.36 MB | 3.4 ms | 75/75 | 91.9 / 91.8 | nano/ |
| Blue-Marble-Flood-tiny | 1.26M | 1.62 MB | 4.5 ms | 116/116 | 90.9 / 90.7 | tiny/ |
| Blue-Marble-Flood-small | 2.4M | 2.86 MB | 5.2 ms | 129/129 | 90.2 / 90.1 | small/ |
| Blue-Marble-Flood-medium | 13.5M | 14.58 MB | 10.1 ms | 223/223 | 91.0 / 90.8 | medium/ |
Each size folder contains:
| File | Use |
|---|---|
model_qcs8275.dlc |
Compiled for the Qualcomm QCS8275 NPU (QNN runtime): runs as-is on the Arduino VENTUNO Q |
model_int8.onnx |
int8 ONNX, the source of the compiled model; ONNX Runtime or your own NPU toolchain |
model_fp32.onnx |
Full precision ONNX (CPU / GPU); the scores below are for this model |
model.safetensors + config.json |
PyTorch weights for fine-tuning, with models.py in this repository |
ventuno_q_profile.json |
On-device profile on the Arduino VENTUNO Q (Qualcomm AI Hub): the compute unit of every op, total latency, memory, load times |
Scores in this table are for the exact files in this repository, re-scored on the full official Sen1Floods11 test split (90 chips) and the Bolivia hold-out (15 chips). Latency and ops on NPU: on-device profile of model_qcs8275.dlc on an Arduino VENTUNO Q (Qualcomm AI Hub).
Evaluation Results
Models under 15M parameters
| Model | Params | Sen1Floods11 test (mIoU) | Sen1Floods11 Bolivia (held-out) (mIoU) | Water-2026 (mIoU) | STURM-Flood (mIoU) |
|---|---|---|---|---|---|
| Blue Marble pico | 0.032M | 91.0 | 87.7 | 86.0 ± 0.8 | 76.7 ± 0.3 |
| Blue Marble nano | 0.19M | 91.9 | 89.7 | 85.2 ± 0.9 | 77.2 ± 0.3 |
| Blue Marble tiny | 1.26M | 90.9 | 89.7 | 88.0 ± 0.7 | 77.6 ± 0.3 |
| Blue Marble small | 2.4M | 90.2 | 88.1 | 87.7 ± 0.3 | 76.4 ± 0.1 |
| Blue Marble medium | 13.5M | 91.0 | 89.2 | 87.3 ± 0.2 | 77.0 ± 0.2 |
| PANGAEA UNet (S1+S2) | 14.8M | 91.4 | - | - | - |
| Segformer-B0 | 3.7M | 89.4 | 83.0 | - | - |
| EfficientViT-B0 | 0.7M | 87.7 | - | - | - |
| TerraMind-Tiny, patch 4 (unreleased; S1+S2) | Tiny (count not published) | 91.9 | - | - | - |
| TerraMind-Tiny (S1+S2) | Tiny (count not published) | 90.2 | - | - | - |
| THOR-Tiny (S1+S2) | 7.6M | 90.2 | - | - | - |
| TerraMind-v1-tiny* | 6.1M | 88.4 | 88.4 | 88.2 | 77.2 |
| MobileNetV4-S* | 0.41M | 90.3 | 81.9 | 69.2 | 75.9 |
Reference: larger models
| Model | Params | Sen1Floods11 test (mIoU) | Sen1Floods11 Bolivia (held-out) (mIoU) | Water-2026 (mIoU) | STURM-Flood (mIoU) |
|---|---|---|---|---|---|
| TerraMind TiM | not disclosed | 91.1 | - | - | - |
| SpectralEarth-FM-a | not disclosed | 91.1 | - | - | - |
| Prithvi-CAFE (frozen Prithvi 2.0 600M backbone) | 45.5M trainable | 90.5 | 88.9 | - | - |
| Prithvi 2.0 300M + LoRA (frozen backbone) | 5.5M trainable | 90.0 | 87.6 | - | - |
| U-Prithvi | not disclosed | 89.7 | 87.7 | - | - |
| DeCUR, full fine-tuning | 25M | 86.9 | 85.8 | - | - |
| TerraMind-v1-small* | 22.9M | 88.0 | 88.7 | 89.5 | 77.3 |
Blue Marble, public benchmarks: score of the released checkpoint in this repository (re-scored from these files). Blue Marble, our own benchmarks: mean ± std over 3 training runs. Other models: published numbers, with inputs noted where they differ from ours (our models use Sentinel-2 only); * = trained and evaluated by us on the same data and split (parameter count includes our decoder). Best per column among models under 15M in bold. Water-2026: our held-out Sentinel-2 scenes from 2025-2026 with JRC water labels. STURM-Flood: public Sentinel-2 flood dataset (CC BY 4.0), scored zero-shot (no STURM data in training); it is surface reflectance with 9 bands, the others set to 0. Water-2026 and STURM-Flood were also used to choose between training recipes that tied on validation, so they are not untouched test sets and are not bolded.



Quickstart
import numpy as np, onnxruntime as ort
MEAN = np.array([2357.089, 2137.385, 2018.788, 2082.986, 2295.651, 2854.537, 3122.849, 3040.560, 3306.481, 1473.847, 506.070, 2472.825, 1838.929], np.float32)[:, None, None]
STD = np.array([1624.683, 1675.806, 1557.708, 1833.702, 1823.738, 1733.977, 1732.131, 1679.732, 1727.26, 1024.687, 442.165, 1331.411, 1160.419], np.float32)[:, None, None]
def prepare(dn): # dn: Sentinel-2 L1C digital numbers, [13, H, W], H and W multiples of 16
dn = np.clip(dn - 1000, 0, None) # only for products from 2022 on (processing baseline 04.00+)
return ((dn - MEAN) / STD)[None].astype(np.float32)
sess = ort.InferenceSession("tiny/model_int8.onnx")
out = sess.run(None, {"image": prepare(dn)})[0]
PyTorch:
import json, torch
from safetensors.torch import load_file
from models import BlueMarble # models.py from this repository
cfg = json.load(open("tiny/config.json"))
model = BlueMarble(cfg["arch"], cfg["num_classes"]).eval()
model.load_state_dict(load_file("tiny/model.safetensors"))
- Input: 13 Sentinel-2 L1C bands, B01 to B12 including B8A and B10. Missing bands (other sensors): set to 0 after normalisation.
- Output:
[1, 2, H, W]logits: 0 land, 1 water.
Reproduce
evaluate.py re-scores any model file in this repository on the public benchmark; the data is downloaded on the first run.
pip install numpy onnxruntime rasterio huggingface_hub
python evaluate.py --model nano/model_fp32.onnx # or nano/model_int8.onnx
Expected mIoU for nano/: test 91.92 (fp32) / 91.79 (int8); Bolivia 89.70 (fp32) / 89.72 (int8).
License
Apache-2.0. Contains modified Copernicus Sentinel data.
Citation
@misc{bluemarble2026,
title = {Blue Marble: Edge Earth Observation Models},
author = {Harsh Kumar},
year = {2026},
url = {https://huggingface.co/Civimatica}
}