kelp-skema
Binary kelp canopy segmentation models for Sentinel-2 L2A imagery, developed by Mohsen Ghanbari (@m5ghanba) at the Spectral Lab, University of Victoria.. This repository hosts ONNX exports of the original SKeMa models (HuggingFace Β· GitHub), re-packaged for use with habitat-mapper. Normalization and spectral index computation are baked into the inference graph, so models accept raw Sentinel-2 DN values directly.
Model Variants
Four variants are available, differing in input channels and auxiliary data requirements:
| Variant | ONNX file | Channels in | Auxiliary data | Geographic scope |
|---|---|---|---|---|
| S2-only | Unet_tu-maxvit_tiny_tf_512_20260414.onnx |
5 | None | Global |
| Full | Unet_tu-maxvit_tiny_tf_512_20260414_full.onnx |
8 | RF substrate, bathymetry, slope | Coastal BC |
| Ensemble | Unet_tu-maxvit_tiny_tf_512_20260414_ensemble.onnx |
8 | RF substrate, bathymetry, slope | Coastal BC |
| Full-BoPs | Unet_tu-maxvit_tiny_tf_512_20260414_full_bops.onnx |
8 | BoPs substrate, bathymetry, slope | Coastal BC |
The Full and Full-BoPs variants use the same UNet weights but were trained with different substrate datasets. Use Full-BoPs for scenes acquired by BC Ministry of Environment BoPs sensors (identifiable by UXQ, UXS, or UDU in the Sentinel-2 product identifier). Use Full for all other scenes.
The Ensemble model combines the S2-only and Full models by averaging their logits, and generally produces the most robust predictions.
Architecture
All variants use a UNet with a MaxViT-tiny encoder (tu-maxvit_tiny_tf_512, tile size 512), implemented via segmentation-models-pytorch.
Each model's forward pass:
- Accepts raw Sentinel-2 DN values (uint16 range, 0β~10000) as float32
- Computes spectral indices internally (NDVI, NDWI, GNDVI, CIG, NDVIre)
- Normalizes the augmented channel stack with baked-in per-channel mean/std
- Runs the UNet backbone
- Returns raw logits (apply sigmoid + threshold externally)
Internal channel layout after augmentation:
| ch | S2-only (10 ch) | Full / Full-BoPs / Ensemble (13 ch) |
|---|---|---|
| 0 | B02 (Blue) | B02 (Blue) |
| 1 | B03 (Green) | B03 (Green) |
| 2 | B04 (Red) | B04 (Red) |
| 3 | B08 (NIR) | B08 (NIR) |
| 4 | B05 (Red Edge) | B05 (Red Edge) |
| 5 | NDVI | Substrate |
| 6 | NDWI | Bathymetry |
| 7 | GNDVI | Slope |
| 8 | CIG | NDVI |
| 9 | NDVIre | NDWI |
| 10 | β | GNDVI |
| 11 | β | CIG |
| 12 | β | NDVIre |
Baked-in Normalization Parameters
Applied as (x - mean) / std after index augmentation.
S2-only (10 channels)
mean = [2.08900522e+02, 2.70272557e+02, 1.52312422e+02, 9.87182507e+02, 3.26650321e+02,
5.65647882e-02, 1.62913280e-01, -1.62913280e-01, 1.63743045e+00, 1.09887867e-01]
std = [1.59021908e+02, 2.18393833e+02, 2.08355086e+02, 1.29667310e+03, 3.79794112e+02,
6.53314129e-01, 7.11820223e-01, 7.11820223e-01, 3.84363017e+00, 3.90619966e-01]
Full / Ensemble β RF substrate (13 channels)
mean = [2.02127847e+02, 2.64991799e+02, 1.45913497e+02, 9.57456953e+02, 3.20302883e+02,
1.37548690e+00, -6.30723576e+00, 7.60650406e+00,
3.66107438e-02, 1.84492036e-01, -1.84492036e-01, 1.56750584e+00, 9.99078992e-02]
std = [1.61504107e+02, 2.22303637e+02, 2.03997451e+02, 1.26105656e+03, 3.79069759e+02,
1.36767732e+00, 2.35930351e+02, 1.14107889e+01,
6.71879776e-01, 7.23202999e-01, 7.23202999e-01, 3.86945642e+00, 4.06695959e-01]
Full-BoPs β BoPs substrate (13 channels, ch 5 differs)
mean = [2.02127847e+02, 2.64991799e+02, 1.45913497e+02, 9.57456953e+02, 3.20302883e+02,
8.15331190e-01, -6.30723576e+00, 7.60650406e+00,
3.66107438e-02, 1.84492036e-01, -1.84492036e-01, 1.56750584e+00, 9.99078992e-02]
std = [1.61504107e+02, 2.22303637e+02, 2.03997451e+02, 1.26105656e+03, 3.79069759e+02,
1.09273473e+00, 2.35930351e+02, 1.14107889e+01,
6.71879776e-01, 7.23202999e-01, 7.23202999e-01, 3.86945642e+00, 4.06695959e-01]
Repo Files
20260414/
βββ Unet_tu-maxvit_tiny_tf_512_20260414.onnx # S2-only model
βββ Unet_tu-maxvit_tiny_tf_512_20260414_full.onnx # Full model (RF substrate)
βββ Unet_tu-maxvit_tiny_tf_512_20260414_ensemble.onnx # Ensemble model (RF substrate)
βββ Unet_tu-maxvit_tiny_tf_512_20260414_full_bops.onnx # Full model (BoPs substrate)
βββ substrate_20m_cog.tif # RF substrate raster (20 m)
βββ bops_substrate_10m_cog.tif # BoPs substrate raster (10 m)
βββ bathymetry_10m_cog.tif # Bathymetry raster (10 m)
βββ slope_10m_cog.tif # Slope raster (10 m)
Usage
The recommended way to run these models is via habitat-mapper:
hab predict <input.SAFE> <output.tif> --model kelp-skema
Model configs are bundled in habitat-mapper and handle dependency downloading, band reading, tiling, and postprocessing automatically. Four configs are available corresponding to the four variants:
kelp-skema/20260414β S2-onlykelp-skema/20260414-fullβ Full (RF substrate)kelp-skema/20260414-ensembleβ Ensemblekelp-skema/20260414-full-bopsβ Full (BoPs substrate)
Direct ONNX inference
The models accept batched float32 input of shape (B, C, H, W) where C is 5 (S2-only) or 8 (full/ensemble/full-bops). Values should be raw Sentinel-2 L2A DN values with the processing baseline offset removed (subtract 1000 for baseline β₯ 4.0, leave as-is for older baselines, then clip to 0).
import onnxruntime as ort
import numpy as np
session = ort.InferenceSession("Unet_tu-maxvit_tiny_tf_512_20260414_full.onnx")
logits = session.run(["output"], {"input": tile.astype(np.float32)})[0]
predictions = (1 / (1 + np.exp(-logits)) > 0.5).astype(np.uint8)
Intended Use
These models are intended for mapping surface kelp canopy extent from multispectral Sentinel-2 satellite imagery, primarily in coastal British Columbia, Canada. They are not validated for other species or regions.
Limitations
- The Full, Ensemble, and Full-BoPs variants require static auxiliary layers (substrate, bathymetry, slope) that are only available for coastal British Columbia.
- All variants are trained on Sentinel-2 L2A (atmospherically corrected) data. Results on L1C data are not validated.
- Performance degrades under heavy cloud cover, sun glint, or turbid water conditions typical of intertidal zones.
- Canopy kelp only β subsurface kelp is not detectable from multispectral imagery.
Citation
If you use these models in your work, please cite the following papers:
@article{ghanbari2026ecoinf,
title = {Automated Kelp Forest Mapping from Sentinel-2 Imagery Using Deep Learning},
author = {Ghanbari, Mohsen and Ernst, Neil and Denouden, Taylor and Reshitnyk, Luba
and Steffen, Piper and Wachmann, Alena and Mora-Soto, Alejandra
and Loos, Eduardo and Hessing-Lewis, Margot and Dedeluk, Nic and Costa, Maycira},
journal = {Ecological Informatics},
year = {2026},
note = {Under review, Manuscript No. ECOINF-D-26-01969}
}
The original model weights and inference code are available at:
License
MIT β see LICENSE.