Dinomaly2

May 30, 2026 · View on GitHub

PyTorch Implementation of "One Dinomaly2 Detect Them All: A Unified Framework for Full-Spectrum Unsupervised Anomaly Detection". (arxiv 2025)

  • Give me a ⭐️ if you like it.
  • This project is currently released under Apache-2.0 License. If your method is based on Dinomaly series, please acknowledge it in your work (papers, products, patents, competitions, etc.), preferably as a "Preliminary" section.
  • Preview version. There might be some bugs, and some config is not exactly as in the paper.

img.png

News

  • 10.2025: We are thrilled to present the extended version of Dinomaly, now evolved into Dinomaly2!!! We introduce the first unified framework for universal UAD that seamlessly handles diverse data modalities (2D, multi-view, RGB-3D, RGB-IR), task settings (single-class, multi-class, inference-unified multi-class, few-shot) and application domains (industrial, biological, outdoor). Of course, Dinomaly2 achieves unprecedented UAD performance. Check it out😎
  • 05.2026: Preview Code released🎉
  • 05.2026: We now support super-large multi-class datasets: Real-IAD_Variety (160 classes) and ADNet (380 classes). How great is that!🚀

img.png

1. Environments

Create a new conda environment and install required packages.

conda create -n my_env python=3.10
conda activate my_env
pip install -r requirements.txt

You can also try requirements2.txt which is simpler.

Our experiments are conducted on NVIDIA GeForce RTX 3090/4090/5090.

2. Prepare Datasets

Noted that ../ is the upper directory of Dinomaly code. It is where we keep all the datasets by default. You can also alter it according to your need, just remember to modify the data_path in the code.

MVTec AD

Download the MVTec-AD dataset from URL. Unzip the file to ../mvtec_anomaly_detection.

|-- mvtec_anomaly_detection
    |-- bottle
    |-- cable
    |-- capsule
    |-- ....

VisA

Download the VisA dataset from URL. Unzip the file to ../VisA/. Preprocess the dataset to ../VisA_pytorch/ in 1-class mode by their official splitting code.

You can also run the following command for preprocess, which is the same to their official code.

python ./prepare_data/prepare_visa.py --split-type 1cls --data-folder ../VisA --save-folder ../VisA_pytorch --split-file ./prepare_data/split_csv/1cls.csv

../VisA_pytorch will be like:

|-- VisA_pytorch
    |-- 1cls
        |-- candle
            |-- ground_truth
            |-- test
                    |-- good
                    |-- bad
            |-- train
                    |-- good
        |-- capsules
        |-- ....

BTAD

Download the BTAD dataset from URL. Unzip the file to ../BTech_Dataset_transformed.

MPDD

Download the MPDD dataset from URL. Unzip the file to ../MPDD.

MIAD

Download the MIAD dataset from URL. Unzip the file to ../MIAD.

Real-IAD

Download Real-IAD from HF Link.

Download and unzip realiad_1024 and realiad_jsons in ../Real-IAD. ../Real-IAD will be like:

|-- Real-IAD
    |-- realiad_1024
        |-- audiokack
        |-- bottle_cap
        |-- ....
    |-- realiad_jsons
        |-- realiad_jsons
        |-- realiad_jsons_sv
        |-- realiad_jsons_fuiad_0.0
        |-- ....

Real-IAD_Variety

Download Real-IAD_Variety from HF Link.

Download and unzip realiadvariety_raw and realiadvariety_jsons in ../Real-IAD_Variety.

Unzip all zip files. Preprocess realiadvariety_raw (big raw images) to realiadvariety_1024 using prepare_data/preprocess_realiadvar_mp. The training will be very slow without downsampling to 1024.

../Real-IAD_Variety will be like:

|-- Real-IAD
    |-- realiadvariety_1024
        |-- 2pin_block_plug
        |-- 3pin_aviation_connector
        |-- ....
    |-- realiad_jsons
        |-- 2pin_block_plug.json
        |-- 3pin_aviation_connector.json
        |-- ....

MANTA-Tiny

Download MANTA-Tiny from URL.

Unzip all files to ../MANTATiny will be like:

|-- MANTATiny
    |-- agriculture
        |-- maize
        |-- paddy
        |-- soybean
        |-- ....
    |-- electronics
        |-- block_inductor
        |-- copper_standoff
        |-- ....
    |-- ....

MVTec3D

Download the MVTec3D dataset from URL. Unzip the file to ../mvtec_3d.

First, run prepare_data/preprocess_mvtec3d_1. Then run prepare_data/preprocess_mvtec3d_2. It will generalize depth maps to e.g. mvtec_3d/bagel/test/hole/z

MulsenAD

Download the MulSenAD dataset from URL. Unzip the file to ../MulSen_AD.

3. Run Experiments

2D MUAD (Conventional)

python dinomaly_2D.py --data_path ../mvtec_anomaly_detection --image_size 448 --crop_size 392 --save_name dinomaly2_mvtec
python dinomaly_2D.py --data_path ../VisA_pytorch/1cls --image_size 448 --crop_size 392 --save_name dinomaly2_visa
python dinomaly_2D.py --data_path ../MPDD --image_size 448 --crop_size 392 --save_name dinomaly2_mpdd
python dinomaly_2D.py --data_path ../BTech_Dataset_transformed --image_size 392 --crop_size 392 --save_name dinomaly2_btad
python dinomaly_2D.py --data_path ../MIAD --image_size 392 --crop_size 392 --save_name dinomaly2_miad
python dinomaly_2D.py --data_path ../Uni-Medical --image_size 280 --crop_size 280 --save_name dinomaly2_unimed
...

Multi-View MUAD

python dinomaly_multiview.py --data_path ../Real-IAD --image_size 448 --crop_size 392 --save_name dinomaly2_realiad
python dinomaly_multiview.py --data_path ../Real-IAD_Variety --image_size 280 --crop_size 280 --save_name dinomaly2_realiadvar
python dinomaly_multiview.py --data_path ../MANTATiny --image_size 280 --crop_size 280 --save_name dinomaly2_manta

RGB-3D MUAD

python dinomaly_mvtec3d.py --data_path ../mvtec_3d --image_size 448 --crop_size 392 --save_name dinomaly2_mvtec3d

RGB-IR MUAD

python dinomaly_mulsen.py --data_path ../MulSen_AD --image_size 448 --crop_size 392 --save_name dinomaly2_mulsen

Fewshot MUAD

python dinomaly_fewshot.py --data_path ../mvtec_anomaly_detection --image_size 448 --crop_size 392 --shots 4 --save_name dinomaly2_mvtec_fs4

Some note

A. Training Stability

We now set the learning rate of first layer of NB to a smaller value for training stablility.

If you encounter training instability or Loss=NaN during training on other datasets (very rare in common datasets), simply use a smaller eps (1e-8 by default) in the LinearAttention2 module:

z = 1.0 / (torch.einsum('...sd,...d->...s', q, k.sum(dim=-2)) + self.eps)

B. Using other backbones, e.g., DINOv3

The following lines in ./models/uad/Dinomaly is for DINOv3.

  if self.use_get_intermediate:
      with torch.no_grad():
          en_list = self.encoder._get_intermediate_layers_not_chunked(x, self.target_layers)

Just set use_get_intermediate=True in the main code if the encoder is DINOv3.

For different backbone (maybe you want to use newer models), the image normalization may be different. For example, for TIPS (ICLR 2025), the normalize should be:

data_transform, gt_transform = get_data_transforms(image_size, crop_size, mean_train=(0., 0., 0.), std_train=(1., 1., 1.))

Acknowledgment

Great thanks to ADer, adeval, anomalib, and many other repositories (if I missed)

Citation

@inproceedings{guo2025dinomaly,
  title={Dinomaly: The less is more philosophy in multi-class unsupervised anomaly detection},
  author={Guo, Jia and Lu, Shuai and Zhang, Weihang and Chen, Fang and Li, Huiqi and Liao, Hongen},
  booktitle={Proceedings of the Computer Vision and Pattern Recognition Conference},
  pages={20405--20415},
  year={2025}
}

@article{guo2025one,
  title={One Dinomaly2 Detect Them All: A Unified Framework for Full-Spectrum Unsupervised Anomaly Detection},
  author={Guo, Jia and Lu, Shuai and Fan, Lei and Li, Zelin and Di, Donglin and Song, Yang and Zhang, Weihang and Zhu, Wenbing and Yan, Hong and Chen, Fang and Li, Huiqi and Liao, Hongen},
  journal={arXiv preprint arXiv:2510.17611},
  year={2025}