A dataset of Sentinel-1 GRD SAR image chips with corresponding bounding-box
annotations for ship detection. This dataset accompanies our paper
OSSDD β a New Open Dataset for Sentinel-1 Ship Detection, which describes the dataset creation and baseline detection results. This repository contains the imagery, annotation files,
metadata, and a ready-to-use PyTorch Dataset class (ShipDataset) for training object
detection models.
The dataset is available in two formats:
| Format | Location | Best for |
|---|---|---|
ZIP archive (ossdd.zip) | repository root | Full flexibility, custom pipelines |
WebDataset shards (.tar) | webdataset/{train,val,test}/ | Streaming, large-scale training |
metadata.csv)The dataset consists of Sentinel-1 SAR image chips (in VV and VH polarization) together with ship annotations. The underlying Sentinel-1 products are GRD (Ground Range Detected) images. Each image is provided as a single-band 32-bit GeoTIFF and comes with text-based annotation files describing both axis-aligned and rotated bounding boxes. Additionally, rotated bounding boxes are provided as binary masks (8-bit GeoTIFF).
dataset_root/
βββ Chip_VV/
β βββ Chip_VV_<file_name>.tif
β βββ ...
βββ Chip_VH/
β βββ Chip_VH_<file_name>.tif
β βββ ...
βββ Metadata_aabb/
β βββ Metadata_aabb_<file_name>.txt
β βββ ...
βββ Metadata_rbb/
β βββ Metadata_rbb_<file_name>.txt
β βββ ...
βββ Rotated_Masks/
β βββ Rotated_Mask_<file_name>.tif
β βββ ...
βββ metadata.csv
Chip_<POL>_<file_name>.tif, where <POL> is either VV or VH.The Sentinel-1 products used are GRD (Ground Range Detected) images. These are generated from SLC data by projection into ground geometry and multilooking. Due to this resampling, some images contain negative pixel values in the vicinity of very strong reflectors. These negative values are already present in the GRD products downloaded from the ESA Copernicus Hub.
This must be taken into account β for example, when applying a logarithmic transform to the images. The
ShipDatasetclass handles this via optional clipping of extreme outliers and non-positive values beforelog10scaling.
Annotations are stored as plain text files inside Metadata_aabb (axis-aligned boxes) and
Metadata_rbb (rotated boxes). All coordinates are pixel coordinates in the corresponding
image patch, using a coordinate system whose origin is at the top-left.
Metadata_aabb)Index || Min-x || Min-y || Max-x || Max-y || Center-x || Center-y
Metadata_rbb)Index || Corner1-x || Corner1-y || ... || Corner4-y || Center-x || Center-y
metadata.csv)metadata.csv contains one row per image chip and defines the training, validation and test
set. Additionally, it provides further information about the land coverage per image derived
from a water-land mask (computed with SNAP). Relevant columns include:
| Column | Description |
|---|---|
file_name | Base file name of the chip (with file extension: *.tif) |
split | Dataset split: train, val, test |
class | Scene class label: water (land coverage < 5%) or land (land coverage β₯ 5%) |
text | Text annotation describing the scene based on land coverage. For land coverage < 5%: An aerial view of ships on open water.; For land coverage β₯ 5%: An aerial view of a coastal area with ships on the water. |
text short | Short text caption based on land coverage. For land coverage < 5%: Open water; For land coverage β₯ 5%: Coastal area |
Download ossdd.zip from the repository root and extract it:
from huggingface_hub import hf_hub_download
import zipfile
zip_path = hf_hub_download(
repo_id="sylviaHoch/OpenSARShip-Detection-Dataset",
filename="ossdd.zip",
repo_type="dataset",
local_dir="./data",
)
with zipfile.ZipFile(zip_path, "r") as z:
z.extractall("./data/ossdd")
Then place ship_dataset.py in your working directory and use the ShipDataset class
as shown below.
| Parameter | Type | Default | Description |
|---|---|---|---|
data_dir | str | β | Directory containing the SAR image files (in subfolders Chip_<polarization>). |
label_dir | str | β | Directory containing metadata.csv and annotations in subfolder Metadata_aabb. If the data structure from the download is retained, data_dir=label_dir. |
normalization | str | None | None | Normalization type: "zscore", "robust_zscore", "percentile_clip", "min_max", "scene_min_max", "scene_min_p99", or None. |
nrows | int | None | None | Number of rows to load from metadata.csv (None loads all). Useful for debugging. |
split | str | 'train' | Dataset split: 'train', 'val', 'test'. |
patch_size | int | 512 | Height and width of the random crops used as model input. |
seed | int | None | None | Random seed for reproducibility. |
db_scaling | bool | True | Apply log10 scaling to raw pixel values before further processing. |
polarization | list | ['VV', 'VH'] | List of polarizations to use ('VV', 'VH'). |
augment_landmasks | int | 1 | If > 1, duplicate land samples this many times to balance land/water scenes. |
filetype | str | 'tif' | Image file type: 'tif' or 'npy'. |
clip | bool | True | Clip extreme outliers and non-positive values in the SAR images. |
crop_offset_height | int | 94 | Fixed vertical crop offset for validation/test (used when the image exceeds patch_size). |
crop_offset_width | int | 94 | Fixed horizontal crop offset for validation/test (used when the image exceeds patch_size). |
training_fraction | float | 1 | Use only a stratified subset of the training data (e.g. 0.1 = 10% of all training data). |
> 20 000 and <= 0 β important for
Sentinel-1 GRD data (see Important Notes on Sentinel-1 GRD Data).log10 transform of pixel values.zscore, robust_zscore,
percentile_clip, min_max) and per-scene normalization (scene_min_max, scene_min_p99).
Scene-based scaling parameters are read from / written to scaling_params.csv.augment_landmasks.water / land) via
training_fraction. This option can be used to evaluate model performance with limited
training data.Each item returned by __getitem__ is a tuple (patch, target):
patch: torch.FloatTensor of shape (1, patch_size, patch_size).target: dict with
boxes: torch.FloatTensor of shape (N, 4) in [xmin, ymin, xmax, ymax] format,labels: torch.Int64Tensor of shape (N,) (single class β label 1),image_id: torch.Tensor([idx]).from torch.utils.data import DataLoader
from ship_dataset import ShipDataset
def collate_fn(batch):
return tuple(zip(*batch))
dataset = ShipDataset(
data_dir="path/to/dataset_root",
label_dir="path/to/dataset_root",
normalization="robust_zscore",
split="train",
patch_size=512,
polarization=["VV", "VH"],
db_scaling=True,
clip=True,
seed=42,
)
loader = DataLoader(
dataset,
batch_size=4,
shuffle=True,
collate_fn=collate_fn,
)
for images, targets in loader:
# images: tuple of tensors of shape (1, 512, 512)
# targets: tuple of dicts with keys 'boxes', 'labels', 'image_id'
pass
The WebDataset format enables efficient streaming of the dataset β either from local storage or directly from the HuggingFace Hub β without requiring the full dataset to be downloaded upfront.
Shards are stored under webdataset/{split}/ as .tar files
(e.g. train-000000.tar, val-000000.tar, test-000000.tar, β¦).
Each sample inside a shard contains the following fields:
| Field | Content |
|---|---|
__key__ | Base file name (without extension) |
vv.tif | VV polarization SAR chip (32-bit GeoTIFF, raw bytes) |
vh.tif | VH polarization SAR chip (32-bit GeoTIFF, raw bytes) |
aabb.txt | Axis-aligned bounding box annotation (UTF-8 text) |
rbb.txt | Rotated bounding box annotation (UTF-8 text) |
mask.tif | Rotated bounding box mask (8-bit GeoTIFF, raw bytes) |
meta.json | Metadata: file_name, text, land_fraction, split |
import io
import json
import numpy as np
import rasterio
import webdataset as wds
def decode_tif(data: bytes) -> np.ndarray:
"""Read a GeoTIFF from a byte buffer and return band 1 as float32 array."""
with rasterio.open(io.BytesIO(data)) as src:
return src.read(1).astype(np.float32)
def decode_aabb(data: bytes) -> list:
"""Parse aabb.txt and return a list of [xmin, ymin, xmax, ymax] boxes."""
boxes = []
lines = data.decode("utf-8").strip().splitlines()
for line in lines[1:]: # first line contains the box count
parts = line.split()
if len(parts) >= 5:
boxes.append([
float(parts[1]), float(parts[2]),
float(parts[3]), float(parts[4]),
])
return boxes
def preprocess(sample: dict) -> dict:
return {
"vv": decode_tif(sample["vv.tif"]),
"vh": decode_tif(sample["vh.tif"]),
"boxes": decode_aabb(sample["aabb.txt"]),
"meta": json.loads(sample["meta.json"]),
}
### --- Stream directly from the HuggingFace Hub ---
from huggingface_hub import hf_hub_url
shard_pattern = [
hf_hub_url(
repo_id="<sylviaHoch/OpenSARShip-Detection-Dataset",
filename=f"webdataset/train/train-{i:06d}.tar",
repo_type="dataset",
) for i in range(43) # adjust range to the actual number of shards
]
### --- Or load shards from local storage ---
# shard_pattern = "path/to/webdataset/train/train-{000000..000042}.tar"
dataset = (
wds.WebDataset(shard_pattern, shardshuffle=True)
.shuffle(500)
.map(preprocess)
)
for sample in dataset:
vv = sample["vv"] # np.ndarray, shape (H, W), float32
vh = sample["vh"] # np.ndarray, shape (H, W), float32
boxes = sample["boxes"] # list of [xmin, ymin, xmax, ymax]
meta = sample["meta"] # dict: file_name, text, land_fraction, split
break
rasterio
numpy
pandas
torch
webdataset # required for WebDataset usage only
huggingface_hub # required for Hub download
If you use this dataset in your research, please cite the corresponding publication.
@misc{hammer2026ossddnewopen,
title={OSSDD - a New Open Dataset for Sentinel-1 Ship Detection},
author={Horst Hammer and Sylvia Hochstuhl and Antje Thiele and Tobias Brosch and Padraig Davidson and Tim Remiger and Michael Teutsch},
year={2026},
eprint={2608.01963},
archivePrefix={arXiv},
primaryClass={cs.CV},
}
The annotations, metadata, and accompanying code created by the dataset authors are released under the Creative Commons Attribution 4.0 International (CC-BY-NC-SA-4.0) license.
The image data is derived from Copernicus Sentinel-1 products and remains subject to the Copernicus Sentinel Data Terms and Conditions.
This dataset contains modified Copernicus Sentinel data (the Sentinel-1 GRD scenes were cropped, preprocessed, and annotated).
Disclaimer: Copernicus Sentinel data is provided without any express or implied warranty, including as regards quality and suitability for any purpose. By using this data, you acknowledge the Copernicus Sentinel Data Terms and renounce any claims for damages against the European Union and the providers of the said data and information.
When using or redistributing this dataset, please include the following notice:
Contains modified Copernicus Sentinel data, processed and annotated by the dataset authors. Annotations licensed under CC-BY-NC-SA-4.0.
A dataset of Sentinel-1 GRD SAR image chips with corresponding bounding-box
annotations for ship detection. This dataset accompanies our paper
OSSDD β a New Open Dataset for Sentinel-1 Ship Detection, which describes the dataset creation and baseline detection results. This repository contains the imagery, annotation files,
metadata, and a ready-to-use PyTorch Dataset class (ShipDataset) for training object
detection models.
The dataset is available in two formats:
| Format | Location | Best for |
|---|---|---|
ZIP archive (ossdd.zip) | repository root | Full flexibility, custom pipelines |
WebDataset shards (.tar) | webdataset/{train,val,test}/ | Streaming, large-scale training |
metadata.csv)The dataset consists of Sentinel-1 SAR image chips (in VV and VH polarization) together with ship annotations. The underlying Sentinel-1 products are GRD (Ground Range Detected) images. Each image is provided as a single-band 32-bit GeoTIFF and comes with text-based annotation files describing both axis-aligned and rotated bounding boxes. Additionally, rotated bounding boxes are provided as binary masks (8-bit GeoTIFF).
dataset_root/
βββ Chip_VV/
β βββ Chip_VV_<file_name>.tif
β βββ ...
βββ Chip_VH/
β βββ Chip_VH_<file_name>.tif
β βββ ...
βββ Metadata_aabb/
β βββ Metadata_aabb_<file_name>.txt
β βββ ...
βββ Metadata_rbb/
β βββ Metadata_rbb_<file_name>.txt
β βββ ...
βββ Rotated_Masks/
β βββ Rotated_Mask_<file_name>.tif
β βββ ...
βββ metadata.csv
Chip_<POL>_<file_name>.tif, where <POL> is either VV or VH.The Sentinel-1 products used are GRD (Ground Range Detected) images. These are generated from SLC data by projection into ground geometry and multilooking. Due to this resampling, some images contain negative pixel values in the vicinity of very strong reflectors. These negative values are already present in the GRD products downloaded from the ESA Copernicus Hub.
This must be taken into account β for example, when applying a logarithmic transform to the images. The
ShipDatasetclass handles this via optional clipping of extreme outliers and non-positive values beforelog10scaling.
Annotations are stored as plain text files inside Metadata_aabb (axis-aligned boxes) and
Metadata_rbb (rotated boxes). All coordinates are pixel coordinates in the corresponding
image patch, using a coordinate system whose origin is at the top-left.
Metadata_aabb)Index || Min-x || Min-y || Max-x || Max-y || Center-x || Center-y
Metadata_rbb)Index || Corner1-x || Corner1-y || ... || Corner4-y || Center-x || Center-y
metadata.csv)metadata.csv contains one row per image chip and defines the training, validation and test
set. Additionally, it provides further information about the land coverage per image derived
from a water-land mask (computed with SNAP). Relevant columns include:
| Column | Description |
|---|---|
file_name | Base file name of the chip (with file extension: *.tif) |
split | Dataset split: train, val, test |
class | Scene class label: water (land coverage < 5%) or land (land coverage β₯ 5%) |
text | Text annotation describing the scene based on land coverage. For land coverage < 5%: An aerial view of ships on open water.; For land coverage β₯ 5%: An aerial view of a coastal area with ships on the water. |
text short | Short text caption based on land coverage. For land coverage < 5%: Open water; For land coverage β₯ 5%: Coastal area |
Download ossdd.zip from the repository root and extract it:
from huggingface_hub import hf_hub_download
import zipfile
zip_path = hf_hub_download(
repo_id="sylviaHoch/OpenSARShip-Detection-Dataset",
filename="ossdd.zip",
repo_type="dataset",
local_dir="./data",
)
with zipfile.ZipFile(zip_path, "r") as z:
z.extractall("./data/ossdd")
Then place ship_dataset.py in your working directory and use the ShipDataset class
as shown below.
| Parameter | Type | Default | Description |
|---|---|---|---|
data_dir | str | β | Directory containing the SAR image files (in subfolders Chip_<polarization>). |
label_dir | str | β | Directory containing metadata.csv and annotations in subfolder Metadata_aabb. If the data structure from the download is retained, data_dir=label_dir. |
normalization | str | None | None | Normalization type: "zscore", "robust_zscore", "percentile_clip", "min_max", "scene_min_max", "scene_min_p99", or None. |
nrows | int | None | None | Number of rows to load from metadata.csv (None loads all). Useful for debugging. |
split | str | 'train' | Dataset split: 'train', 'val', 'test'. |
patch_size | int | 512 | Height and width of the random crops used as model input. |
seed | int | None | None | Random seed for reproducibility. |
db_scaling | bool | True | Apply log10 scaling to raw pixel values before further processing. |
polarization | list | ['VV', 'VH'] | List of polarizations to use ('VV', 'VH'). |
augment_landmasks | int | 1 | If > 1, duplicate land samples this many times to balance land/water scenes. |
filetype | str | 'tif' | Image file type: 'tif' or 'npy'. |
clip | bool | True | Clip extreme outliers and non-positive values in the SAR images. |
crop_offset_height | int | 94 | Fixed vertical crop offset for validation/test (used when the image exceeds patch_size). |
crop_offset_width | int | 94 | Fixed horizontal crop offset for validation/test (used when the image exceeds patch_size). |
training_fraction | float | 1 | Use only a stratified subset of the training data (e.g. 0.1 = 10% of all training data). |
> 20 000 and <= 0 β important for
Sentinel-1 GRD data (see Important Notes on Sentinel-1 GRD Data).log10 transform of pixel values.zscore, robust_zscore,
percentile_clip, min_max) and per-scene normalization (scene_min_max, scene_min_p99).
Scene-based scaling parameters are read from / written to scaling_params.csv.augment_landmasks.water / land) via
training_fraction. This option can be used to evaluate model performance with limited
training data.Each item returned by __getitem__ is a tuple (patch, target):
patch: torch.FloatTensor of shape (1, patch_size, patch_size).target: dict with
boxes: torch.FloatTensor of shape (N, 4) in [xmin, ymin, xmax, ymax] format,labels: torch.Int64Tensor of shape (N,) (single class β label 1),image_id: torch.Tensor([idx]).from torch.utils.data import DataLoader
from ship_dataset import ShipDataset
def collate_fn(batch):
return tuple(zip(*batch))
dataset = ShipDataset(
data_dir="path/to/dataset_root",
label_dir="path/to/dataset_root",
normalization="robust_zscore",
split="train",
patch_size=512,
polarization=["VV", "VH"],
db_scaling=True,
clip=True,
seed=42,
)
loader = DataLoader(
dataset,
batch_size=4,
shuffle=True,
collate_fn=collate_fn,
)
for images, targets in loader:
# images: tuple of tensors of shape (1, 512, 512)
# targets: tuple of dicts with keys 'boxes', 'labels', 'image_id'
pass
The WebDataset format enables efficient streaming of the dataset β either from local storage or directly from the HuggingFace Hub β without requiring the full dataset to be downloaded upfront.
Shards are stored under webdataset/{split}/ as .tar files
(e.g. train-000000.tar, val-000000.tar, test-000000.tar, β¦).
Each sample inside a shard contains the following fields:
| Field | Content |
|---|---|
__key__ | Base file name (without extension) |
vv.tif | VV polarization SAR chip (32-bit GeoTIFF, raw bytes) |
vh.tif | VH polarization SAR chip (32-bit GeoTIFF, raw bytes) |
aabb.txt | Axis-aligned bounding box annotation (UTF-8 text) |
rbb.txt | Rotated bounding box annotation (UTF-8 text) |
mask.tif | Rotated bounding box mask (8-bit GeoTIFF, raw bytes) |
meta.json | Metadata: file_name, text, land_fraction, split |
import io
import json
import numpy as np
import rasterio
import webdataset as wds
def decode_tif(data: bytes) -> np.ndarray:
"""Read a GeoTIFF from a byte buffer and return band 1 as float32 array."""
with rasterio.open(io.BytesIO(data)) as src:
return src.read(1).astype(np.float32)
def decode_aabb(data: bytes) -> list:
"""Parse aabb.txt and return a list of [xmin, ymin, xmax, ymax] boxes."""
boxes = []
lines = data.decode("utf-8").strip().splitlines()
for line in lines[1:]: # first line contains the box count
parts = line.split()
if len(parts) >= 5:
boxes.append([
float(parts[1]), float(parts[2]),
float(parts[3]), float(parts[4]),
])
return boxes
def preprocess(sample: dict) -> dict:
return {
"vv": decode_tif(sample["vv.tif"]),
"vh": decode_tif(sample["vh.tif"]),
"boxes": decode_aabb(sample["aabb.txt"]),
"meta": json.loads(sample["meta.json"]),
}
### --- Stream directly from the HuggingFace Hub ---
from huggingface_hub import hf_hub_url
shard_pattern = [
hf_hub_url(
repo_id="<sylviaHoch/OpenSARShip-Detection-Dataset",
filename=f"webdataset/train/train-{i:06d}.tar",
repo_type="dataset",
) for i in range(43) # adjust range to the actual number of shards
]
### --- Or load shards from local storage ---
# shard_pattern = "path/to/webdataset/train/train-{000000..000042}.tar"
dataset = (
wds.WebDataset(shard_pattern, shardshuffle=True)
.shuffle(500)
.map(preprocess)
)
for sample in dataset:
vv = sample["vv"] # np.ndarray, shape (H, W), float32
vh = sample["vh"] # np.ndarray, shape (H, W), float32
boxes = sample["boxes"] # list of [xmin, ymin, xmax, ymax]
meta = sample["meta"] # dict: file_name, text, land_fraction, split
break
rasterio
numpy
pandas
torch
webdataset # required for WebDataset usage only
huggingface_hub # required for Hub download
If you use this dataset in your research, please cite the corresponding publication.
@misc{hammer2026ossddnewopen,
title={OSSDD - a New Open Dataset for Sentinel-1 Ship Detection},
author={Horst Hammer and Sylvia Hochstuhl and Antje Thiele and Tobias Brosch and Padraig Davidson and Tim Remiger and Michael Teutsch},
year={2026},
eprint={2608.01963},
archivePrefix={arXiv},
primaryClass={cs.CV},
}
The annotations, metadata, and accompanying code created by the dataset authors are released under the Creative Commons Attribution 4.0 International (CC-BY-NC-SA-4.0) license.
The image data is derived from Copernicus Sentinel-1 products and remains subject to the Copernicus Sentinel Data Terms and Conditions.
This dataset contains modified Copernicus Sentinel data (the Sentinel-1 GRD scenes were cropped, preprocessed, and annotated).
Disclaimer: Copernicus Sentinel data is provided without any express or implied warranty, including as regards quality and suitability for any purpose. By using this data, you acknowledge the Copernicus Sentinel Data Terms and renounce any claims for damages against the European Union and the providers of the said data and information.
When using or redistributing this dataset, please include the following notice:
Contains modified Copernicus Sentinel data, processed and annotated by the dataset authors. Annotations licensed under CC-BY-NC-SA-4.0.