Industrial quality control often faces the lack of labeled defect data. We specialize in unsupervised anomaly detection for images, implementing state-of-the-art methods like PatchCore and EfficientAD to detect defects without labeled data. Our experience includes automatic detection of scratches, cracks, contaminants, and other anomalies. According to the MVTec-AD study, modern unsupervised detection methods achieve AUROC up to 99%.
Why unsupervised approach is better than supervised for anomalies?
Supervised detection requires thousands of examples for each defect type. In reality, defects are rare and diverse — collecting a representative dataset is nearly impossible. Unsupervised learning solves this: the model memorizes only the norm and signals all deviations. On the MVTec-AD benchmark, modern methods achieve AUROC 99.1% (PatchCore) and 98.9% (EfficientAD) — close to supervised approaches, but without labeling costs.
How to choose the right method for your task?
Choice of architecture depends on data volume and speed requirements. PatchCore builds a memory bank from normal patches — no gradient training, so it starts in minutes. EfficientAD requires more data (from 200 images) but delivers consistently high quality with inference as low as 10 ms on GPU. If you need zero-shot anomaly detection, WinCLIP based on CLIP is suitable.
PatchCore: optimal algorithm for small data
PatchCore is suitable for scenarios with 50–200 normal images.
from anomalib.models import PatchCore from anomalib.data import Folder from anomalib import TaskType from lightning.pytorch import Trainer datamodule = Folder( name='my_product', root='./dataset', normal_dir='train/good', abnormal_dir='test/defective', task=TaskType.SEGMENTATION, image_size=(256, 256), train_batch_size=32, eval_batch_size=32 ) model = PatchCore( backbone='wide_resnet50_2', pre_trained=True, layers=['layer2', 'layer3'], coreset_sampling_ratio=0.1, num_neighbors=9 ) trainer = Trainer(max_epochs=1) trainer.fit(model, datamodule) How we implement the system in 1-2 weeks?
The development process consists of five stages:
- Production analysis: assess available data, lighting conditions, FP/FN requirements.
- Architecture selection: PatchCore for small data, EfficientAD for high loads.
- Threshold and metric calibration: set threshold based on quantile with target FPR.
- Deployment and integration: containerization, REST API, SCADA integration.
- Documentation and operator training: instructions for use and interpretation of results.
- 6-month warranty support: maintenance and fine-tuning.
Common mistake in threshold calibration
Many engineers set the threshold at the maximum score on the normal sample set. This leads to many false positives. We recommend using a quantile with a specified FPR.Comparison of anomaly detection methods
| Method | AUROC MVTec-AD | Speed | Feature |
|---|---|---|---|
| PatchCore | 99.1% | Medium | Memory bank |
| SimpleNet | 98.7% | Fast | Simple |
| WinCLIP | 91.8% | Slow | Zero-shot |
| STFPM | 97.9% | Fast | Teacher-Student |
| FastFlow | 97.5% | Very fast | Normalizing Flow |
| EfficientAD | 98.9% | Very fast | Recommended for prod |
EfficientAD is the best choice for production due to its inference speed while maintaining high AUROC. We use it in projects with high latency requirements.
How is the detection threshold tuned?
The threshold determines the score above which a sample is considered anomalous. We calibrate it based on a quantile from validation normal data:
class AnomalyDetector: def __init__(self, model_path: str, threshold: float = None): self.model = load_model(model_path) self.threshold = threshold or self._calibrate_threshold() def _calibrate_threshold(self, fp_rate: float = 0.01) -> float: """Порог при заданном False Positive Rate""" val_scores = self._predict_normal_samples() threshold = np.quantile(val_scores, 1 - fp_rate) return float(threshold) def predict(self, image: np.ndarray) -> dict: result = self.model(image) score = float(result.anomaly_score) return { 'anomaly_score': score, 'is_anomaly': score > self.threshold, 'severity': self._classify_severity(score), 'heatmap': result.anomaly_map, 'threshold': self.threshold } def _classify_severity(self, score: float) -> str: if score < self.threshold: return 'normal' elif score < self.threshold * 1.5: return 'minor' elif score < self.threshold * 2.5: return 'moderate' return 'severe' Localization of anomalies via heat maps
The anomaly map allows operators to see the exact location of a defect:
import matplotlib.pyplot as plt import matplotlib.cm as cm def visualize_anomaly(original: np.ndarray, anomaly_map: np.ndarray, threshold: float) -> np.ndarray: heatmap_norm = (anomaly_map - anomaly_map.min()) / \ (anomaly_map.max() - anomaly_map.min() + 1e-8) heatmap_colored = cv2.applyColorMap( (heatmap_norm * 255).astype(np.uint8), cv2.COLORMAP_JET ) _, mask = cv2.threshold( (heatmap_norm * 255).astype(np.uint8), int(threshold * 255), 255, cv2.THRESH_BINARY ) contours, _ = cv2.findContours(mask, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE) overlay = cv2.addWeighted(original, 0.6, heatmap_colored, 0.4, 0) cv2.drawContours(overlay, contours, -1, (0, 255, 0), 2) return overlay What is included in turnkey system development
We handle the entire cycle: from collecting reference samples to deployment on the line. Our turnkey solution includes documentation, system access, operator training, and 6-month support. Deliverables include:
- Production analysis: assess available data, lighting conditions, FP/FN requirements.
- Architecture selection: PatchCore for small data, EfficientAD for high loads.
- Threshold and metric calibration: tailored to your business criteria.
- Deployment and integration: containerization, REST API, SCADA integration.
- Documentation and operator training: instructions for use and interpretation of results.
- 6-month warranty support: maintenance and fine-tuning.
Timelines and our experience
| Scenario | Estimated timeframe |
|---|---|
| 1 product, PatchCore out of the box | 1–2 weeks |
| 5–10 products, threshold calibration | 3–5 weeks |
| Industrial system with online learning | 6–10 weeks |
Typical investment for a single product system starts at $5,000–$10,000, with savings from reduced manual inspection costs. We are certified engineers with 5+ years in the market and over 20 successful computer vision projects. Anomaly detection is our core expertise. Contact us to evaluate your task — we will select the optimal solution and calculate the budget within 2 days. Order a pilot project on one product — you will have a working prototype within a week.







