DeepContrail segmentation: UPerNet + CAFormer-B36 (v0.1.0)
Contrail segmentation model for DeepContrail.
It takes a GOES-16 ABI false-colour composite and returns, for each pixel, the probability that
it shows a contrail. It was trained on the
OpenContrails dataset (20250305 export).
Usage
Install the DeepContrail packages from git; they are not on PyPI yet:
pip install \
"deepcontrail-core @ git+https://github.com/eurocontrol-asu/deepcontrail@v0.1.0#subdirectory=packages/core" \
"deepcontrail-segmentation @ git+https://github.com/eurocontrol-asu/deepcontrail@v0.1.0#subdirectory=packages/segmentation"
import numpy as np
from deepcontrail.core import false_color_from_spectral, read_band_manifest
from deepcontrail.segmentation import load_pretrained, predict
model = load_pretrained("eurocontrol-asu/deepcontrail-segmentation", revision="v0.1.0")
bands = np.load(f"{root}/spectral_bands/test/{record_id}.npy")
composite = false_color_from_spectral(bands, model.config.false_color, read_band_manifest(root))
probabilities = predict(model, composite, tta=model.config.tta) # (H, W), float32 in [0, 1]
mask = probabilities > model.config.threshold
root is a dataset in the DeepContrail format; the
OpenContrails converter
produces it from the raw TFRecords. predict also takes a batch (N, H, W, 3).
Model
- Architecture: UPerNet decoder with a CAFormer-B36 encoder
(
timmcaformer_b36.sail_in22k_ft_in1k_384), from segmentation-models-pytorch; 102.6 M parameters. - Input: a 3-channel composite in [0, 1] (below) of a 256 Γ 256 scene, resized to 512 px and
normalised with mean [0.485, 0.456, 0.406], std [0.229, 0.224, 0.225].
predictdoes this. - Output: contrail probability at the input's resolution; contrail where > 0.5.
- Test-time augmentation: recommended; it averages the 8 flips and rotations.
Input composite (standard ash RGB)
| Channel | Bands | Bounds (scaled to [0, 1], clipped) |
|---|---|---|
| R | data_12um β data_11um (GOES-16 ABI bands 15 β 14) | [β4, 2] K |
| G | data_11um β cloud_top (GOES-16 ABI bands 14 β 11) | [β4, 5] K |
| B | data_11um (GOES-16 ABI band 14) | [243, 303] K |
The bands are referred to by their keys in the dataset's bands.json.
Training
- Data: the OpenContrails
20250305export. Of its 20,088 training scenes, 10% (2,009, seed- were held out for validation, so the model trained on 18,079 scenes.
- Labels: the per-pixel fraction of annotators who marked a contrail (soft labels).
- Recipe: 40 epochs at 512 px, batch 32, AdamW (learning rate 1e-4, weight decay 1e-2), cosine
schedule with 3 warm-up epochs, BCE + 0.2 Γ Dice loss, bf16 mixed precision, flips, 90Β°
rotations and small shift/scale/rotate augmentations. The checkpoint with the best validation
Dice was kept. The full configuration is
experiment.yaml.
Evaluation
Global Dice on the held-out test split: 1,879 scenes, the OpenContrails validation shards, never used for training or model selection.
| Inference | Threshold | Test Dice |
|---|---|---|
| Single pass | 0.5 | 0.6892 |
| Single pass | tuned on validation | 0.6913 |
| Test-time augmentation | 0.5 | 0.6960 |
| Test-time augmentation | tuned on validation | 0.6936 |
GPU training is not bit-for-bit reproducible. Four trainings of this exact configuration, with the same seed and data, scored 0.6916β0.6960 (test-time augmentation, threshold 0.5); this model is the best of the four.
Instance segmentation
This repository also holds the instance step tuned for this model, which splits its probability map into individual contrails (one mask and one score each):
instance_pipeline.yaml: the settings of thedeepcontrail-instancepipeline (threshold, Mannstein line detection, growth);score_model.json: a learned score that ranks the detected contrails, trained on this model's test-time-augmented predictions for 1,000 of its validation scenes.
They are not part of the v0.1.0 revision. They need deepcontrail-instance from the
repository's main branch (not yet in a release):
pip install "deepcontrail-instance[map] @ git+https://github.com/eurocontrol-asu/deepcontrail#subdirectory=packages/instance"
from deepcontrail.instance import load_instance_step, to_coco_results
model = load_pretrained("eurocontrol-asu/deepcontrail-segmentation") # main revision
step = load_instance_step(model.directory, tta=model.config.tta)
masks, scores = step(predict(model, composite, tta=model.config.tta))
results = to_coco_results(masks, scores, image_id=record_id) # COCO results with RLE masks
On the 1,879 test scenes, scored against each annotator's contrails (2,700 annotator samples with
at least one contrail), these settings reach a COCO segmentation mAP of 0.277 (averaged over IoU
0.25β0.75), with precision 0.516, recall 0.382 and F1 0.439 at IoU 0.5. The settings and the score
were chosen on validation scenes only. The score model is valid only for this model's
probabilities made with test-time augmentation on 256 Γ 256 scenes; load_instance_step and the
pipeline refuse other uses.
Limitations
- Sensor and scene size. Trained on GOES-16 ABI scenes of 256 Γ 256 pixels (about 2 km per
pixel).
predictresizes any input to 512 Γ 512, so other sizes or non-square scenes are not supported yet. - Label convention. The
20250305masks are aligned with the images. The older20230419export and the Kaggle competition data put the masks half a pixel down-right: on those, callpredict(..., pixel_shift=0.5). - Other label sets. The
20250305masks overlap the20230419/Kaggle ones at an IoU of only about 0.78, so scores on the two are not directly comparable. An earlier training of this same configuration scored 0.6914 (private) / 0.6994 (public) on the hidden test set of the Kaggle Google Research β Identify Contrails to Reduce Global Warming competition.
Provenance
| Training run | upernet-caformer-b36-512-20250305-final |
| Checkpoint | best-val_dice=0.6963.ckpt |
| Code | DeepContrail 0.1.0 |
| Data | OpenContrails GOES-16 ABI TFRecords, export 20250305 |
Licence and attribution
The weights are released under the Apache License 2.0 by EUROCONTROL. If you
redistribute them, as they are or modified, keep the NOTICE file with them. The
DeepContrail code is under the EUPL-1.2.
- Training data: OpenContrails
(bucket
goes_contrails_dataset), by Google Research, under the CC BY 4.0 licence. GOES-16 imagery is courtesy of NOAA and has no use restrictions. - Encoder initialisation:
timm/caformer_b36.sail_in22k_ft_in1k_384, under the Apache License 2.0.
If you use this model, please cite the OpenContrails dataset:
@article{Ng2024ContrailDO,
title={Contrail Detection on GOES-16 ABI With the OpenContrails Dataset},
author={Joe Yue-Hei Ng and Kevin McCloskey and Jian Cui and Vincent R. Meijer and Erica Brand and Aaron Sarna and Nita Goyal and Christopher Van Arsdale and Scott Geraedts},
journal={IEEE Transactions on Geoscience and Remote Sensing},
year={2024},
volume={62},
pages={1-14}
}
- Downloads last month
- -