Skip to main content

Universal Cloud Mask Detector for Optical Remote Sensing Imagery

Project description

A Python package for efficient cloud masking in satellite imagery using deep learning models 🚀

PyPI License Black isort


GitHub: https://github.com/IPL-UV/satalign 🌐

PyPI: https://pypi.org/project/satalign/ 🛠️


Overview 📊

phicloudmask is a Python package designed to generate cloud masks from Sentinel-2 satellite imagery using a deep learning model. The model can classify different semantic categories such as land, water, snow, various types of clouds, shadows, and areas with no data. This project is inspired by and builds upon the SEnSeIv2 model developed by Francis et al.

Background 🛰️

The original code by Francis was complex and hard to understand, so this project aims to provide a more Pythonic and user-friendly implementation. The goal is to offer a straightforward way to apply cloud masking to Sentinel-2 imagery and to provide a foundation for building custom models.

Relevant links 🔗

Installation ⚙️

To install the phicloudmask package, run the following command:

pip install phicloudmask

Usage 🚀

The following sections provide detailed instructions on how to use the phicloudmask model for cloud masking.

Load data and weights 📥

Before you begin, ensure that you have the necessary weights and data files in the weights/ directory:

  • spectral_embedding.pt: Weights for the embedding model.
  • cloudmask_weights.pt: Weights for the cloud mask model.
  • demo.pkl: Sample data file containing Sentinel-2 imagery and cloud masks.

Load the data and weights into your Python environment:

import torch
import pickle
import pathlib
import numpy as np
from phicloudmask import CloudMask
from phicloudmask.constant import SENTINEL2_DESCRIPTORS

# Define the semantic categories mapping
cloudsen12_style = {
    0: 0, 1: 0, 2: 0, 6: 0,  # Merged into category 0 (land, water, snow, no_data)
    4: 1,                   # Thick cloud -> category 1
    3: 2,                   # Thin cloud -> category 2
    5: 3                    # Shadow -> category 3
}
map_values = lambda x: cloudsen12_style.get(x, x)

# Load the weights
weights_folder = pathlib.Path("weights/")
embedding_weights = torch.load(weights_folder / "spectral_embedding.pt")
cloudmask_weights = torch.load(weights_folder / "cloudmask_weights.pt")

# Load a sample image
with open(weights_folder / "demo.pkl", "rb") as f:
    dict_demo = pickle.load(f)
    array_demo = dict_demo["s2"][:, 0:512, 0:512]  # S2 L1C image
    mask_demo = dict_demo["cloud_mask"][:, 0:512, 0:512]  # Original mask

Generate cloud masks ☁️

Using all spectral bands 🌈

To generate cloud masks using all Sentinel-2 spectral bands:

1. Initialize the model:

# Initialize the cloud mask model
model = CloudMask(descriptor=SENTINEL2_DESCRIPTORS, device="cuda")
model.embedding_model.load_state_dict(embedding_weights)
model.cloud_model.load_state_dict(cloudmask_weights)
model.eval()

2. Generate cloud mask:

with torch.no_grad():
    image = torch.from_numpy(array_demo[None]).float().to("cuda")
    cloud_probs_all = model(image)
    cloud_mask_all = cloud_probs_all.argmax(dim=0).cpu().numpy()
    cloud_4class_all = np.vectorize(map_values)(cloud_mask_all)

Using RGB bands only 🎨

To generate cloud masks using only the RGB bands:

1. Define RGB bands descriptors:

RGB_DESCRIPTORS = [
    {"band_type": "TOA Reflectance", "min_wavelength": 645.5, "max_wavelength": 684.5},
    {"band_type": "TOA Reflectance", "min_wavelength": 537.5, "max_wavelength": 582.5},
    {"band_type": "TOA Reflectance", "min_wavelength": 446.0, "max_wavelength": 542.0},
]

2. Reinitialize the model for RGB:

model = CloudMask(descriptor=RGB_DESCRIPTORS, device="cuda")
model.embedding_model.load_state_dict(embedding_weights)
model.cloud_model.load_state_dict(cloudmask_weights)
model.eval()

3. Generate cloud mask for RGB bands:

with torch.no_grad():
    image = torch.from_numpy(array_demo[[3, 2, 1]][None]).float().to("cuda")
    cloud_probs_rgb = model(image)
    cloud_mask_rgb = cloud_probs_rgb.argmax(dim=0).cpu().numpy()
    cloud_4class_rgb = np.vectorize(map_values)(cloud_mask_rgb)

Visualize the results 📊

To visualize the original RGB image, the ground truth mask, and the predicted cloud masks:

import matplotlib.pyplot as plt

fig, axes = plt.subplots(2, 2, figsize=(10, 10))
axes = axes.flatten()
axes[0].imshow(image[0].permute(1, 2, 0).cpu().numpy() * 5)
axes[0].set_title("RGB Image")
axes[1].imshow(mask_demo[0])
axes[1].set_title("Original Mask - SEnSeIv2")
axes[2].imshow(cloud_4class_all)
axes[2].set_title("All Bands Mask - phiCloudMask")
axes[3].imshow(cloud_4class_rgb)
axes[3].set_title("RGB Bands Mask - phiCloudMask")
plt.show()

Additional information ✔️

Understanding the model 🧠

The phiCloudMask model leverages a pre-trained neural network architecture to predict cloud masks. It uses two main sets of weights:

  • Embedding weights: Used to convert the spectral data into a meaningful representation for the model.
  • Cloud mask weights: Used for the final classification of each pixel into the predefined categories.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

phicloudmask-0.0.3.tar.gz (10.8 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

phicloudmask-0.0.3-py3-none-any.whl (12.2 kB view details)

Uploaded Python 3

File details

Details for the file phicloudmask-0.0.3.tar.gz.

File metadata

  • Download URL: phicloudmask-0.0.3.tar.gz
  • Upload date:
  • Size: 10.8 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: poetry/2.4.1 CPython/3.12.13 Windows/11

File hashes

Hashes for phicloudmask-0.0.3.tar.gz
Algorithm Hash digest
SHA256 339e2ba21e921ea3781d66572410632db0f16136b81ce9419db780746a1f62f2
MD5 cc9f4ec4b4f7ba1a201e5995fdb0ec20
BLAKE2b-256 a0dd6a61871847bad212ffbc6f10d2c47f4f28b504a8bbdcd9012fe64dd05d25

See more details on using hashes here.

File details

Details for the file phicloudmask-0.0.3-py3-none-any.whl.

File metadata

  • Download URL: phicloudmask-0.0.3-py3-none-any.whl
  • Upload date:
  • Size: 12.2 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: poetry/2.4.1 CPython/3.12.13 Windows/11

File hashes

Hashes for phicloudmask-0.0.3-py3-none-any.whl
Algorithm Hash digest
SHA256 139e130ee536a86d68ac68171a624b21cb17996b678b855d2bcaabad0282c6cd
MD5 3e25bd7768b5c649b1cf62908bad100f
BLAKE2b-256 af18e417e9b3c7a3492e4fc4b0c088a274065d636e5ed43c650e9838574964ce

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page