Copernicus-FM: Foundation Model for Earth Vision
repository·main·Indexed 40 days ago
https://github.com/zhu-xlab/copernicus-fmA unified foundation model and ecosystem for Earth Vision featuring Copernicus-FM, a multi-modal foundation model, and Copernicus-Bench, a systematic evaluation benchmark with 15 datasets covering Sentinel missions (S1, S2, S3, S5P). The ecosystem provides large-scale pretraining datasets, high-resolution global embeddings, and implementations for comparing models like SatMAE++ and CROMA using metrics such as mIoU, OA, mAP, and RMSE.
What's inside Copernicus-FM
- SatMAE++ (CVPR 2024) is a transformer pre-training method designed for multi-spectral satellite imagery. Unlike standard natural image pre-training, SatMAE++ addresses the diverse scale variations and multiple modalities found in remote sensing data. It utilizes multi-scale pre-training and convolution-based upsampling blocks to reconstruct images at multiple scales, making it effective for both optical and multi-spectral imagery.
Overview of the Copernicus Foundation Model ecosystem
mainThe Copernicus Foundation Model project provides a unified framework for Earth Vision, consisting of four primary components:
- Copernicus-Pretrain: A massive-scale pretraining dataset containing 18.7M aligned images from major Copernicus Sentinel missions (S1-S5P), organized into ~310K regional grids (0.25°x0.25°).
- Copernicus-FM: A unified foundation model capable of processing any spectral or non-spectral sensor modality using extended dynamic hypernetworks and flexible metadata encoding.
- Copernicus-Bench: A systematic evaluation benchmark with 15 hierarchical downstream tasks across three levels of applications (L1, L2, L3) covering Sentinel missions S1, S2, S3, and S5P.
- Copernicus-Embed-025deg: A global embedding map (721x1440x768) at 0.25° resolution that integrates various satellite observations at a high compression ratio, useful for linking Earth's surface to the atmosphere.
Overview of Copernicus-Pretrain dataset
mainCopernicus-Pretrain is a large-scale Earth observation dataset designed for pretraining foundation models. It extends the SSL4EO-S12 dataset to include all major Sentinel missions (S1-S5P) and Copernicus DEM. The dataset is organized into approximately 310K regional grids (0.25°x0.25°) covering land and near-land ocean surfaces. Each grid contains time series data from eight distinct modalities:
- Sentinel-1 GRD (SAR)
- Sentinel-2 TOA (Multispectral)
- Sentinel-3 OLCI (Multispectral)
- Sentinel-5P CO (Atmospheric)
- Sentinel-5P NO2 (Atmospheric)
- Sentinel-5P SO2 (Atmospheric)
- Sentinel-5P O3 (Atmospheric)
- Copernicus DEM (Elevation)
The dataset contains over 18.7 million total images across ~3.8 million patches/grids.
Overview of Copernicus-Bench datasets
mainCopernicus-Bench is a hierarchical evaluation benchmark consisting of 15 datasets across three levels of application, covering major Sentinel missions (S1, S2, S3, S5P).Install CROMA dependencies
mainTo use CROMA, you need to install
einops. Ensure you also havetorchinstalled. A relatively recent version of both should be compatible.pip install einopsSetup FMoW-Sentinel dataset for SatMAE++
mainTo use the FMoW-Sentinel dataset, ensure your directory structure follows this pattern:
[Root folder] ____ train.csv ____ val.csv ____ [images folder] ________ train ____________ [class_folder] ________ val ____________ [class_folder]Note:
[class_folder]should contain subdirectories for each class (e.g.,aiport,aiport_hangar).Use PretrainedCROMA to extract representations
mainTo use pretrained models, you must have the
use_croma.pyfile in your working directory along with the downloaded weights.Input Requirements
- Sentinel-1 (SAR): Must have 2 channels.
- Sentinel-2 (Optical): Must have 12 channels (remove the cirrus band if necessary).
- Resolution: Default is 120x120px, but can be specified via
image_resolution.
Implementation Example
import torch from use_croma import PretrainedCROMA device = 'cuda:0' use_8_bit = True N = 1_000 # Example dummy data sentinel_1 = torch.randn(N, 2, 120, 120).to(device) sentinel_2 = torch.randn(N, 12, 120, 120).to(device) # Normalization function (required for correct model input) def normalize(x, use_8_bit): x = x.float() imgs = [] for channel in range(x.shape[1]): min_value = x[:, channel, :, :].mean() - 2 * x[:, channel, :, :].std() max_value = x[:, channel, :, :].mean() + 2 * x[:, channel, :, :].std() if use_8_bit: img = (x[:, channel, :, :] - min_value) / (max_value - min_value) * 255.0 img = torch.clip(img, 0, 255).unsqueeze(dim=1).to(torch.uint8) imgs.append(img) else: img = (x[:, channel, :, :] - min_value) / (max_value - min_value) img = torch.clip(img, 0, 1).unsqueeze(dim=1) imgs.append(img) return torch.cat(imgs, dim=1) sentinel_1 = normalize(sentinel_1, use_8_bit) sentinel_2 = normalize(sentinel_2, use_8_bit) # Initialize model model = PretrainedCROMA(pretrained_path='CROMA_base.pt', size='base', modality='both', image_resolution=120).to(device) # If using 8-bit normalization, rescale back to float for the model if use_8_bit: sentinel_1 = sentinel_1.float() / 255 sentinel_2 = sentinel_2.float() / 255 with torch.no_grad(): outputs = model(SAR_images=sentinel_1, optical_images=sentinel_2)import torch from use_croma import PretrainedCROMA device = 'cuda:0' use_8_bit = True N = 1_000 sentinel_1 = torch.randn(N, 2, 120, 120).to(device) sentinel_2 = torch.randn(N, 12, 120, 120).to(device) def normalize(x, use_8_bit): x = x.float() imgs = [] for channel in range(x.shape[1]): min_value = x[:, channel, :, :].mean() - 2 * x[:, channel, :, :].std() max_value = x[:, channel, :, :].mean() + 2 * x[:, channel, :, :].std() if use_8_bit: img = (x[:, channel, :, :] - min_value) / (max_value - min_value) * 255.0 img = torch.clip(img, 0, 255).unsqueeze(dim=1).to(torch.uint8) imgs.append(img) else: img = (x[:, channel, :, :] - min_value) / (max_value - min_value) img = torch.clip(img, 0, 1).unsqueeze(dim=1) imgs.append(img) return torch.cat(imgs, dim=1) sentinel_1 = normalize(sentinel_1, use_8_bit) sentinel_2 = normalize(sentinel_2, use_8_bit) model = PretrainedCROMA(pretrained_path='CROMA_base.pt', size='base', modality='both', image_resolution=120).to(device) if use_8_bit: sentinel_1 = sentinel_1.float() / 255 sentinel_2 = sentinel_2.float() / 255 with torch.no_grad(): outputs = model(SAR_images=sentinel_1, optical_images=sentinel_2)Download pretrained Copernicus-FM weights
mainDownload the pretrained model weights to a
./weights/directory before loading them into the model.mkdir -p ./weights/ wget https://huggingface.co/wangyi111/Copernicus-FM/resolve/main/CopernicusFM_ViT_base_varlang_e100.pth -P ./weights/Access Copernicus-Pretrain in WebDataset format
mainThe streaming WebDataset format is available on HuggingFace under the
ssl4eo_s_*prefix. This format is optimized for efficient streaming and distributed training. Images are converted into PyTorch tensors and grouped into shards (small.tarfiles), where each shard contains approximately 100 samples.Each sample in a shard consists of:
- 8
.pthtensors (one for each modality) - 1
.jsonfile containing metadata (grid_id, coord, date, etc.)
Two versions are available:
ssl4eo_s_220k_aligned/: ~220K grids with all modalities.ssl4eo_s_220k_310k_union/: ~310K grids with potential missing modalities.
- 8
Setup the Copernicus-Bench environment
mainThe benchmark implementation depends on PyTorch, PyTorch Lightning, Hydra, TorchGeo, MMSegmentation, and experiment trackers like MLflow or Weights & Biases.
Follow these steps to create a Conda environment and install the necessary dependencies:
conda create -n copernicusbench python=3.10 conda activate copernicusbench pip install -U openmim pip install torch==2.1.2 mim install mmcv==2.1.0 mmsegmentation==1.2.2 pip install -e .Install Copernicus-FM dependencies
mainTo set up the environment for using the pretrained model, create a new Conda environment with Python 3.10 and install the required packages.
conda create -n copernicusfm python=3.10 conda activate copernicusfm pip install torch torchvision timm einops rasterio pyproj # or pip install -r requirements.txtAccess Copernicus-Pretrain in GeoTiff format
mainThe raw GeoTiff format is available on HuggingFace under the
raw_geotiffs_*prefix. Data is organized intotar.zstchunks, where each chunk contains 1,000 grids per modality. Chunk IDs are aligned across modalities (e.g.,dem_grid_wgs_chunk001.tar.zstands1_grd_utm_chunk001.tar.zstcontain the same 1,000 grids), making it easy to create subdatasets.Two versions are available:
raw_geotiffs_220k_aligned/: ~220K grids with all modalities available.raw_geotiffs_220k_310k_union/: ~310K grids where some modalities may be missing.