Spaces:
Configuration error
Visual Defect Inspector
An industrial anomaly detection API built on PatchCore, trained on the MVTec AD dataset. Upload an image of a bottle and the API returns an anomaly prediction, confidence score, and a heatmap overlay highlighting suspicious regions.
Live API: codehashira73-visual-defect-inspector.hf.space/docs
Demo
Note: This model is trained on MVTec AD bottle images β professionally lit, white background, standardized angles. Testing with images from this distribution will give reliable results. Random internet images may return false positives due to distribution shift (different backgrounds, lighting, angles).
How It Works
PatchCore is a memory-based anomaly detection algorithm. Instead of learning what anomalies look like (which is impossible without labeled defect data), it learns what normal looks like and flags anything that deviates.
Training (offline):
- Pass all normal training images through a pretrained CNN backbone (
resnet18) - Extract intermediate feature maps from
layer2andlayer3β these capture both low-level textures and mid-level semantics - Flatten these into patch-level embeddings, one per spatial location
- Apply coreset subsampling (ratio=0.1) to compress the embeddings into a representative memory bank β this keeps inference fast without sacrificing much accuracy
Inference (at API call time):
- Pass the uploaded image through the same backbone
- Extract patch embeddings from the same layers
- For each patch, find its nearest neighbor in the memory bank and compute the distance
- Large distance = that patch looks nothing like any normal patch = anomaly
- Upsample per-patch distances back to image resolution β anomaly heatmap
- Take the maximum patch distance as the image-level anomaly score
- Compare score against a threshold computed during training β
NORMALorANOMALOUS
Why resnet18 over wide_resnet50_2?
Both backbones performed nearly identically β wide_resnet50_2 achieved pixel_AUROC=0.986 vs resnet18 at pixel_AUROC=0.978. Since PatchCore's performance is driven primarily by the coreset memory bank and nearest-neighbor search rather than backbone capacity, the heavier backbone offers no meaningful advantage. resnet18 was selected for its faster inference time and lower memory footprint at deployment, with negligible cost to detection performance.
Results
Trained and evaluated on the bottle category of MVTec AD.
| Backbone | Image AUROC | Pixel AUROC | Image F1 | Model Size |
|---|---|---|---|---|
| wide_resnet50_2 | 1.000 | 0.986 | 0.992 | ~1.5 GB |
| resnet18 (deployed) | 1.000 | 0.978 | 0.992 | 42 MB |
Both runs logged with MLflow under the visual-defect-inspector experiment.
API Usage
GET /health
Health check endpoint.
curl https://codehashira73-visual-defect-inspector.hf.space/health
Response:
{"status": "ok"}
POST /inspect
Upload an image and get an anomaly prediction.
curl -X POST \
https://codehashira73-visual-defect-inspector.hf.space/inspect \
-F "file=@bottle.png"
Response:
{
"prediction": "ANOMALOUS",
"anomaly_score": 0.9753,
"heatmap_base64": "/9j/4AAQSkZJRgAB..."
}
| Field | Type | Description |
|---|---|---|
prediction |
string | "NORMAL" or "ANOMALOUS" |
anomaly_score |
float | Score between 0 and 1. Higher = more anomalous |
heatmap_base64 |
string | Base64-encoded JPEG of the original image overlaid with the anomaly heatmap (blue = normal, red = anomalous) |
To render the heatmap in Python:
import base64
from PIL import Image
import io
heatmap_bytes = base64.b64decode(response["heatmap_base64"])
image = Image.open(io.BytesIO(heatmap_bytes))
image.show()
Project Structure
visual-defect-inspector/
βββ app/
β βββ __init__.py
β βββ main.py # FastAPI app β routes, CORS, validation
β βββ inference.py # Model loading (singleton) + predict logic
βββ saved_model/
β βββ weights/
β βββ torch/
β βββ model.pt # PatchCore model with memory bank (via Git LFS)
βββ Anomaly_detection.ipynb # Training, evaluation, MLflow logging
βββ Dockerfile
βββ requirements.txt
βββ .gitignore
Tech Stack
| Component | Tool |
|---|---|
| Anomaly detection | anomalib |
| Backbone | ResNet18 (PyTorch) |
| Experiment tracking | MLflow |
| API framework | FastAPI + Uvicorn |
| Image processing | OpenCV, Pillow |
| Containerization | Docker |
| Deployment | Hugging Face Spaces |
| Model storage | Git LFS |
Local Setup
Prerequisites: Python 3.10+, Git LFS installed
# Clone the repo
git clone https://github.com/JeremiahAdebayo/visual-defect-inspector.git
cd visual-defect-inspector
# Install dependencies
pip install -r requirements.txt
# Run the API
uvicorn app.main:app --reload
API will be available at http://127.0.0.1:8000/docs
With Docker:
docker build -t visual-defect-inspector .
docker run -p 7860:7860 visual-defect-inspector
Limitations
- Trained on a single MVTec AD category (bottle). Does not generalize to other object types without retraining.
- Sensitive to distribution shift β images must closely resemble the MVTec training distribution (white background, controlled lighting, top-down angle) for reliable results.
- Anomaly threshold is fixed at training time. May need recalibration for production use cases with different defect types.
Author
Jeremiah Adebayo
3rd Year Information Technology Student, University of Iloilo
GitHub Β· Hugging Face


