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#
Split Generation:
Used existing train/validation/test splits from original dataset
Created additional test subset from training data for extended evaluation
Dataset Subsampling:
The final version consists of
20,000 training samples
4,000 validation samples
4,000 test samples
References#
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
Original Dataset Download: http://bigearth.net/
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()
Dataset Statistics#
Image Dataset Statistics#
[5]:
fig = plot_channel_histograms(STATS_SATMAE_PATH)
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)"
)
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
)
Visualize Batch#
[9]:
fig, batch = datamodule.visualize_batch()