PyTorch implementation of Fast Dynamic Prototypes for Unsupervised Anomaly Detection and Localization (ECCV 2026).
conda create -n fdp python==3.10.16 -y
conda activate fdp
pip install torch torchvision --index-url https://download.pytorch.org/whl/cu126
pip install -r requirements.txtConvert each source dataset into its direct destination below data/:
python utils/mvtec3d2mvtecad.py --source <mvtec-3d-source> --target data/mvtec3d
python utils/visa2mvtecad.py --split_type 1cls --data_dir <visa-source> --save_dir data/visa --split_csv <visa-source>/split_csv/1cls.csv
python utils/realiad2mvtecad.py --json_dir <realiad-source>/realiad_jsons --source_dir <realiad-source>/realiad_1024 --output_dir data/realiadThe expected processed category layout is:
data/<dataset>/<category>/
|-- train/good/*.png
|-- test/good/*.png
|-- test/<defect-type>/*.png
`-- ground_truth/<defect-type>/*_mask.png
We provide pre-processed data available at: Download Link
By default, DINOv3-small is loaded from encoder_weights/small.safetensors. If the local file is unavailable and network download is desired, set this value in Configs.py:
DEFAULT_ALLOW_BACKBONE_DOWNLOAD = TrueThis path requires timm>=1.0.20. The auxiliary ResNet18 backbone is loaded through torchvision and may download ImageNet weights on first use.
We provide pre-downloaded weights available at: Download Link
Generate BiRefNet foreground masks into cache/<dataset>:
python utils/generate_foreground_masks.py \
--data_dir data/mvtecad \
--output_root cache/mvtecad \
--target-category bottle cable capsule hazelnut metal_nut pill screw toothbrush transistor zipper \
--device cuda:0We provide pre-processed foreground mask available at: Download Link
FDP/
|-- data/
| |-- dtd/images/...
| |-- mvtecad/<category>/{train,test,ground_truth}/...
| |-- mvtec3d/<category>/{train,test,ground_truth}/...
| |-- visa/<category>/{train,test,ground_truth}/...
| `-- realiad/<category>/{train,test,ground_truth}/...
|-- cache/
| `-- <dataset>/<category>/train/good/...
|-- encoder_weights/
| |-- small.safetensors
| `-- modelscope/...
`-- logs/
`-- <dataset>/
|-- prototype_banks/
| `-- <category>_8192.pth
`-- <mode>/
|-- training/
|-- checkpoints/
| |-- fdp/<category>/*.pth
| `-- seghead/<category>/*.pth
|-- results/metrics.json
`-- samples/<category>/<checkpoint>/*.png
All project paths are defined in Configs.py; no project path is read from an environment variable. Edit the user-settings block directly before running an experiment:
PROJECT_ROOT = Path(__file__).resolve().parent
DATA_ROOT = PROJECT_ROOT / 'data'
CACHE_ROOT = PROJECT_ROOT / 'cache'
LOGS_ROOT = PROJECT_ROOT / 'logs'
ENCODER_WEIGHTS_ROOT = PROJECT_ROOT / 'encoder_weights'
DEFAULT_DATASET = 'mvtecad' # mvtecad / mvtec3d / visa / realiad
DEFAULT_MODE = 'multi' # multi / single / cross
DEFAULT_DEVICE = 'cuda:0'
DEFAULT_BATCH_SIZE = 16
DEFAULT_NUM_WORKERS = 8
DEFAULT_ALLOW_BACKBONE_DOWNLOAD = False
DEFAULT_SAVE_VISUALIZATION_SAMPLES = True
DEFAULT_NUM_VISUALIZATION_SAMPLES = 8Set DEFAULT_DATASET and DEFAULT_MODE in Configs.py, then run:
python prototypes_bank.py
python train.py
python train_seg.py
python test.py
python results.pyWe provide trained weights available at: Download Link
| Field | Default | Meaning |
|---|---|---|
batch_size |
2 |
Batch size |
num_workers |
8 |
Data-loader workers |
num_visualization_samples |
8 |
Test samples saved per class and checkpoint under logs/.../samples/ |