--- license: apache-2.0 datasets: - kostaspic/amfitrite-inland-waters-hab-sentinel2 metrics: - f1 - accuracy base_model: - BIFOLD-BigEarthNetv2-0/rdnet_base-s2-v0.2.0 pipeline_tag: image-classification library_name: timm tags: - earth-observation - remote-sensing - sentinel-2 - water-quality - harmful-algal-blooms - environmental --- # AMFITRITE-Sentinel2-HAB-RDNet This model is a deep learning classifier designed to detect **Harmful Algal Blooms (HABs)** in inland waters using **Sentinel-2 Level-2A** satellite imagery. It operates as a binary classifier, determining whether a water surface patch contains a bloom or not. The model is built on the **RDNet Base** architecture. It was initialized with weights pretrained on [**BigEarthNet v2.0**](https://huggingface.co/BIFOLD-BigEarthNetv2-0/rdnet_base-s2-v0.2.0) (`rdnet_base-s2-v0.2.0`) and fine-tuned on the [**Amfitrite-Inland-Waters-HAB-Sentinel2**](https://huggingface.co/datasets/kostaspic/amfitrite-inland-waters-hab-sentinel2) dataset. ## Dataset & Training Details The model was fine-tuned using the Amfitrite-Inland-Waters-HAB-Sentinel2 dataset. * **Original Classes:** The source dataset contains three indicative classes: `High`, `Moderate` and `Low`. * **Preprocessing for Detection:** To create a robust binary detector, these classes were merged: * **Bloom (Class 1):** Merged `High` and `Moderate` samples. * **No Bloom (Class 0):** Mapped from `Low` samples. This merging strategy allows the model to focus on the critical distinction between "Clear Water" and "Algal Presence". ## Spectral Awareness Utilizes 10 spectral bands from Sentinel-2 in the following order (B02, B03, B04, B05, B06, B07, B08, B8A, B11, B12) like the BigEarthNet v2.0 RDNet Base pretrained only with Sentinel-2 data. ## Performance The model was evaluated on a strictly stratified test set to ensure reliability. | Metric | Test Set | Validation Set | | :--- | :--- | :--- | | **F1 Score** | 0.926 | 0.934 | | **Accuracy** | 0.898 | 0.909 | | **Balanced Acc** | 0.892 | 0.909 | ## Limitations * The model expects standard L2A Sentinel-2 surface reflectance values (scaled 0-10000). * Performance may vary on water bodies that were not well-represented in the training set (e.g. with extremely high sediment loads). ## Preprocessing Requirements To successfully run inference with this model, your input data must meet the following criteria: 1. **Dimensions:** The input image must be resized or cropped to exactly **256 x 256 pixels**. 2. **Channel Order:** The tensor must contain 10 bands in the following specific order: `B02, B03, B04, B05, B06, B07, B08, B8A, B11, B12`. 3. **Normalization:** The raw Sentinel-2 L2A pixel values (usually ranging from 0 to ~10000) must be divided by `10000.0` so that the input values generally fall between `0.0` and `1.0`. 4. **Shape:** The final tensor passed to the model must have the shape `(Batch_Size, 10, 256, 256)`. ## How to Use This model requires the `timm` library. ### 1. Installation ```bash pip install torch timm rasterio ``` ### 2. Inference Code ```python import rasterio import torch import timm import numpy as np import torch.nn.functional as F # 1. Load Model model = timm.create_model('rdnet_base', pretrained=False, num_classes=2, in_chans=10) # Load weights (assuming the file is downloaded locally as 'model.pth'), use huggingface_hub to download directly state_dict = torch.load("model.pth", map_location='cpu') model.load_state_dict(state_dict) model.eval() def predict_patch(img_tensor): """ Args: img_tensor (torch.Tensor): A tensor of shape (10, Height, Width) containing Sentinel-2 bands. """ # 1. Add batch dimension -> Shape: (1, 10, H, W) img_tensor = img_tensor.unsqueeze(0) # 2. Force resize to the required 256x256 if img_tensor.shape[-2:] != (256, 256): img_tensor = F.interpolate(img_tensor, size=(256, 256), mode='bilinear', align_corners=False) # 3. Normalize Sentinel-2 DN values (0-10000) to 0-1 range img_tensor = img_tensor / 10000.0 # 4. Predict with torch.no_grad(): output = model(img_tensor) prob = torch.softmax(output, dim=1)[0, 1].item() # Probability of Bloom return prob # --- Example Usage --- # Dummy tensor representing a 10-band image that is 365x365 pixels sample_image = torch.rand(10, 365, 365) * 5000 score = predict_patch(sample_image) print(f"Score: {score:.1%}") ``` ## Citations & References If you use this model in your research, please cite the following papers for the underlying architecture and pre-training: **1. This Model:** Pikounis, K. (2026). *Sentinel-2 HAB Detector (RDNet Base)*. Amfitrite Project. ```bibtex @misc{pikounis2026hab, author = {Pikounis, Kostas}, title = {Sentinel-2 HAB Detector (RDNet Base)}, year = {2026}, publisher = {Hugging Face}, howpublished = {\url{https://huggingface.co/kostaspic/AMFITRITE-Sentinel2-HAB-RDNet}}, organization = {Amfitrite Project} } ``` **2. Amfitrite Dataset:** * [kostaspic/amfitrite-inland-waters-hab-sentinel2](https://huggingface.co/datasets/kostaspic/amfitrite-inland-waters-hab-sentinel2) **3. BigEarthNet v2.0 (Pretraining Source):** K. 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. ```bibtex @inproceedings{clasen2025refinedbigearthnet, title={{reBEN}: Refined BigEarthNet Dataset for Remote Sensing Image Analysis}, author={Clasen, Kai Norman and Hackel, Leonard and Burgert, Tom and Sumbul, Gencer and Demir, Beg{\"u}m and Markl, Volker}, year={2025}, booktitle={IEEE International Geoscience and Remote Sensing Symposium (IGARSS)}, } ``` **4. Library & Framework:** L. Hackel, K. Clasen, B. Demir, "ConfigILM: A General Purpose Configurable Library for Combining Image and Language Models for Visual Question Answering.", SoftwareX 26 (2024): 101731. ```bibtex @article{hackel2024configilm, title={ConfigILM: A general purpose configurable library for combining image and language models for visual question answering}, author={Hackel, Leonard and Clasen, Kai Norman and Demir, Beg{\"u}m}, journal={SoftwareX}, volume={26}, pages={101731}, year={2024}, publisher={Elsevier} } ```