File size: 2,652 Bytes
f1705b3
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
---
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_<category>.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.