Skip to content

Latest commit

History

14 Commits

Folders and files

NameName
Last commit message
Last commit date

Repository files navigation

[WACV 2026] FlowCLAS: Enhancing Normalizing Flow-Based Anomaly Segmentation Via Contrastive Learning

Official repository for FlowCLAS.

arXivPaperWebsiteVideo

All commands below assume the working directory is src/ (where trainer_cli.py lives).

Environment setup

Docker

The image is defined under docker/. It uses a multi-stage build (CUDA 12.8, PyTorch 2.7, MMCV, SAM2, and project Python dependencies). GPU access at runtime requires the NVIDIA Container Toolkit.

Build (from the repository root):

bash scripts/docker_build.bash

Equivalent manual command (paths are relative to the repo root; the build context must be the docker/ directory):

RENDER_GID=$(getent group render | cut -d: -f3)
docker build \
--network=host \
--build-arg "USERNAME=$(whoami)" \
--build-arg CREATE_USER=true \
--build-arg "WORKDIR_PATH=/home/$(whoami)" \
--build-arg "RENDER_GID=${RENDER_GID}" \
-t flowclas \
-f docker/Dockerfile \
docker
Flag / argumentPurpose
--network=hostUses the host network during build (helps reach package indexes).
CREATE_USER=trueCreates a container user matching your host username (for volume permissions).
WORKDIR_PATHSets the container working directory to your home path inside the image.
RENDER_GIDAdds the container user to a render group with the host’s GID (for GPU/GL access).

The image is tagged flowclas. To start an interactive container with project directories mounted, run from the repository root:

bash scripts/docker_run.bash /path/to/your/datasets

Paths in the YAML configs below are relative to src/ (for example, ../data/cityscapes~/data/cityscapes inside the container).

Dataset preparation

Cityscapes

  1. Register and download the gtFine split (and matching leftImg8bit images) from the Cityscapes dataset.
  2. (Recommended) Preprocess labels to the common 19-classtrainId convention using cityscapesScripts — install the package, then run createTrainIdLabelImgs.py on your download. FlowCLAS remaps raw labelIds to 19 training classes in code; generating *_gtFine_labelTrainIds.png keeps your tree aligned with the standard Cityscapes tooling.
  3. Set city_root in src/configs/base/cityscapes_coco.yaml to the dataset root that contains leftImg8bit/ and gtFine/ (Torchvision layout).

Expected layout:

cityscapes/
├── leftImg8bit/
│ ├── train/<city>/*.png
│ └── val/<city>/*.png
└── gtFine/
├── train/<city>/*_gtFine_labelIds.png
└── val/<city>/*_gtFine_labelIds.png

ALLO

A new version of the ALLO dataset will be released soon. For the current benchmark, set allo_root, train_dir, and test_dir in src/configs/base/allo_coco.yaml.

COCO (outlier exposure)

COCO images are used as an OoD proxy during training (paste/mix with in-distribution scenes). You can either prepare them yourself or use the preprocessed archive on Google Drive (same folder as Fishyscapes and Road Anomaly).

Option A — prepare from scratch (Meta-OoD):

  1. Download COCO 2017 train images and instance annotations.
  2. Run preparation/prepare_coco_segmentation.py to build binary ood_seg masks for images without instances that overlap Cityscapes train classes.

Option B — download preprocessed data from the Google Drive folder and extract under your coco_root.

In both cases, set coco_root in the data config you use (cityscapes_coco.yaml and/or allo_coco.yaml).

Expected layout:

coco/
├── annotations/
│ ├── instances_train2017.json
│ └── ood_seg_train2017/ # optional; masks may also live at repo root
├── ood_seg_train2017/*.png # required by FlowCLAS loaders
└── train2017/*.jpg

You can override any root on the CLI, for example:

--data.init_args.city_root /path/to/cityscapes \
--data.init_args.coco_root /path/to/coco

Other benchmarks (preprocessed)

Preprocessed Fishyscapes, Road Anomaly, and COCO (see above) are available on Google Drive. After extracting, point the paths in cityscapes_coco.yaml:

Config keyRole
fishy_rootFishyscapes Lost & Found split (images/, labels/)
roadanomaly_rootRoad Anomaly frames and semantic labels
smiyc_rootSegment Me If You Can (AnomalyTrack + ObstacleTrack)

Expected layouts (as used by this repo):

fishyscapes/
├── LostAndFound/
│ ├── images/*.png
│ └── labels/*.png
└── Static/
├── images/*.png
└── labels/*.png
RoadAnomaly/
└── frames/
├── <clip>.jpg
└── <clip>.labels/
└── labels_semantic.png
smiyc/
├── dataset_AnomalyTrack/
│ ├── images/
│ └── labels_masks/
└── dataset_ObstacleTrack/
├── images/
└── labels_masks/

Evaluation uses fishy_root for Fishyscapes (default: ../data/fishyscapes/LostAndFound), plus smiyc_root and roadanomaly_root for the other test benchmarks in the Cityscapes training pipeline.

Weights and checkpoints

Pre-trained backbones, SAM2, and FlowCLAS checkpoints are available on Google Drive. After downloading, place files under the repo root as follows (paths are relative to src/ in the configs):

FileDestination
rein_dinov2l_allo.pthweights/rein_dinov2l_allo.pth
rein_dinov2l_city.pthweights/rein_dinov2l_city.pth
sam2.1_hiera_large.ptmisc/weights/sam2.1_hiera_large.pt
best_allo.ckptweights/flowclas/best_allo.ckpt
best_cityscapes.ckptweights/flowclas/best_cityscapes.ckpt

Training reads backbone_ckpt from flowclas_allo.yaml / flowclas_city.yaml; inference passes --ckpt to a FlowCLAS checkpoint under weights/flowclas/.

Results

Pre-trained checkpoints and pixel-level metrics on the official test splits (checkpoints from Google Drive):

BenchmarkData configModel configCheckpointPixel APPixel FPR95
ALLOconfigconfigbest_allo.ckpt88.46.6
Fishyscapesconfigconfigbest_cityscapes.ckpt88.80.7
Road Anomalyconfigconfigbest_cityscapes.ckpt93.03.3

Fishyscapes and Road Anomaly are evaluated with the same Cityscapes-trained best_cityscapes.ckpt; use the inference commands in Road Anomaly Segmentation below.

Training

Replace <num_devices>, <num_workers>, and <seed> with values for your setup.

ALLO

python3 trainer_cli.py fit \
--data configs/base/allo_coco.yaml \
-c configs/base/base.yaml \
--trainer.devices <num_devices> \
--data.num_workers <num_workers> \
-c configs/flowclas/flowclas_allo.yaml \
--seed_everything <seed> \
--experiment.name flowclas_allo \
--experiment.project_name ALLO

Cityscapes (Road Anomaly / Fishyscapes)

python3 trainer_cli.py fit \
--data configs/base/cityscapes_coco.yaml \
-c configs/base/base.yaml \
--trainer.devices <num_devices> \
--data.num_workers <num_workers> \
-c configs/flowclas/flowclas_city.yaml \
--seed_everything <seed> \
--experiment.name flowclas_city \
--metrics_on_cpu \
--no_sigmoid

Examples

Paper-style runs using alternate experiment configs (same flag set as above):

ALLO

python3 trainer_cli.py fit \
--data configs/base/allo_coco.yaml \
-c configs/base/base.yaml \
--trainer.devices 4 \
--data.num_workers 8 \
-c configs/flowclas/flowclas_allo.yaml \
--seed_everything 42 \
--experiment.name flowclas_allo \
--experiment.project_name flowclas_ALLO

Cityscapes

python3 trainer_cli.py fit \
--data configs/base/cityscapes_coco.yaml \
-c configs/base/base.yaml \
--trainer.devices 2 \
--data.num_workers 8 \
-c configs/flowclas/flowclas_city.yaml \
--seed_everything 42 \
--experiment.name flowclas_city \
--experiment.project_name flowclas_Cityscapes \
--metrics_on_cpu \
--no_sigmoid

Inference

Replace <num_devices>, <num_workers>, <seed>, and <ckpt> with values for your setup.

ALLO

python3 trainer_cli.py test \
--data configs/base/allo_coco.yaml \
-c configs/base/base.yaml \
--trainer.devices <num_devices> \
--data.num_workers <num_workers> \
-c configs/flowclas/flowclas_allo.yaml \
--seed_everything <seed> \
--experiment.name flowclas_allo \
--data.eval_batch_size 2 \
--experiment.logger [csv] \
--trainer.precision 32 \
--ckpt <ckpt>

Road Anomaly Segmentation (Fishyscapes & Road Anomaly)

python3 trainer_cli.py test \
--data configs/base/cityscapes_coco.yaml \
-c configs/base/base.yaml \
--trainer.devices <num_devices> \
--data.num_workers <num_workers> \
-c configs/flowclas/flowclas_city.yaml \
--seed_everything <seed> \
--experiment.name flowclas_city \
--data.eval_batch_size 2 \
--metrics_on_cpu \
--no_sigmoid \
--experiment.logger [csv] \
--trainer.precision 32 \
--ckpt <ckpt>

Examples

Download checkpoints from Google Drive first (see Weights and checkpoints). Example inference commands (same flag set as above):

ALLO

python3 trainer_cli.py test \
--data configs/base/allo_coco.yaml \
-c configs/base/base.yaml \
--trainer.devices 1 \
--data.num_workers 8 \
-c configs/flowclas/flowclas_allo.yaml \
--seed_everything 42 \
--experiment.name flowclas_allo_test \
--data.eval_batch_size 2 \
--experiment.logger [csv] \
--trainer.precision 32 \
--ckpt ../weights/flowclas/best_allo.ckpt

Road Anomaly Segmentation (Fishyscapes & Road Anomaly)

python3 trainer_cli.py test \
--data configs/base/cityscapes_coco.yaml \
-c configs/base/base.yaml \
--trainer.devices 1 \
--data.num_workers 1 \
-c configs/flowclas/flowclas_city.yaml \
--seed_everything 42 \
--experiment.name flowclas_city_test \
--data.eval_batch_size 2 \
--metrics_on_cpu \
--no_sigmoid \
--experiment.logger [csv] \
--trainer.precision 32 \
--ckpt ../weights/flowclas/best_cityscapes.ckpt

Citation

If you use FlowCLAS in your research, please cite:

@inproceedings{lee2026flowclas,
title={FlowCLAS: Enhancing Normalizing Flow-Based Anomaly Segmentation Via Contrastive Learning},
author={Lee, Chang Won and Leveugle, Selina and Grouchy, Paul and Langley, Chris and Stolpner, Svetlana and Kelly, Jonathan and Waslander, Steven L},
booktitle={Proceedings of the IEEE/CVF Winter Conference on Applications of Computer Vision},
pages={6998--7007},
year={2026}
}

About

[WACV 2026] Official Repository for "FlowCLAS: Enhancing Normalizing Flow-Based Anomaly Segmentation Via Contrastive Learning"

Resources

Stars

3 stars

Watchers

0 watching

Forks

Contributors

Languages