--- license: cc-by-nc-sa-4.0 library_name: onnx pipeline_tag: image-classification tags: - anomaly-detection - patchcore - mvtec-ad - onnx - industrial-inspection datasets: - mvtec-ad --- # PatchCore on MVTec AD (ONNX, runs in the browser) From-scratch PyTorch reimplementation of **PatchCore** (Roth et al., *Towards Total Recall in Industrial Anomaly Detection*, CVPR 2022), exported to ONNX. Fitted on **defect-free images only**; defects are found as patches that are far from every patch seen on good parts. **Live demo (in your browser, no server):** [yandyassine/patchcore-defect-detection](https://huggingface.co/spaces/yandyassine/patchcore-defect-detection) · **Code & write-up:** [COMPUTER-VISION-PROJECT-LIBRARY / 13](https://github.com/yandouziyassine/COMPUTER-VISION-PROJECT-LIBRARY/tree/main/13-anomaly-detection-patchcore) ## Results (MVTec AD test set, image level) | Category | Test images | Image AUROC | F1 at the shipped threshold | |---|---|---|---| | bottle | 83 | 1.000 | 1.000 | | metal_nut | 115 | 0.999 | 0.995 | | grid | 78 | 0.977 | 0.974 | These numbers were re-measured **with the ONNX files in this repo** (fp16-stored weights), and match the PyTorch model exactly at this precision. ## Files | File | What it does | Size | |---|---|---| | `backbone.onnx` | image `(1,3,224,224)` → patch features `(784, 1536)`: WideResNet-50-2 layers 2+3, 3×3 local averaging | 50 MB | | `knn_.onnx` | features → anomaly map `(224,224)` + image score; memory bank (10 % greedy coreset) baked in | 50–64 MB | | `thresholds.json` | per-category decision threshold (best F1 on the test set) | | Weights are stored as float16 and cast to float32 inside the graph, so the math runs in float32. ## Use Preprocessing: resize the shorter side to 256, center-crop 224, ImageNet mean/std normalization. ```python import numpy as np, onnxruntime as ort bb = ort.InferenceSession("backbone.onnx") knn = ort.InferenceSession("knn_bottle.onnx") feats = bb.run(None, {"image": x})[0] # x: float32 (1,3,224,224) amap, score = knn.run(None, {"features": feats}) defect = score > 1.9728 # thresholds.json["bottle"]["threshold"] ``` ## Limitations - One model per product; a photo of another object will look anomalous everywhere (by design). - Thresholds were picked on the MVTec test set itself, so the F1 column is optimistic; AUROC is threshold-free. - Trained at 224 px; very small defects can be missed. ## License Memory banks are derived from MVTec AD, licensed **CC BY-NC-SA 4.0**: non-commercial use only. Backbone weights: torchvision ImageNet WideResNet-50-2.