Skip to main content

btt_cloud_mask_example

Reference cloud masks for satellite images, so you can check how well your cloud-detection model does.

The images come from Maxar Open Data: very high resolution (about 0.3–3.5 m) imagery of natural disasters, published as a free STAC catalog. The masks come from pretrained cloud models, OmniCloudMask by default.

Install

pip install btt_cloud_mask_example

This includes OmniCloudMask. Two more models are optional:

pip install "btt_cloud_mask_example[all]"     # adds ukis-csmask and CloudSEN12

The first mask you make downloads OmniCloudMask's model weights (about 55 MB).

Quickstart

Everything comes back as plain numpy arrays plus a rasterio profile (a dict with the map projection, pixel size and so on), so it works with numpy, matplotlib and rasterio as usual.

import btt_cloud_mask_example as bcm
import matplotlib.pyplot as plt

# 1. Find some cloudy images from a disaster event
urls = bcm.find_images("Hurricane-Ian-9-26-2022", n=3, min_cloud=20)

# 2. Load an image: reflectance values from 0 to 1, shaped (bands, height, width)
data, profile = bcm.load_image(urls[0])      # bands, in order: red, green, blue, nir
data.shape                                   # e.g. (4, 2868, 2868)
plt.imshow(bcm.rgb(data))                    # bcm.rgb makes a viewable colour picture

# 3. Make a reference cloud mask for the same image
mask, mask_profile = bcm.create_mask(urls[0])
valid = mask != 0                            # ignore the empty edges
(mask[valid] == 2).mean()                    # e.g. 0.37: share of the image that is cloud
plt.imshow(mask, vmin=0, vmax=3)

# 4. Compare your model's prediction against the reference
my_prediction = my_model(data)               # True/False, 0/1 or probabilities, shaped (height, width)
bcm.compare(my_prediction, mask)
# e.g. {'iou': 0.71, 'precision': 0.93, 'recall': 0.75, 'f1': 0.83, 'accuracy': 0.91, ...}

load_image and create_mask use the same pixel grid, so data[:, y, x] and mask[y, x] are the same spot on the ground.

What's in a mask

mask is a numpy array with one number per pixel (also available as bcm.CLASSES):

Value Meaning
0 no data (the empty edges of an image)
1 clear
2 cloud
3 cloud shadow

mask == 2 gives a True/False array of just the cloud. To save a GeoTIFF that opens in QGIS, use the profile with rasterio (or pass save_to="mask.tif" to create_mask):

import rasterio

with rasterio.open("mask.tif", "w", **mask_profile) as f:
    f.write(mask, 1)

Useful options

urls = bcm.find_images(event, n=10, min_cloud=10, max_cloud=60, sensors=["WV02", "WV03"])
data, profile = bcm.load_image(url, bands=["red", "green", "blue", "nir", "rededge"])  # pick bands
data, profile = bcm.load_image(url, resolution=10)   # resample to 10 m pixels (smaller, faster)
mask, profile = bcm.create_mask(url, resolution=10)  # ...and a mask on the same 10 m grid
mask, profile = bcm.create_mask(url, model="ukis")   # another model, for comparison
mask, profile = bcm.create_mask(url, save_to="masks/one.tif")

Event names (like Hurricane-Ian-9-26-2022) are listed in the catalog browser. You can also pass a link copied from the browser straight into load_image or create_mask.

Bands

Name WorldView-2/3 (WV02, WV03) GeoEye-1 (GE01), WorldView-4 (WV04)
coastal, yellow, rededge, nir2 ✓
blue, green, red, nir ✓ ✓

WorldView-1 (WV01) images are black-and-white only: load them with bands=["pan"]. find_images skips them unless you ask for sensors=["WV01", ...].

Command line

cloud-detect find Hurricane-Ian-9-26-2022 --n 3 --min-cloud 20     # prints image URLs
cloud-detect mask <url> [<url> ...] --out masks                      # writes GeoTIFF masks
cloud-detect mask <url> --model ukis --resolution 10

The models

Model Install Uses Licence
omnicloudmask (default) included red, green, NIR MIT
ukis [ukis] blue, green, red, NIR Apache-2.0
cloudsen12 [cloudsen12] NIR, red, green, blue LGPL-3.0 code, CC-BY-NC-4.0 weights

None of them was trained on Maxar imagery. Compared with Maxar's own cloud masks on 34 cloudy images, OmniCloudMask agreed best (cloud IoU 0.83, F1 0.90), ahead of CloudSEN12 (0.72) and ukis (0.71). Treat the masks as a strong baseline, not ground truth. Details are in docs/DETECTORS.md; data quirks are in docs/DATA.md.

Data licence

Maxar Open Data imagery is licensed CC-BY-NC-4.0 (non-commercial). This package reads it from Maxar's servers and does not redistribute it.

For developers

The friendly functions above are built on a lower-level layer you can use directly: btt_cloud_mask_example.stac (search and download from any static STAC catalog), .raster (reading bands, writing masks), .detectors (the model wrappers) and .pipeline. The cloud-detect fetch and cloud-detect run commands expose the same layer.

git clone https://github.com/jeckseveg/btt_cloud_mask_example
cd btt_cloud_mask_example
pip install -e ".[all,dev]"
pytest
python -m build && twine check dist/*

Metadata

Release files for btt-cloud-mask-example 0.2.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for btt-cloud-mask-example 0.2.0
File Size Uploaded
btt_cloud_mask_example-0.2.0.tar.gz 22.8 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for btt-cloud-mask-example 0.2.0
File Interpreter ABI Platform
btt_cloud_mask_example-0.2.0-py3-none-any.whl Python 3 none any Details

Total release size: 47.1 kB

Release files / btt_cloud_mask_example-0.2.0.tar.gz

Download URL btt_cloud_mask_example-0.2.0.tar.gz
Size 22.8 kB
Tags Source
SHA-256 checksum
How to use checksums
ad7ea7a6e67cf7d2c70666c548160690a003e0bd3eda8ef706975bf16beb2c6e
BLAKE2b-256 checksum
How to use checksums
2c9eaa9ff183e3a89b7410fe01da7f160ba0540d45129f690b76e3b06c0f1d93
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Oct 14, 2026.

Transparency log

Release files / btt_cloud_mask_example-0.2.0-py3-none-any.whl

Download URL btt_cloud_mask_example-0.2.0-py3-none-any.whl
Size 24.2 kB
Tags Python 3
SHA-256 checksum
How to use checksums
2bc7540291c992546b9757c387bf24cdd7d79ed7fc00d564c5c8839dcf788fbb
BLAKE2b-256 checksum
How to use checksums
a8ba581cef159bf5c2ab49adc9008688bd46af5d9e908a858a15b308e7eb5614
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Oct 14, 2026.

Transparency log

Release history Release notifications | RSS feed

0.2.1

2 release files

This release

0.2.0 This release

2 release files

0.1.1

2 release files

0.1.0

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page