基于生成模型特征处理的工业异常检测系统(全套源码+数据集)
本项目面向工业质检场景,以 Dinomaly(CVPR 2025)为核心算法,结合 DINOv2 视觉基础模型与 ViTill 线性注意力解码器,实现对工业产品的无监督异常检测与亚像素级缺陷定位。系统涵盖从数据集构建、模型训练调优,到 Web 可视化平台的完整工程链路。
数据集


MVTec Anomaly Detection(MVTec AD)
MVTec AD 是工业异常检测领域最权威的基准数据集,收录了 15 种工业产品类别,涵盖纹理类与物体类两大场景。训练集仅包含无缺陷的正常图像,测试集同时包含正常图像与多种缺陷类型的异常图像,并附带像素级缺陷掩码(ground truth mask),适合无监督异常检测方法的训练与评估。
数据集图像均为 RGB 彩色图,原始分辨率在 700×700 至 1024×1024 之间,本项目统一 resize 至 448×448 输入模型。
类别分布
| 类别 | 中文名 | 训练图像 | 测试图像 |
|---|---|---|---|
| bottle | 瓶子 | 209 | 83 |
| cable | 线缆 | 224 | 150 |
| capsule | 胶囊 | 219 | 132 |
| carpet | 地毯 | 280 | 117 |
| grid | 栅格 | 264 | 78 |
| hazelnut | 榛子 | 391 | 110 |
| leather | 皮革 | 245 | 124 |
| metal_nut | 螺母 | 220 | 115 |
| pill | 药片 | 267 | 167 |
| screw | 螺丝 | 320 | 160 |
| tile | 瓷砖 | 230 | 117 |
| toothbrush | 牙刷 | 60 | 42 |
| transistor | 晶体管 | 213 | 100 |
| wood | 木材 | 247 | 79 |
| zipper | 拉链 | 240 | 151 |
| 合计 | — | 3 629 | 1 725 |
数据集构建与预处理
训练阶段,对正常样本施加轻量数据增强——随机水平翻转(概率 0.5)与颜色抖动(亮度 ±0.1、对比度 ±0.1),以提升模型对光照变化的鲁棒性,同时避免破坏纹理结构导致语义失真。测试阶段仅做缩放,不做任何增强,保证评估的客观性。所有图像在归一化时采用 ImageNet 统计量(mean=[0.485, 0.456, 0.406],std=[0.229, 0.224, 0.225]),以兼容 DINOv2 预训练权重的输入分布。
异常掩码以最近邻插值缩放,避免引入中间灰度值而污染像素级二值标签;掩码像素值大于 0 的位置统一置为 1.0,与 MVTec 官方评估协议保持一致,确保微小缺陷区域不被截断。
本项目采用统一多类别训练策略,将 15 个类别的正常样本合并为一个 Dataset,让解码器在同一套参数下学习多类工业产品的正常特征分布,而非分别训练 15 个独立模型。这一策略显著降低了部署复杂度,同时在实验中验证了其泛化能力并不弱于单类模型。
模型架构
整体思路
Dinomaly 的核心假设是:当一个强大的视觉编码器提取到正常图像的特征后,一个容量受限且带有噪声的解码器能够"近似但不精确地"重建这些特征——对正常区域重建误差小,对异常区域(训练中从未见过)重建误差大。这个误差图即为异常分数图。
DINOv2 编码器
编码器采用 vit_base_patch14_dinov2.lvd142m(ViT-Base,patch size=14),通过 timm 加载预训练权重(约 330MB),参数量约 86M。在 448×448 输入下,图像被切分为 (448/14)² = 1024 个 patch token,每个 token 的特征维度为 768。
编码器参数全程冻结,不参与梯度计算。通过 register_forward_hook 钩子提取第 2~9 层(共 8 层)的 patch 特征,CLS token 被丢弃,只保留空间语义信息。将这 8 层特征分为两组(第 2-5 层为低语义组,第 6-9 层为高语义组),组内取均值融合,得到两个融合特征张量,供解码器使用。
ViTill 解码器
解码器是唯一需要训练的部分,参数量约 25M,包含以下三个关键模块:
Noisy Bottleneck(噪声瓶颈):将两组编码器融合特征拼接(维度翻倍),经过两层线性层压缩回 768 维,中间插入 Dropout(p=0.2)作为噪声注入。Dropout 在训练阶段随机屏蔽部分特征维度,强迫解码器不能逐位复制编码器的输出,从而避免退化为恒等映射。
线性注意力(LinearAttention):采用 ELU 核函数近似,将标准 Softmax 注意力的 O(N²) 复杂度降至 O(N)。公式为 φ(x) = ELU(x) + 1,先计算 KT·V(维度 D×D),再计算 Q·(KT·V),规避了 token 间两两交互的显存瓶颈。线性注意力天然无法精确聚焦于局部区域,这一"缺陷"在异常检测中反而有益:解码器很难对异常区域也做到精确重建。内部强制使用 float32 计算,防止 1024 个 token 累加时 fp16 溢出产生 NaN。
解码层堆叠:共 8 个 DecoderBlock(层归一化 → 线性注意力 → 残差;层归一化 → MLP → 残差),输出 8 层中间特征,再以相同的分组策略做均值融合,得到两个解码器融合特征张量。
损失函数
使用松散余弦重建损失(Loose Cosine Reconstruction Loss):
Loss = mean over groups of (1 - cosine_similarity(enc_fused, dec_fused))
对两组融合特征分别计算余弦相似度,取均值后取反。之所以称为"松散",是因为只对融合后的特征对齐,而非逐层逐点强制匹配,这给解码器更多弹性,避免过拟合到噪声细节。
异常分数推理
推理时将解码器的 dropout 关闭(eval 模式),对每个 token 位置计算编码器与解码器特征的余弦距离,得到 (B, 1024) 的异常分数图,再双线性插值上采样到 448×448 的像素空间。每张图像取分数图的最大值作为图像级异常分数,分数图本身作为像素级定位依据。
训练过程
硬件环境
针对 RTX 3060 12GB 显卡进行了专项优化,在官方 batch_size=16 的基础上降至 8,启用混合精度训练(AMP fp16)节省约 30% 显存,线性注意力内部强制 float32 防止数值溢出,最终训练峰值显存约 10GB。
优化器配置
优化器:AdamW
学习率:2e-4
权重衰减:1e-5
学习率调度:CosineAnnealingLR(T_max=200,eta_min=1e-6)
梯度裁剪:max_norm=1.0
混合精度:GradScaler(fp16=True)
随机种子:42
AdamW 的权重衰减对线性层参数起到正则化作用,防止解码器过度拟合正常样本。余弦退火调度让学习率在训练末期平滑衰减至接近 0,使模型在最优解附近精细收敛。梯度裁剪防止线性注意力累加运算导致的梯度突刺。
断点续训
每个 epoch 结束后将解码器权重与优化器状态保存为 last_checkpoint.pth(覆盖写,不累积体积)。下次启动时自动检测并从断点恢复,避免意外中断导致训练进度损失。
权重保存策略
每 10 个 epoch 评估一次,分别在图像级 AUROC 和像素级 AUROC 创新高时各保存一份最优权重(best_img_auroc.pth / best_pix_auroc.pth)。权重文件仅保存解码器参数,编码器权重在推理时由 timm 重新加载,因此单份权重文件体积约 100MB。
训练指标记录
每 10 个 epoch 完成一次全测试集评估,训练过程中的指标变化如下:
| Epoch | Loss | Img-AUROC | Pix-AUROC |
|---|---|---|---|
| 10 | 0.0495 | 97.25% | 96.68% |
| 50 | 0.0293 | 98.23% | 97.68% |
| 100 | 0.0225 | 98.83% | 98.03% |
| 150 | 0.0193 | 99.20% | 98.09% |
| 200 | 0.0179 | 99.41% | 98.12% |
Loss 呈现平稳单调下降趋势,AUROC 随之持续提升,200 epoch 后未出现明显过拟合,表明余弦松散损失 + Noisy Bottleneck 的组合具有良好的泛化性。
评估指标说明
图像级 AUROC(Image-level AUROC):以每张图像异常分数图的最大值作为该图的异常分数,与图像级标签(0=正常,1=异常)计算 ROC 曲线下面积。反映模型"判断一张图是否存在缺陷"的能力,本项目最终达到 99.41%。
像素级 AUROC(Pixel-level AUROC):将所有图像的像素级异常分数图展平,与 ground truth 掩码展平后计算 ROC 曲线下面积。反映模型"准确定位缺陷位置"的能力,本项目最终达到 98.12%。
Per-Region Overlap(PRO):在 FPR ≤ 0.3 范围内,对预测缺陷与真实缺陷连通域的重叠率进行积分并归一化。PRO 对大小不均匀的缺陷区域更公平,避免大面积背景区域主导评估结果,适合精细定位场景的补充评估。
可视化图说明
异常热力图:将像素级异常分数图经 JET colormap 渲染为伪彩色图像(蓝→绿→红,分数由低到高),再以一定透明度叠加到原图上。热力图中红色区域对应高异常分数,代表模型判断该位置存在缺陷,蓝色区域为正常背景。
训练 AUROC 曲线:系统配置页中展示每 10 个 epoch 的图像级 AUROC、像素级 AUROC 与 Loss 的变化趋势。图像 AUROC / 像素 AUROC 对应左 Y 轴(单位 %),Loss 对应右 Y 轴(虚线),帮助判断训练是否正常收敛。
异常分数进度条:检测结果页面中,进度条以当前分数与阈值的比值表示异常程度——分数超过阈值则判为异常,进度条颜色由绿色变为红色,直观反映边界情况下的置信程度。
近期检测趋势图:结果分析页面展示最近 20 次检测的异常分数折线,阈值以红色虚线标注,异常点用红色散点单独标出,便于识别批量检测中的异常集中段。
各类别异常分布柱状图:以堆叠柱状图展示 15 个类别各自的正常与异常样本数量分布,帮助识别哪类产品缺陷率最高,辅助工程师进行产线针对性改进。
系统功能
数据管理:展示 MVTec AD 15 个类别的图标、名称、训练/测试图像数量,选中类别后可快速跳转至检测页面。
模型部署:自动扫描 dinomaly/checkpoints/ 目录下的可用权重文件,展示文件名与大小;支持通过滑块预设异常判定阈值后加载;展示加载后的模型详细信息(训练轮次、图像/像素 AUROC、推理设备)。
实时检测:支持点击选择或拖拽上传图像文件(JPG/PNG),选择检测类别后调用后端推理接口,返回异常分数、异常判定结果、异常热力图,同时以进度条可视化分数与阈值的关系。
结果分析:汇总展示检测总量、正常/异常样本数、异常率、平均分数等统计指标;提供趋势折线图、正常/异常占比饼图、各类别堆叠柱状图;历史记录表支持按类别筛选、分页浏览、单条删除、批量清空、一键导出 CSV。
系统配置:实时调节异常判定阈值与热力图叠加透明度;展示 GPU 显存用量与使用率;显示训练 AUROC/Loss 曲线(数据来源于 train_log.txt);提供快速阈值预设按钮(0.3~0.7)。
登录注册:内置管理员账号(admin/admin123),支持新用户注册,账号信息持久化存储于浏览器本地,已登录状态在关闭浏览器后仍保留。






技术栈
深度学习
- PyTorch 2.x + CUDA — 模型训练与推理框架
- timm — DINOv2 预训练权重加载
- torchvision — 数据增强与预处理
- scikit-learn / scikit-image — AUROC、PRO 指标计算
- Pillow / NumPy — 图像读写与数值运算
后端服务
- FastAPI — 高性能异步 Web 框架
- Uvicorn — ASGI 服务器
- Python 3.8+
前端
- Vue 3(Composition API +
<script setup>) - Vite 4 — 本地开发服务器与生产构建
- Element Plus 2 — UI 组件库
- ECharts 5 — 数据可视化图表
- Axios — HTTP 请求封装
项目结构
c177/
├── mvtec_anomaly_detection/ # MVTec AD 数据集(需自行下载)
│ ├── bottle/
│ ├── cable/
│ └── ...(共 15 个类别目录)
│
├── dinomaly/ # 深度学习核心模块
│ ├── config.py # 训练超参与路径配置
│ ├── train.py # 训练主入口(断点续训、评估、保存)
│ ├── models/
│ │ ├── encoder.py # DINOv2 编码器(hook 提取多层特征)
│ │ ├── decoder.py # ViTill 解码器(线性注意力 + 噪声瓶颈)
│ │ └── dinomaly.py # 编解码器组合 + 推理接口
│ ├── data/
│ │ └── mvtec.py # MVTec 数据集加载器
│ ├── utils/
│ │ ├── losses.py # 余弦松散重建损失
│ │ └── metrics.py # AUROC / PRO 评估指标
│ ├── checkpoints/ # 训练权重输出目录
│ │ ├── last_checkpoint.pth # 断点续训文件(每 epoch 覆盖)
│ │ ├── best_img_auroc.pth # 图像级 AUROC 最优权重
│ │ └── best_pix_auroc.pth # 像素级 AUROC 最优权重
│ └── logs/
│ └── train_log.txt # 训练指标日志(每 10 epoch 追加)
│
└── web/ # Web 系统
├── backend/ # FastAPI 后端
│ ├── main.py # 应用入口,挂载路由与静态文件
│ ├── schemas.py # Pydantic 数据模型
│ ├── api/
│ │ ├── detect.py # 检测接口(上传图像、返回热力图)
│ │ ├── model.py # 模型管理接口(加载、状态、阈值)
│ │ ├── history.py # 历史记录接口(列表、统计、删除)
│ │ └── system.py # 系统接口(GPU 状态、训练日志)
│ └── core/
│ ├── detector.py # 检测器单例(加载模型、执行推理)
│ └── database.py # JSON 文件持久化历史记录
├── vue-frontend/ # Vue 3 前端源码
│ ├── package.json
│ ├── vite.config.js
│ ├── index.html
│ └── src/
│ ├── main.js
│ ├── App.vue
│ ├── api/index.js # Axios 接口封装
│ ├── composables/
│ │ ├── useAuth.js # 登录注册状态管理
│ │ └── useModelStore.js # 跨组件模型状态共享
│ ├── constants/index.js # 类别定义 + 演示数据
│ ├── styles/main.css # 全局样式变量
│ ├── views/ # 页面组件
│ │ ├── LoginView.vue
│ │ ├── DataView.vue
│ │ ├── ModelView.vue
│ │ ├── DetectView.vue
│ │ ├── AnalysisView.vue
│ │ └── ConfigView.vue
│ └── components/
│ └── HeatmapModal.vue # 热力图预览弹窗
├── frontend/ # Vue 构建产物(由 npm run build 生成)
└── data/
└── history.json # 检测历史持久化文件
启动教程
环境要求
- Python 3.8 或以上,推荐使用 conda 管理环境
- Node.js 16 或以上(前端开发构建需要)
- NVIDIA GPU(推荐显存 ≥ 8GB);CPU 模式也可运行但推理速度较慢
第一步:安装 Python 依赖
pip install torch torchvision --index-url https://download.pytorch.org/whl/cu118
pip install timm fastapi uvicorn pillow numpy scikit-learn scikit-image tqdm
第二步:准备数据集
从 MVTec 官网 下载 MVTec AD 数据集,解压后将 15 个类别目录放置到项目根目录下的 mvtec_anomaly_detection/ 文件夹中,确保路径为 mvtec_anomaly_detection/bottle/train/good/...。
第三步:训练模型
cd dinomaly
python train.py
首次运行会自动从 timm 下载 DINOv2 预训练权重(约 330MB)。训练日志实时输出到控制台,每 10 个 epoch 将指标写入 dinomaly/logs/train_log.txt,最优权重保存至 dinomaly/checkpoints/。训练意外中断后重新运行 python train.py 即可从断点续训。
第四步:构建前端
cd web/vue-frontend
npm install
npm run build
构建产物会自动输出到 web/frontend/,FastAPI 会从该目录托管静态文件。
第五步:启动后端服务
cd web/backend
python main.py
服务启动后访问 http://localhost:8000 即可使用完整 Web 系统。
开发阶段也可以单独启动前端开发服务器(
npm run dev,端口 5173),API 请求会自动代理到 8000 端口。
本项目为个人原创,结构清晰,功能完整,适合计算机视觉方向课程设计、毕业设计和项目演示使用。有定制化需求可以评论或私信作者。
作者原创项目地址:michael-jay.pages.dev/projects.html
浙公网安备 33010602011771号