Dinomaly是一个基于“少即是多”理念的极简主义多类别无监督异常检测框架。它旨在解决一个核心痛点:传统方法需要为每个类别训练独立模型,存储成本高;而现有多类别统一模型性能又显著落后。Dinomaly的创新之处在于,它仅使用纯Transformer架构,不依赖任何复杂设计或额外模块,却首次让多类别模型的性能逼近甚至超越了需要为每个类别单独训练的传统模型。
该模型的成功源于四个简单而关键的设计:首先,利用在大规模数据上预训练的基础Transformer(如DINOv3)来提取通用特征。其次,巧妙地直接启用Transformer的MLP层中内置的Dropout功能作为“噪声瓶颈”,这有效防止了解码器对异常样本也产生过度泛化的重建。再次,采用“无法聚焦”的线性注意力机制,使其难以精确复制异常区域的细节。最后,采用“宽松重建”策略,不强制解码器逐点严格模仿编码器,给予模型更多自由度来学习全局正常模式。
在MVTec-AD、VisA等多个权威基准测试中,Dinomaly取得了突破性性能,其极简设计还带来了出色的可扩展性,模型性能随规模增大而提升。这项工作表明,通过精心协调简单而基础的组件,可以构建出强大且通用的AI模型,为异常检测的实际部署提供了更简洁高效的解决方案。
本仓库只保留 Dinomaly 到 ONNX/OM 迁移所需的导出适配代码和说明,不直接分发 DINO/DINOv2/DINOv3/BEiT 等第三方源码。导出时需要按本文档拉取 cnulab/Dinomaly 固定快照到本地 third_party/Dinomaly,再从 PyTorch 权重导出 ONNX。当前已验证的导出输入尺寸为 1,3,448,448,最终 ONNX 文件为 saved_results/Dinomaly_base/dinomaly_sim.onnx。
硬件型号:Atlas 800 3000 (300I Duo卡)
软件版本:
推理镜像下载:https://www.hiascend.com/developer/ascendhub/detail/af85b724a7e5469ebd7ea13c3439d48f

选择硬件对应的推理镜像

Docker启动命令:
docker run -it -d --net=host --shm-size=1g \
--privileged \
--name <container-name> \
-v /usr/local/Ascend/driver:/usr/local/Ascend/driver:ro \
-v /usr/local/sbin:/usr/local/sbin:ro \
-v /path-to-weights:/path-to-weights:ro \
mindie:1.0.0-800I-A2-py311-openeuler24.03-lts bash如果只需要在本地导出 ONNX,可先使用普通 Python 环境完成导出;ATC 转 OM 再放到带 CANN 的昇腾环境中执行。当前本地 ONNX 导出已验证环境如下:
在仓库根目录执行:
python3.10 -m venv .venv
source .venv/bin/activate
python -m pip install --upgrade pip
python -m pip install -r requirements.txt
python -m pip check导出 ONNX 以及之前的操作也可以在本地用 Windows 环境执行。
Windows PowerShell 备注:
python -m venv .venv
.\.venv\Scripts\python.exe -m pip install --upgrade pip
.\.venv\Scripts\python.exe -m pip install -r requirements.txt
.\.venv\Scripts\python.exe -m pip checkpip check 输出 No broken requirements found. 就说明 Python 依赖安装正常。
Dinomaly模型仓库:https://github.com/guojiajeremy/Dinomaly

由模型仓库的README得知,需要到 cnulab 的 fork 仓拉取支持 DINOv3 算法的模型。本仓库不再内置 DINO/DINOv2/DINOv3/BEiT 等第三方源码,导出前请在本地拉取固定快照:
mkdir -p third_party
git clone https://github.com/cnulab/Dinomaly.git third_party/Dinomaly
git -C third_party/Dinomaly checkout 9535c38b1f2f4d1c1576a671323eed7bcd65e67c导出 ONNX 以及之前的操作也可以在本地用 Windows 环境执行。
Windows PowerShell 备注:
New-Item -ItemType Directory -Force -Path .\third_party | Out-Null
git clone https://github.com/cnulab/Dinomaly.git .\third_party\Dinomaly
git -C .\third_party\Dinomaly checkout 9535c38b1f2f4d1c1576a671323eed7bcd65e67c该提交是当前导出流程验证使用的 cnulab/Dinomaly 快照。固定到 commit 可以避免上游 master 更新后引入不可控变化。
上游快照中导出相关源码主要包括:
dataset.py
utils.py
models/
dinov1/
dinov2/
dinov3/
beit/
optimizers/
flops_profiler/
dinomaly_mvtec_uni_base.py
dinomaly_mvtec_uni_large.py这些目录作为本地 third_party/Dinomaly 快照使用,不提交到本仓库。同步 DINOv3 或 cnulab fork 的更新时,需要先在本地对比并验证导出结果,再更新 README 中的快照 commit。后续长期维护时,建议遵循以下方式:
第三方源码许可证也需要分开看待:dinov3/ 文件头声明受 DINOv3 License Agreement 约束;dinov2/ 多数文件声明为 Apache License 2.0;beit/ 中包含 MIT 来源说明。发布或对外交付时,本仓库不直接分发这些源码,使用者按上游仓库和对应许可证自行获取。
当前 ONNX 导出脚本 export_onnx.py 的主路径依赖 third_party/Dinomaly/dinov3/ 来构建 DINOv3 encoder,并依赖本仓库的 models/vision_transformer.py、models/uad.py 构建 Dinomaly decoder。third_party/ 已加入 .gitignore,不要把该目录提交到对外开源仓库。
参考DINOv3官方仓库指引获取编码器权重文件:https://github.com/facebookresearch/dinov3

或在HuggingFace下载Safetensors编码器权重文件,并使用以下脚本转换为 PyTorch (.pth):https://huggingface.co/facebook/dinov3-vitb16-pretrain-lvd1689m
import torch
from safetensors.torch import load_file
def safetensors_to_pth(safetensors_path, pth_path):
state_dict = load_file(safetensors_path)
torch.save(state_dict, pth_path)
print(f"转换成功,文件已保存为: {pth_path}")
safetensors_to_pth("model.safetensors", "dinov3_vitb16_pretrain_lvd1689m-73cec8be.pth")实际导出需要两个 .pth 权重文件,放到仓库的 weights/ 目录:
weights/
dinomaly_39.pth
dinov3_vitb16_pretrain_lvd1689m-73cec8be.pth其中 dinov3_vitb16_pretrain_lvd1689m-73cec8be.pth 是 DINOv3 encoder 权重,dinomaly_39.pth 是 Dinomaly 模型权重。如果权重文件在其他目录,复制到当前仓库:
mkdir -p weights
cp "<权重目录>/dinomaly_39.pth" ./weights/dinomaly_39.pth
cp "<权重目录>/dinov3_vitb16_pretrain_lvd1689m-73cec8be.pth" ./weights/dinov3_vitb16_pretrain_lvd1689m-73cec8be.pth检查文件是否到位:
ls -lh weights导出 ONNX 以及之前的操作也可以在本地用 Windows 环境执行。
Windows PowerShell 备注:
New-Item -ItemType Directory -Force -Path .\weights | Out-Null
Copy-Item -LiteralPath "<权重目录>\dinomaly_39.pth" -Destination ".\weights\dinomaly_39.pth" -Force
Copy-Item -LiteralPath "<权重目录>\dinov3_vitb16_pretrain_lvd1689m-73cec8be.pth" -Destination ".\weights\dinov3_vitb16_pretrain_lvd1689m-73cec8be.pth" -Force
Get-ChildItem -File .\weights | Select-Object Name,Length期望至少看到:
dinomaly_39.pth
dinov3_vitb16_pretrain_lvd1689m-73cec8be.pth参考Dinomaly模型仓库和cnulab的fork仓库的README,使用dinomaly_mvtec_uni_base.py或者dinomaly_mvtec_uni_large.py脚本进行预训练,将预训练后得到的pth权重文件保存至weights目录下。
本仓库已提供导出脚本 export_onnx.py。它会加载 weights/dinomaly_39.pth,再加载 weights/dinov3_vitb16_pretrain_lvd1689m-73cec8be.pth 作为 encoder 权重,导出并简化 ONNX。
torch.onnx.export()用于将PyTorch框架中训练好的模型转换为onnx格式。
onnx-simplifier简化后,可以使ONNX模型结构更清晰,减少ATC转换过程中因复杂结构或冗余节点导致的转换错误。
由于300I Duo暂不支持三输入的Einsum算子,当前仓库已经修改 models/vision_transformer.py:
# x = torch.einsum('...de,...sd,...s->...se', kv, q, z)
y = torch.einsum('...de,...sd->...se', kv, q)
x = torch.einsum('...se,...s->...se', y, z)执行导出命令:
source .venv/bin/activate
python export_onnx.py \
--model_path ./weights/dinomaly_39.pth \
--save_dir ./saved_results \
--save_name Dinomaly_base \
--third_party_dir ./third_party/Dinomaly导出 ONNX 以及之前的操作也可以在本地用 Windows 环境执行。
Windows PowerShell 备注:
.\.venv\Scripts\python.exe export_onnx.py --model_path .\weights\dinomaly_39.pth --save_dir .\saved_results --save_name Dinomaly_base --third_party_dir .\third_party\Dinomaly成功后会生成:
saved_results/Dinomaly_base/dinomaly_tmp.onnx
saved_results/Dinomaly_base/dinomaly_tmp_modify.onnx
saved_results/Dinomaly_base/dinomaly_sim.onnx后续转换 OM 时使用 dinomaly_sim.onnx。
导出后建议先用脚本验证 ONNX 是否能被 ONNX Runtime 正常加载。执行:
source .venv/bin/activate
python scripts/validate_onnx.py --model ./saved_results/Dinomaly_base/dinomaly_sim.onnx导出 ONNX 以及之前的操作也可以在本地用 Windows 环境执行。
Windows PowerShell 备注:
.\.venv\Scripts\python.exe scripts\validate_onnx.py --model .\saved_results\Dinomaly_base\dinomaly_sim.onnx如果正常,会看到类似输出:
正在检查ONNX文件: saved_results\Dinomaly_base\dinomaly_sim.onnx
ONNX结构检查通过。
模型输入:
- input: shape=[1, 3, 448, 448], type=tensor(float)
模型输出:
- en_output: shape=[1, 768, 28, 28], type=tensor(float)
- de_output: shape=[1, 768, 28, 28], type=tensor(float)
- 2920: shape=[1, 768, 28, 28], type=tensor(float)
- 2922: shape=[1, 768, 28, 28], type=tensor(float)
ONNX Runtime加载通过,可以进入后续ATC转换步骤。看到“ONNX结构检查通过”和“ONNX Runtime加载通过”就说明导出的 ONNX 文件基本可用。
昇腾张量编译器(Ascend Tensor Compiler,简称ATC)是异构计算架构CANN体系下的模型转换工具。
可以将开源框架的网络模型以及Ascend IR定义的单算子描述文件(JSON格式)转换为昇腾AI处理器支持的.om格式离线模型。
模型转换过程中,ATC会进行算子调度优化、权重数据重排、内存使用优化等具体操作,对原始的深度学习模型进行进一步调优。
ATC转换命令:
atc --model=saved_results/Dinomaly_base/dinomaly_sim.onnx \
--framework=5 \
--output=saved_results/Dinomaly_base/dinomaly_sim \
--soc_version=Ascend310P3 \
--input_shape="input:1,3,448,448"参数说明:
.om 后缀修改om_infer.py中路径相关参数:
if __name__ == '__main__':
# 初始化推理器并执行样例推理
ompath = 'saved_results/Dinomaly_base/dinomaly_sim.om'
device_id = 0
om_infer = OMInfer(ompath, device_id)
img_path = 'xxx.png' # 输入图片路径
output_path = 'output.jpg' # 输出图片路径
om_infer(img_path, output_path)执行推理
python om_infer.py找不到 weights/dinov3_vitb16_pretrain_lvd1689m-73cec8be.pth
说明 encoder 权重没有放到 weights/ 目录。按“三.1”复制两个权重。
找不到 third_party/Dinomaly 或导入 dinov3 失败
说明还没有拉取 cnulab/Dinomaly 固定快照,或导出命令中的 --third_party_dir 路径不正确。按“三.1”拉取快照,默认路径为:
third_party/Dinomaly如果放在其他目录,导出时显式指定:
python export_onnx.py \
--model_path ./weights/dinomaly_39.pth \
--save_dir ./saved_results \
--save_name Dinomaly_base \
--third_party_dir /path/to/Dinomaly加载 dinomaly_39.pth 时报 state_dict 不匹配
多半是拿错了模型权重。当前验证通过的权重 key 以 encoder.cls_token、encoder.storage_tokens 开头,可以用下面命令检查:
source .venv/bin/activate
python -c "import torch; x=torch.load('weights/dinomaly_39.pth', map_location='cpu'); print(len(x)); print(list(x.keys())[:10])"导出 ONNX 以及之前的操作也可以在本地用 Windows 环境执行。
Windows PowerShell 备注:
.\.venv\Scripts\python.exe -c "import torch; x=torch.load('weights/dinomaly_39.pth', map_location='cpu'); print(len(x)); print(list(x.keys())[:10])"HuggingFace 下载 DINOv3 权重返回 401
facebook/dinov3-vitb16-pretrain-lvd1689m 是 gated repo,未登录或未获授权时会返回 401。当前流程不依赖在线下载,只需要提前准备好本地 .pth 权重并放入 weights/。
出现 xFormers is not available 警告
当前 CPU 导出流程可以忽略该警告,不影响已验证的 ONNX 导出。
出现 Matplotlib cache 警告
该警告不影响 ONNX 导出。如果需要消除,可以设置一个可写目录:
export MPLCONFIGDIR="$PWD/.mplconfig"导出 ONNX 以及之前的操作也可以在本地用 Windows 环境执行。
Windows PowerShell 备注:
$env:MPLCONFIGDIR="$PWD\.mplconfig"