DINO-style self-supervised pretraining for OCT B-scan images, plus curve head (LoRA) post-train stage.
dinoct/: Python package (models, data, training)configs/: YAML configs (merged:configs/ssl_default_config.yaml+configs/train/oct.yaml)eval/: evaluation entrypointstools/: export and dataset-maintenance utilities
- Python:
>=3.12 - CUDA: single GPU
This repo uses uv:
uv sync
uv run python -m dinoct --helpDefault expected layout under data/oct/:
data/oct/raw/*.jpgdata/oct/background/*.jpgdata/oct/labeled/<image_stem>.txt(optional; marks an image as labeled)data/oct/extra/entries.npy(metadata cache; regenerated each run)data/oct/extra/splits.csv(paper train/val/test assignment)
Each label file should contain either:
- 500 floats (one per column), or
- a 500×2 table
(x, y)(the second column is used).
You can change the dataset paths via the dataset string: OCT:root=<root>[:extra=<extra>] (see configs/train/oct.yaml).
In that string, root/extra refer to dataset directories (not the repo root).
The dataset name token is case-insensitive.
Replication experiments expect data/oct/extra/splits.csv.
SSL pretraining uses split=train, while post-train reads the explicit train and val assignments from that file.
If splits.csv is already present, you can skip split generation.
If you need to regenerate it, run:
uv run python tools/data/build_oct_manifest.py --dir data/oct
uv run python tools/data/build_oct_splits.py --dir data/oct --seed 0 --train-frac 0.7 --val-frac 0.15Use the single replication entrypoint:
uv run python eval/run_paper.py --helpAll paper results use the checked-in default config at configs/train/oct.yaml.
The replication workflow below is intended to be run without extra optimizer or schedule overrides.
Recommended replication order:
- Make sure
data/oct/extra/splits.csvexists. If it is already present, skip this step.
uv run python tools/data/build_oct_manifest.py --dir data/oct
uv run python tools/data/build_oct_splits.py --dir data/oct --seed 0 --train-frac 0.7 --val-frac 0.15- Make sure the default pretrained backbone exists at:
outputs/pretrain/dinov3_pretrain.pthYou can grab it from Github releases or generate it by running the default training config once:
uv run python -m dinoct \
--config configs/train/oct.yaml \
--output-dir outputsThis writes both outputs/pretrain/dinov3_pretrain.pth and the default outputs/post_train/ checkpoint.
eval/run_paper.py reuses the backbone checkpoint from outputs/pretrain/dinov3_pretrain.pth.
- Run the paper tables and benchmarks from
eval/run_paper.py.
Main paper commands:
uv run python eval/run_paper.py low-data --resume
uv run python eval/run_paper.py ablations --resume
uv run python eval/run_paper.py robustness
uv run python eval/run_paper.py skin-db-export --overwrite
uv run python eval/run_paper.py skin-db-paper-dl
uv run python eval/run_paper.py skin-db-cv --layer upper --resume
uv run python eval/run_paper.py skin-db-cv --layer dej --resumeWhat each command produces:
low-data- runs the DINOCT / UNET / FCBR data-efficiency experiments
- writes outputs under
outputs/data_efficiency/ - fills the paper tables under
outputs/paper_tables/data_efficiency_*
ablations- runs the final single-component ablation around
configs/train/oct.yaml - writes
outputs/ablations/final_component_ablation/final_component_ablation.csv - writes
outputs/ablations/final_component_ablation/final_component_ablation.tex
- runs the final single-component ablation around
robustness- runs clean + synthetic artifact evaluation for the default DINOCT checkpoint
- writes under
outputs/robustness/dinoct/test/
skin-db-export- exports
skin_db.matinto:data/skin_db/upper_gtdata/skin_db/dej_gt
- exports
skin-db-paper-dl- evaluates the paper-provided
dlpredictions fromskin_db.mat - writes
outputs/skin_db_mat_dl_eval/paper_dl_summary.csv
- evaluates the paper-provided
skin-db-cv --layer upper|dej- runs the patient-wise external CV comparison for DINOCT and the paper-style U-Net baseline
- writes under:
outputs/frontiers_cv_upper_gt/outputs/frontiers_cv_dej_gt/
Expected external-data input:
data/skin_db/skin_db.matdata/skin_db/plot_results.mdata/skin_db/readme.txt
Evaluate a fused curve checkpoint on val or test using the paper metrics:
MAEP95- signed
Bias |Bias|Acc@2pxAcc@4pxSpikeRate@kappa
UV_CACHE_DIR=/tmp/uv-cache uv run python eval/evaluate_curve.py \
--config configs/train/oct.yaml \
--curve-ckpt outputs/post_train/fused_curve_best.pth \
--split testThis writes:
per_scan_metrics.csvper_recording_metrics.csvsummary.json
If --spike-kappa is not provided, the evaluator estimates kappa from the reference centerlines on the validation split using the configured quantile.
Train a supervised learned baseline with the same OCT splits, Gaussian targets, and evaluation metrics:
UV_CACHE_DIR=/tmp/uv-cache uv run python eval/train_learned_baseline.py \
--config configs/train/oct.yaml \
--model-type unetor
UV_CACHE_DIR=/tmp/uv-cache uv run python eval/train_learned_baseline.py \
--config configs/train/oct.yaml \
--model-type fcbrBoth scripts write checkpoints under outputs/learned_baselines/<model_type>/. Evaluate them with the same curve evaluator:
UV_CACHE_DIR=/tmp/uv-cache uv run python eval/evaluate_curve.py \
--curve-ckpt outputs/learned_baselines/unet/curve_best.pth \
--split testThe interactive curve label editor requires matplotlib:
uv sync --extra label
uv run python tools/data/curve_labeler.py --dir data/octTrain the default OCT recipe end to end:
uv run python -m dinoct \
--config configs/train/oct.yaml \
--output-dir outputs/run1This uses the values already defined in configs/train/oct.yaml and runs SSL pretrain followed by post-train.
Outputs:
outputs/run1/pretrain/dinov3_pretrain.pthoutputs/run1/pretrain/train.log,metrics.csv,config_used.yamloutputs/run1/post_train/fused_curve.pthoutputs/run1/post_train/fused_curve_best.pthoutputs/run1/post_train/val_summary.json
To rerun only the curve post-train stage with an existing backbone, keep the same config and use:
uv run python -m dinoct \
--config configs/train/oct.yaml \
--output-dir outputs/run1 \
--post-train-only \
--pretrained-backbone outputs/run1/pretrain/dinov3_pretrain.pthuv run python tools/export_model.py --model outputs/run1/post_train/fused_curve_best.pth --outdir exportsDataset are available from https://huggingface.co/datasets/rjbaw/oct and using the huggingface dataset loader.
Set train.dataset_path to OCT:hub=rjbaw/oct (or include root=... for local-first).
Apache-2.0.
This project includes alot of code derived from Meta Platforms, Inc. and affiliates' DINOv2 and DINOv3 repositories, licensed under the Apache License, Version 2.0.
