GeoBench BigEarthNetV2#

Intro#

BigEarthNet v2.0 Clasen et al. 2025 is a large-scale multi-modal satellite image dataset for multi-label land cover classification. The dataset contains Sentinel-1 SAR and Sentinel-2 optical imagery with multi-label annotations based on the CORINE Land Cover (CLC) labels. In comparison to v1.0, the v2.0 release provides improved hierarchical multi-label annotations, enhanced data quality, and geospatial splits. It can be used to evaluate multi-label classification and data fusion (SAR + Optical) data fusion schemes.

Dataset Characteristics#

  • Modalities:

    • Sentinel-1 SAR (VV, VH polarizations)

    • Sentinel-2 Optical (12 spectral bands)

  • Spatial Resolution:

    • S1: 10m ground sample distance

    • S2: 10m, 20m, 60m (resampled to 10m)

  • Temporal Resolution: Single acquisition per patch

  • Spectral Bands:

    • S2: 12 bands (B01, B02, B03, B04, B05, B06, B07, B08, B8A, B09, B11, B12)

    • S1: 2 polarizations (VV, VH)

  • Image Dimensions: 120x120 pixels (1.2km x 1.2km patches)

  • Labels: 19 CORINE Land Cover classes (multi-label)

  • Geographic Distribution: 10 European countries

  • Temporal Coverage: June 2017 - May 2018

GeoBenchV2 Processing Pipeline#

Preprocessing Steps#

  1. Split Generation:

    • Used existing train/validation/test splits from original dataset

    • Created additional test subset from training data for extended evaluation

  2. Dataset Subsampling:

    • The final version consists of

      • 20,000 training samples

      • 4,000 validation samples

      • 4,000 test samples

References#

    1. Clasen, L. Hackel, T. Burgert, G. Sumbul, B. Demir, V. Markl, “ reBEN: Refined BigEarthNet Dataset for Remote Sensing Image Analysis “, IEEE International Geoscience and Remote Sensing Symposium (IGARSS), 2025. https://arxiv.org/abs/2407.03653

  1. Original Dataset Download: http://bigearth.net/

  2. CORINE Land Cover: https://land.copernicus.eu/pan-european/corine-land-cover

[1]:
import os
from pathlib import Path

import torch

from geobench_v2.datamodules import GeoBenchBENV2DataModule
from geobench_v2.datasets import GeoBenchBENV2
from geobench_v2.datasets.normalization import SatMAENormalizer, ZScoreNormalizer
from geobench_v2.datasets.visualization_util import (
    compare_normalization_methods,
    compute_batch_histograms,
    plot_batch_histograms,
    plot_channel_histograms,
)

%load_ext autoreload
%autoreload 2
[2]:
DATA_ROOT = Path("../../data/benv2")

STATS_SATMAE_PATH = os.path.join(DATA_ROOT, "benv2_stats_satmae.json")
STATS_CLIP_RESCALE_PATH = os.path.join(DATA_ROOT, "benv2_stats_clip_rescale.json")
[ ]:
band_order = GeoBenchBENV2.band_default_order

datamodule = GeoBenchBENV2DataModule(
    img_size=120,
    batch_size=4,
    num_workers=4,
    root=DATA_ROOT,
    band_order=band_order,
    data_normalizer=torch.nn.Identity(),  # we do custom normalization in the tutorial
)
datamodule.setup("fit")
Using provided pre-initialized normalizer instance: Identity
Using provided pre-initialized normalizer instance: Identity
[4]:
sample_dist_fig = datamodule.visualize_geospatial_distribution()
../_images/dataset_notebooks_benv2_4_0.png

Dataset Statistics#

Image Dataset Statistics#

[5]:
fig = plot_channel_histograms(STATS_SATMAE_PATH)
../_images/dataset_notebooks_benv2_7_0.png
../_images/dataset_notebooks_benv2_7_1.png

Target Statistics#

Raw Batch Image Statistics#

Statistics of a single batch before any normalization

[6]:
train_dataloader = datamodule.train_dataloader()
raw_batch = next(iter(train_dataloader))

raw_batch_stats = compute_batch_histograms(raw_batch, n_bins=100)

vis_band_order = {
    "s2": [b for b in band_order["s2"] if isinstance(b, str)],
    "s1": [b for b in band_order["s1"] if isinstance(b, str)],
}
raw_figs = plot_batch_histograms(
    raw_batch_stats, vis_band_order, title_suffix=" (Raw Data)"
)
../_images/dataset_notebooks_benv2_10_0.png
../_images/dataset_notebooks_benv2_10_1.png

Effect of different Normalization Schemes#

[7]:
zscore_normalizer = ZScoreNormalizer(STATS_CLIP_RESCALE_PATH, band_order)
satmae_normalizer = SatMAENormalizer(STATS_SATMAE_PATH, band_order)
[8]:
norm_fig, normalized_batches = compare_normalization_methods(
    raw_batch, [zscore_normalizer, satmae_normalizer], datamodule
)
../_images/dataset_notebooks_benv2_13_0.png

Visualize Batch#

[9]:
fig, batch = datamodule.visualize_batch()
../_images/dataset_notebooks_benv2_15_0.png