Anomalib MVTec AD 2 Datamodule:三测试集工业异常检测数据集的加载与评估全流程
【免费下载链接】anomalibAn anomaly detection library comprising state-of-the-art algorithms and features such as experiment management, hyper-parameter optimization, and edge inference.项目地址: https://gitcode.com/GitHub_Trending/an/anomalib
本文围绕 Anomalib 官方文档中 MVTecAD2 Datamodule 参考页 所介绍的MVTecAD2DataModule 展开,结合 核心实现源码 与 底层数据集类,讲解 MVTec AD 2 数据集的下载、目录解析、train/val/test 划分,以及 public、private、private_mixed 三套测试集的选择机制。读完后你可以直接在 Anomalib 中加载该数据集完成训练、本地评估,并为官方排行榜提交做准备。
一、MVTec AD 2 数据集概述
MVTec AD 2 是 MVTec 团队推出的第二代工业异常检测基准,面向"无监督异常检测的进阶场景"(Advanced Scenarios for Unsupervised Anomaly Detection,arXiv 预印本 2024,作者包括 Lars Heckler-Kram、Carsten Steger 等)。相对于初代 MVTec AD,它在测试集设计上做了关键变化:提供三套相互独立的测试集,以区分本地评估与官方排行榜评估两种用途。
从 数据集模块的文档字符串 中可以看到三套测试集的定义:
| 测试集 | 目录 | 特点 | 用途 |
|---|---|---|---|
| Public test set | test_public/ | 同时包含正常与异常样本,且带有像素级 ground truth 掩码 | 本地测试与初步性能估计 |
| Private test set | test_private/ | 官方"未见"测试样本,不提供 ground truth | 提交官方排行榜 |
| Private mixed test set | test_private_mixed/ | 未见样本,在"已见"与"未见"光照条件下随机混合拍摄,无 ground truth | 提交官方排行榜 |
数据集共包含 8 个类别,定义在 CATEGORIES 常量 中:
CATEGORIES = ( "can", "fabric", "fruit_jelly", "rice", "sheet_metal", "vial", "wallplugs", "walnuts", )每个类别都包含 RGB 图像和像素级异常分割掩码(仅 public 测试集提供)。数据集以 Creative Commons Attribution-NonCommercial-ShareAlike 4.0 International (CC BY-NC-SA 4.0) 许可证发布,使用时需遵守其非商业与相同方式共享条款。官方评估通过 MVTec 官方 benchmark 站点(源码注释中给出的域名为 benchmark.mvtec.com)进行。
二、Datamodule 快速上手
MVTecAD2是继承自AnomalibDataModule的 PyTorch Lightning DataModule,源码位于 src/anomalib/data/datamodules/image/mvtecad2.py,可从anomalib.data顶层包直接导入。最小化用法(与源码 类文档中的 Example 一致):
from anomalib.data import MVTecAD2 datamodule = MVTecAD2( root="./datasets/MVTec_AD_2", category="sheet_metal", train_batch_size=32, eval_batch_size=32, num_workers=8, ) datamodule.setup() # 准备数据集:下载(如缺失)+ 构建各 split 数据集调用setup()之后,可以直接读取各 split 的样本数量:
print(f"Number of training samples: {len(datamodule.train_data)}") print(f"Number of validation samples: {len(datamodule.val_data)}") print(f"Number of test samples (public): {len(datamodule.test_public_data)}") print(f"Number of test samples (private): {len(datamodule.test_private_data)}") print(f"Number of test samples (private mixed): {len(datamodule.test_private_mixed_data)}")仓库中提供了完整的可运行示例 examples/api/02_data/mvtecad2.py,覆盖基础加载、自定义 transforms、三套测试集访问、直接用MVTecAD2Dataset构建 DataLoader 以及 matplotlib 可视化(将gt_mask以红色半透明叠在图像上)等场景。
三、参数与默认值详解
MVTecAD2.__init__的完整签名定义在 mvtecad2.py 第 113–142 行,各参数含义与默认值如下:
| 参数 | 类型 | 默认值 | 说明 |
|---|---|---|---|
root | str \| Path \| None | "./datasets/MVTec_AD_2" | 数据集根目录。传入None时经resolve_dataset_root解析为数据集目录下的MVTec_AD_2 |
category | str | "sheet_metal" | 要加载的类别名,取值见上节CATEGORIES |
train_batch_size | int | 32 | 训练 batch size |
eval_batch_size | int | 32 | 验证与测试 batch size |
num_workers | int | 8 | 数据加载进程数 |
train_augmentations | Transform \| None | None | 仅作用于训练集的 torchvision v2 增强 |
val_augmentations | Transform \| None | None | 仅作用于验证集的增强 |
test_augmentations | Transform \| None | None | 仅作用于测试集的增强 |
augmentations | Transform \| None | None | 当未提供 stage 专属增强时的通用增强 |
test_type | str \| TestType | TestType.PUBLIC | 初始化时选择的测试集类型,可传字符串"public"/"private"/"private_mixed" |
seed | int \| None | None | 复现用随机种子 |
使用 YAML 配置(如流水线或 CLI 场景)时,对应的 init 配置形如仓库内置的 examples/configs/data/mvtecad2.yaml:
class_path: anomalib.data.MVTecAD2 init_args: root: "./datasets/MVTec_AD_2" category: "sheet_metal" train_batch_size: 32 eval_batch_size: 32 num_workers: 8 test_type: "public" seed: null字符串形式的test_type会在构造时被显式转换为枚举(TestType(test_type) if isinstance(test_type, str)),拼写错误会直接抛出ValueError,属于 fail-fast 设计。
四、三套测试集的选择机制:TestType与test_dataloader
4.1 TestType 枚举
TestType定义在 src/anomalib/data/datasets/image/mvtecad2.py 第 44–57 行:
class TestType(str, Enum): PUBLIC = "public" # 带 ground truth 的本地评估测试集 PRIVATE = "private" # 官方私有测试集,无 ground truth PRIVATE_MIXED = "private_mixed" # 混合光照条件的官方私有测试集它继承str,因此在 Pydantic 校验、YAML 配置等场景中可以直接与字符串互换。
4.2 setup 阶段一次性构建全部测试集
值得注意的是,_setup 方法(第 173–221 行) 并不按test_type只构建一个测试集,而是一次性构建三个测试数据集:
self.test_public_data = MVTecAD2Dataset( root=self.root, category=self.category, split=Split.TEST, test_type=TestType.PUBLIC, augmentations=self.test_augmentations, ) self.test_private_data = MVTecAD2Dataset( root=self.root, category=self.category, split=Split.TEST, test_type=TestType.PRIVATE, augmentations=self.test_augmentations, ) self.test_private_mixed_data = MVTecAD2Dataset( root=self.root, category=self.category, split=Split.TEST, test_type=TestType.PRIVATE_MIXED, augmentations=self.test_augmentations, ) # Always set test_data to public test set for standard evaluation self.test_data = self.test_public_data两个关键行为:
test_data始终指向 public 测试集。这意味着在标准 Lightning 训练循环里,validation/test阶段默认走的是带 ground truth 的本地评估路径,不会误用私有集。- MVTec AD 2 自带独立的验证集(
validation/good/),因此_setup中val_data使用Split.VAL而非从训练集切分,这也是与初代 MVTec AD(训练集中无验证划分)的一个实现差异。
4.3 按类型获取 DataLoader
test_dataloader 方法(第 223–263 行) 是切换到私有测试集的统一入口:
datamodule.setup() public_loader = datamodule.test_dataloader() # 回落到 self.test_type private_loader = datamodule.test_dataloader(test_type="private") mixed_loader = datamodule.test_dataloader(test_type="private_mixed")其内部按TestType分派到对应数据集,最终统一返回一个DataLoader:shuffle=False、batch_size=self.eval_batch_size、collate_fn=dataset.collate_fn、pin_memory=True。对于私有集,由于样本没有 ground truth(详见下节),拿到的 batch 只用于推理输出,而不是与标签对比打分。
五、目录结构与样本解析:make_mvtec2_dataset
样本发现逻辑集中在 make_mvtec2_dataset 函数(第 164–296 行)。它期望数据集解压后遵循如下结构(以单个类别目录为根):
root/ ├── test_private/ # 官方私有测试样本(无标注) ├── test_private_mixed/ # 混合光照的官方私有测试样本(无标注) ├── test_public/ │ ├── bad/ # 异常测试图像 │ ├── good/ # 正常测试图像 │ └── ground_truth/ │ └── bad/ # 异常图像的掩码(命名为 <stem>_mask.png) ├── train/ │ └── good/ # 训练集:仅正常样本 └── validation/ └── good/ # 验证集:仅正常样本解析规则可以从源码逐条读出:
- 训练集:只扫描
train/good下的图像,标签为good,label_index=0,无掩码; - 验证集:只扫描
validation/good,同样label_index=0; - public 测试集:
test_public/good的图像标记为正常(label_index=0);test_public/bad的图像标记为异常(label_index=1),且掩码文件名强制按图像名_mask.png规则在test_public/ground_truth/bad/下查找——若掩码缺失,会抛出MisMatchError("Missing mask for anomalous image"),保证图像与标注严格一一对应; - private / private_mixed 测试集:目录下所有图像统一标记为
label="unknown"、label_index=-1,无掩码。-1这一约定的意义在于:下游评估指标能识别出这些样本不可用于有监督打分,只用于推理。
函数最终返回一个 PandasDataFrame,列包括path、split、label、image_path、mask_path、label_index,并通过samples.attrs["task"] = "segmentation"声明该数据集面向分割任务。若整个类别目录下找不到任何.png/.PNG图像(IMG_EXTENSIONS 中定义的扩展名),函数会直接抛出RuntimeError。
六、自动下载:prepare_data 与 DownloadInfo
Datamodule 内嵌了 DOWNLOAD_INFO 常量(第 49–54 行),声明了数据集的下载地址与 SHA-256 校验和:
DOWNLOAD_INFO = DownloadInfo( name="mvtecad2", url="https://www.mydrive.ch/shares/150997/701c90d3aea6588f404936e32a674602/download/" "466712769-1743429042/mvtec_ad_2.tar.gz", hashsum="c0ded99ef32bfc8e352d52beb44515e5b292b8598cb963aadfa91ca0763505e4", )prepare_data 方法(第 144–171 行) 的判断逻辑非常简单:
if (self.root / self.category).is_dir(): logger.info("Found the dataset.") else: download_and_extract(self.root, DOWNLOAD_INFO)即以"当前类别目录是否存在"作为数据集就绪的判据:只要root/category目录存在就跳过下载,否则调用anomalib.data.utils.download_and_extract完成下载、按hashsum校验并解压。这带来两个实践上的注意点:
- 只下载/解压了部分类别也能触发"已存在"判定,因为检查粒度是类别级而非压缩包级;
- 若已手动解压的数据集结构不符合第五节的目录约定,问题会在
_setup阶段(make_mvtec2_dataset找不到图像或掩码)以RuntimeError/MisMatchError暴露,而不是静默产出空数据集。
七、实战:自定义 transforms 与直接构建 Dataset
在 Lightning 训练流程外,MVTecAD2Dataset也可以脱离 DataModule 直接使用。以下代码整理自 examples/api/02_data/mvtecad2.py:
import torch from torch.utils.data import DataLoader from torchvision.transforms.v2 import Compose, Resize, ToDtype, ToImage from anomalib.data import MVTecAD2 from anomalib.data.datasets.image.mvtecad2 import MVTecAD2Dataset, TestType from anomalib.data.utils import Split transform = Compose([ ToImage(), Resize((256, 256)), ToDtype(torch.float32, scale=True), ]) # 通过 DataModule 传入 stage 专属增强 datamodule = MVTecAD2( root="./datasets/MVTec_AD_2", category="sheet_metal", train_augmentations=transform, val_augmentations=transform, test_augmentations=transform, ) datamodule.setup() # 或者直接用 Dataset + collate_fn 构建 DataLoader train_dataset = MVTecAD2Dataset( root="./datasets/MVTec_AD_2", category="sheet_metal", split=Split.TRAIN, augmentations=transform, ) train_loader = DataLoader( train_dataset, batch_size=4, shuffle=True, collate_fn=train_dataset.collate_fn, # 产出 ImageItem 批量结构 pin_memory=True, )两个要点:
- transforms 类型是
torchvision.transforms.v2.Transform(源码中即按该类型标注),示例使用ToImage → Resize → ToDtype(float32, scale=True)的组合,是配合 Anomalib 数据类(dataclass)输出结构的推荐写法; - 自行构建
DataLoader时必须带上dataset.collate_fn,否则拿不到image/gt_label/gt_mask等具名字段结构(示例中通过train_samples.image.shape、train_samples.gt_label直接访问批量字段,public 测试集还可通过test_samples.gt_mask取到掩码)。
八、小结与延伸阅读
MVTecAD2DataModule 的核心设计可以概括为三句话:一次 setup 构建全部三套测试集、test_data默认指向 public 集、私有集样本以label_index=-1标记以隔离评估语义。这使同一份代码既能支撑带标注的本地指标计算,也能安全地驱动无标注私有集的推理流程,契合 MVTec AD 2"本地评估 + 官方排行榜"双轨制的基准设计。
进一步阅读:
- MVTecAD2 Datamodule API 参考页
- DataModule 实现:下载、setup 与测试集分派逻辑
- Dataset 实现:
TestType枚举与目录解析规则 - API 完整示例:加载、transform、可视化一条龙
- YAML 配置示例:流水线/CLI 场景的 init 参数写法
【免费下载链接】anomalibAn anomaly detection library comprising state-of-the-art algorithms and features such as experiment management, hyper-parameter optimization, and edge inference.项目地址: https://gitcode.com/GitHub_Trending/an/anomalib
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考