---
library_name: vessel-reid
tags:
- computer-vision
- image-embeddings
- image-retrieval
- model_hub_mixin
- pytorch
- pytorch_model_hub_mixin
- timm
- vessel-reid
- vessel
- dinov3
- identification
base_model:
- timm/vit_base_patch16_dinov3.lvd1689m
license: other
license_name: dinov3-license
license_link: https://ai.meta.com/resources/models-and-libraries/dinov3-license
---
# Detection and Metric Learning from Pseudo-Labels for Unsupervised Maritime Vessel Re-Identification
This repository contains the weights of the model trained for vessel re-identification on the [VesselReID Dataset](https://github.com/vsislab/VesselReID), presented at [AVSS 2026](https://www.avss2026.org/):
- Backbone: ViT-B/16 DINOv3
- Code: [TO-DO]
- Paper: [Detection and Metric Learning from Pseudo-Labels for Unsupervised Maritime Vessel Re-Identification](https://cnrsc-my.sharepoint.com/:b:/g/personal/cosimo_distante_cnr_it/IQA9ASnL2ykMSYyj0rbKjIPvARy8eIHqRC_VEq0htfgLWmg?e=7QtdNm) (AVSS'26 oral)
This model has been pushed to the Hub using the [PytorchModelHubMixin](https://huggingface.co/docs/huggingface_hub/package_reference/mixins#huggingface_hub.PyTorchModelHubMixin) integration:
## Usage
Install the required dependencies:
```bash
pip install torch torchvision timm huggingface_hub
```
Download the model from Hugging Face and run this self-contained inference script on a random image:
```python
import torch
import torch.nn as nn
import torch.nn.functional as F
import timm
from huggingface_hub import PyTorchModelHubMixin
MODEL_ID = "sangioai/vessel-reid-vit-base-dinov3"
class VesselReIDModel(
nn.Module,
PyTorchModelHubMixin,
library_name="vessel-reid",
tags=[
"vessel-reid",
"image-retrieval",
"image-embeddings",
"computer-vision",
"pytorch",
"timm",
"dinov3",
],
):
"""
Vessel Re-Identification model.
Backbone:
ViT-B/16 DINOv3
Projection head:
2-layer MLP
Output:
L2-normalized 256-dimensional embedding.
"""
def __init__(
self,
model_name: str = "vit_base_patch16_dinov3.lvd1689m",
proj_dim: int = 256,
pretrained: bool = False,
):
super().__init__()
self.model_name = model_name
self.proj_dim = proj_dim
self.encoder = timm.create_model(model_name, pretrained=pretrained, num_classes=0)
embedding_dim = self.encoder.num_features
self.projector = nn.Sequential(
nn.Linear(embedding_dim, embedding_dim),
nn.ReLU(inplace=True),
nn.Linear(embedding_dim, proj_dim),
)
def forward(self, x: torch.Tensor) -> torch.Tensor:
"""
Args:
x:
Tensor of shape (B, 3, H, W).
Returns:
L2-normalized embeddings of shape (B, proj_dim).
"""
features = self.encoder(x)
if isinstance(features, (tuple, list)):
features = features[0]
embeddings = self.projector(features)
return F.normalize(embeddings, dim=1)
@torch.no_grad()
def encode_image(self, x: torch.Tensor) -> torch.Tensor:
"""
Convenience method for extracting normalized image embeddings.
"""
self.eval()
return self.forward(x)
if __name__ == "__main__":
## Example usage of VesselReIDModel
DEVICE = ("cuda" if torch.cuda.is_available() else "cpu")
# Download model from Hugging Face
model = VesselReIDModel.from_pretrained(MODEL_ID)
model = model.to(DEVICE)
model.eval()
# Random image smoke test
image = torch.randn(1, 3, 224, 224, device=DEVICE)
with torch.no_grad():
embedding = model(image)
print("Embedding shape:", embedding.shape)
print("Embedding norm:", embedding.norm(dim=1))
```
Expected output:
```
Embedding shape: torch.Size([1, 256])
Embedding norm: tensor([1.])
```
The model returns a 256-dimensional L2-normalized embedding. These embeddings can be compared using cosine similarity for vessel re-identification and image retrieval.
## Dataset
This model is trained on the [VesselReID Dataset](https://github.com/vsislab/VesselReID) with about 30,587 images over 1,248 unique vessels (624 for training, 624 for testing).
## Evaluation
Evaluation code will be published.
Comparison of representative vessel re-identification methods on the VesselReID benchmark dataset:
| Methods | R1\*↑ | R5\*↑ | R10\*↑ | mAP\*↑ |
|---|---:|---:|---:|---:|
| BNN | 63.8 | 85.3 | 90.9 | 50.7 |
| PAGS | 66.2 | 85.7 | 90.9 | 53.9 |
| MCL | 63.9 | 82.1 | 82.1 | 45.3 |
| Trans-ReID | 68.2 | 86.3 | 91.1 | 58.7 |
| PFD-Net | 66.1 | 84.9 | 90.2 | 49.2 |
| AP-Net | 62.6 | 83.3 | 89.6 | 50.1 |
| Tran-Aligned | 64.3 | 82.8 | 89.4 | 51.8 |
| MCFormer | 72.8 | 88.9 | 93.1 | 63.4 |
| ResNet50 (**Ours**) | 58.1 | 81.9 | 87.5 | 36.5 |
| ConvNeXt DINOv2 (**Ours**) | 77.7 | 93.9 | 65.3 | 65.3 |
| ViT DINOv3 (**Ours**) | **83.4** | **95.5** | **97.6** | **68.1** |
\* Best result is in bold and second-best result is underlined.
Further information about the metrics and the cited models can be found in the paper.
## License
This model uses the pretrained `DINOv3 ViT-B/16` backbone `timm/vit_base_patch16_dinov3.lvd1689m`, which originates from Meta's DINOv3 project. The backbone was pretrained on the LVD-1689M dataset.
The pretrained DINOv3 weights are distributed under the `DINOv3 License`. This model incorporates these pretrained weights, and their applicable licensing and redistribution terms therefore apply.
* **Upstream model**: [timm/vit_base_patch16_dinov3.lvd1689m](https://huggingface.co/timm/vit_base_patch16_dinov3.lvd1689m)
* **Original model**: Meta DINOv3 ViT-B/16
* **Pretraining dataset**: LVD-1689M
* **Upstream license**: [DINOv3 License](https://ai.meta.com/resources/models-and-libraries/dinov3-license/)
For the complete license terms, please refer to the DINOv3 License and the official DINOv3 repository.
This model is not an independently initialized network; its backbone is initialized from the pretrained DINOv3 checkpoint. Users redistributing or using this model should review and comply with the applicable DINOv3 License terms.ù
## Citation
```bibtex
@inproceedings{sangiorgi2026detection,
author = {Marco Sangiorgi},
title = {Detection and Metric Learning from Pseudo-Labels for Unsupervised Maritime Vessel Re-Identification},
booktitle = {2026 IEEE International Conference on Advanced Video and Signal-Based Systems (AVSS)},
year = {2026},
publisher = {IEEE},
address = {Lecce, Italy}
}
```