Blue Marble Clouds

License Sizes Device Params

74.1 mIoU on the official CloudSEN12+ L1C test split: above published models under 15M parameters on that split (best: FEMNet, 4.4M, 71.8) and on par with Cloud-Adapter (~300M parameters, 74.2).

Introduction

Blue Marble Clouds is a family of five cloud and cloud-shadow 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

  • 74.1 mIoU on CloudSEN12 test (4-class) with Blue Marble medium (13.5M parameters, released checkpoint); best published model under 15M: 71.8, FEMNet (4.4M); best published of any size: 74.2, Cloud-Adapter.
  • 4.8 ms per 512x512 tile (tiny) on the Arduino VENTUNO Q NPU, int8, every layer on the NPU.

Model Downloads

Model Params int8 size VENTUNO Q latency Ops on NPU CloudSEN12 test (4-class): fp32 / int8 Download
Blue-Marble-Clouds-pico 0.032M 0.14 MB 3.0 ms 61/61 66.4 / 65.8 pico/
Blue-Marble-Clouds-nano 0.19M 0.36 MB 3.7 ms 75/75 70.8 / 69.7 nano/
Blue-Marble-Clouds-tiny 1.26M 1.62 MB 4.8 ms 116/116 73.2 / 72.8 tiny/
Blue-Marble-Clouds-small 2.4M 2.86 MB 5.5 ms 129/129 73.9 / 73.2 small/
Blue-Marble-Clouds-medium 13.5M 14.58 MB 10.7 ms 223/223 74.1 / 73.7 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 CloudSEN12+ L1C high-quality test split (975 images). 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 CloudSEN12 test (4-class) (mIoU) Landsat-8 Biome (zero-shot) (cloud F1)
Blue Marble pico 0.032M 66.4 89.3 ± 0.5
Blue Marble nano 0.19M 70.8 89.6 ± 0.1
Blue Marble tiny 1.26M 73.2 91.1 ± 1.0
Blue Marble small 2.4M 73.9 88.6 ± 0.1
Blue Marble medium 13.5M 74.1 91.2 ± 0.6
UNetMobV2 6.6M 71.7 -
FEMNet 4.4M 71.8 -
SCTNet 0.7M 71.2 -
SegMAN 7.4M 70.8 -
UNetMobV2, released checkpoint* 6.63M 72.2 73.2
TerraMind-v1-tiny* 6.1M 72.2 87.9
MobileNetV4-S* 0.41M 66.5 80.7

Reference: larger models

Model Params CloudSEN12 test (4-class) (mIoU) Landsat-8 Biome (zero-shot) (cloud F1)
Cloud-Adapter 300M 74.2 -
TerraMind-v1-small* 22.9M 72.8 86.8

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. All CloudSEN12 numbers are on the official high-quality L1C split (8,490 / 535 / 975). Landsat-8 Biome was also used to choose between training recipes, so it is not an untouched test set and is 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, 4, H, W] logits: 0 clear, 1 thick cloud, 2 thin cloud, 3 cloud shadow.

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 medium/model_fp32.onnx      # or medium/model_int8.onnx

Expected mIoU for medium/: test 74.07 (fp32) / 73.73 (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}
}
Downloads last month

-

Downloads are not tracked for this model. How to track
Inference Providers NEW
This model isn't deployed by any Inference Provider. 🙋 Ask for provider support

Collection including Civimatica/blue-marble-clouds