Skip to main content

Enterprise-Grade Visual Anomaly Detection Toolkit with 120+ registry models and 80+ operations

Project description

pyimgano banner

Production-oriented visual anomaly detection for industrial inspection.
Image-level + Pixel-level · 120+ Models · Train → Deploy in one pipeline

PyPI Python CI License: MIT Code style: black Downloads

InstallationQuickstartModel ZooAPIBenchmarkingDocsCitation

Translations: 中文 · 日本語 · 한국어


Why pyimgano?

Most anomaly detection libraries target either research (maximizing paper metrics) or tabular data (PyOD-style). pyimgano bridges the gap for teams that need to go from algorithm selection to production deployment on real industrial images:

Research libs Tabular AD (PyOD…) pyimgano
Image-level scoring
Pixel-level anomaly maps
Industrial IO (numpy, tiling, formats)
Deploy bundles (ONNX / OpenVINO) partial
Reproducible CLI + audit trail
120+ unified model registry
Synthetic anomaly generation

✨ Key Features

Key Features

🧠 Unified Model Registry

  • 120+ registered entry points in a single create_model() call
  • Classical (ECOD, KNN, IF, PCA…) + Deep (PatchCore, PaDiM, STFPM…) + VLM (WinCLIP, AnomalyDINO…)
  • Lazy-loading registry — no heavy imports at startup

🔍 Image + Pixel Anomaly Detection

  • Image-level anomaly scores
  • Pixel-level anomaly maps with defect masks
  • Connected-component regions with BBox and area
  • ROI gating & binary morphology

⚡ Production CLI Pipeline

  • pyimgano-trainpyimgano-infer → JSONL
  • Reproducible runs with report.json + per_image.jsonl
  • Deploy bundles for containers/servers
  • Run comparison & leaderboard tables

🚀 Deploy-ready Inference

  • Export to ONNX / OpenVINO / TorchScript
  • Auditable infer_config.json + calibration_card.json
  • High-resolution tiling for large images
  • Explicit ImageFormat (RGB/BGR, U8/U16/F32, HWC/CHW)

🏗️ Architecture

Architecture Overview

Pipeline flow (Mermaid)
graph LR
    A[📁 Images / NumPy] --> B[Preprocessing]
    B --> C[Feature Extraction]
    C --> D[Model Zoo<br/>120+ Detectors]
    D --> E[Calibration]
    E --> F{Output}
    F --> G[🎯 Anomaly Score]
    F --> H[🗺️ Pixel Map]
    F --> I[🔲 Defect Regions]
    F --> J[📄 JSONL Report]

    style A fill:#1e293b,stroke:#38bdf8,color:#e2e8f0
    style B fill:#1e293b,stroke:#38bdf8,color:#e2e8f0
    style C fill:#1e293b,stroke:#818cf8,color:#e2e8f0
    style D fill:#1e293b,stroke:#f472b6,color:#e2e8f0
    style E fill:#1e293b,stroke:#fb923c,color:#e2e8f0
    style F fill:#0f172a,stroke:#34d399,color:#e2e8f0
    style G fill:#1e293b,stroke:#34d399,color:#e2e8f0
    style H fill:#1e293b,stroke:#34d399,color:#e2e8f0
    style I fill:#1e293b,stroke:#34d399,color:#e2e8f0
    style J fill:#1e293b,stroke:#34d399,color:#e2e8f0

📦 Installation

pip install pyimgano
Install from source (latest dev)
git clone https://github.com/skygazer42/pyimgano.git
cd pyimgano
pip install -e ".[dev]"
Optional extras
pip install "pyimgano[torch]"       # PyTorch deep backends + TorchScript export
pip install "pyimgano[onnx]"        # ONNX runtime
pip install "pyimgano[openvino]"    # OpenVINO runtime
pip install "pyimgano[skimage]"     # scikit-image baselines (SSIM/HOG/LBP/Gabor…)
pip install "pyimgano[numba]"       # Numba-accelerated baselines
pip install "pyimgano[viz]"         # matplotlib / seaborn plots
pip install "pyimgano[diffusion]"   # Diffusion-based methods
pip install "pyimgano[clip]"        # OpenCLIP backends
pip install "pyimgano[faiss]"       # Faster kNN for memory-bank methods
pip install "pyimgano[anomalib]"    # Anomalib checkpoint wrappers
pip install "pyimgano[backends]"    # clip + faiss + anomalib
pip install "pyimgano[all]"         # Everything

See docs/OPTIONAL_DEPENDENCIES.md for the full extras map.


🚀 Quickstart

Python API — 5 lines to detect

from pyimgano.models import create_model

detector = create_model("vision_patchcore", device="cuda")
detector.fit(train_paths)                           # normal/reference images
scores = detector.decision_function(test_paths)     # anomaly scores
Classical baseline (CPU, no pixel maps)
from pyimgano.models import create_model
from pyimgano.utils import ImagePreprocessor

extractor = ImagePreprocessor(resize=(224, 224), output_tensor=False)
detector = create_model("vision_ecod", feature_extractor=extractor, contamination=0.1, n_jobs=-1)

detector.fit(train_paths)
scores = detector.decision_function(test_paths)
labels, confidence = detector.predict(test_paths, return_confidence=True)
NumPy-first industrial inference
import numpy as np
from pyimgano.inference import calibrate_threshold, infer
from pyimgano.inputs import ImageFormat

train_frames = [np.zeros((64, 64, 3), dtype=np.uint8) for _ in range(8)]
detector.fit(train_frames)
calibrate_threshold(detector, train_frames, input_format=ImageFormat.RGB_U8_HWC, quantile=0.995)

results = infer(detector, test_frames, input_format=ImageFormat.RGB_U8_HWC, include_maps=True)
print(results[0].score, results[0].label)

CLI — End-to-end pipeline

# 1. Quick demo (creates dataset + runs suite + exports tables)
pyimgano-demo

# 2. Environment check
pyimgano-doctor --suite industrial-v4

# 3. Train → export infer config
pyimgano-train \
  --config examples/configs/industrial_adapt_defects_fp40.json \
  --export-infer-config

# 4. Inference → JSONL + defect masks
pyimgano-infer \
  --infer-config /path/to/run_dir/artifacts/infer_config.json \
  --input /path/to/images \
  --defects \
  --save-masks /tmp/pyimgano_masks \
  --save-jsonl /tmp/pyimgano_results.jsonl

The JSONL output carries stable deployment metadata for downstream systems, including decision_summary on each success record; Python best-effort batch integrations also receive a triage_summary aggregate from run_continue_on_error_inference(...).

One-off inference (no workbench)
pyimgano-infer \
  --model vision_patchcore \
  --preset industrial-balanced \
  --device cuda \
  --train-dir /path/to/normal/train_images \
  --calibration-quantile 0.995 \
  --input /path/to/images \
  --include-maps

Pass extra kwargs via --model-kwargs '{"backbone":"wide_resnet50","coreset_sampling_ratio":0.1}'.

Model discovery
pyimgano --list models
pyimgano list models
pyimgano -- list models --json
pyimgano --list models --family patchcore
pyimgano --list preprocessing --deployable-only
pyim --list models
pyim --list models --family patchcore
pyim --list models --year 2021 --type deep-vision
pyim --list models --type flow-based
pyim --list preprocessing --deployable-only

pyimgano is now the umbrella CLI. pyimgano list ... and pyimgano -- list ... map to the same discovery flow as pyimgano --list .... pyim remains the shorter discovery alias.

Shortest audited operator path

If you want the shortest “train -> validate -> gate” path for production-style handoff, the root CLI now exposes it directly:

pyimgano --help
pyimgano -- list preprocessing --deployable-only
pyimgano train --config examples/configs/industrial_adapt_audited.json --export-infer-config --export-deploy-bundle
pyimgano validate-infer-config runs/<run_dir>/deploy_bundle/infer_config.json
pyimgano runs quality runs/<run_dir> --require-status audited --json
pyimgano runs acceptance runs/<run_dir> --require-status audited --check-bundle-hashes --json
pyimgano weights audit-bundle runs/<run_dir>/deploy_bundle --check-hashes --json

That flow uses the checked-in industrial_adapt_audited.json example and is described in more detail in docs/INDUSTRIAL_FASTPATH.md.

For reproducible benchmark reporting, pair that operator loop with the built-in official preset discovery and publication gate:

pyimgano benchmark --list-official-configs
pyimgano benchmark --official-config-info official_mvtec_industrial_v4_cpu_offline.json --json
pyimgano runs acceptance /path/to/suite_export --json
pyimgano runs publication /path/to/suite_export --json

That keeps the shortest industrial fast-path and the publication path visible from the same umbrella CLI entrypoint.

If your deploy bundle carries model_card.json and weights_manifest.json, pyimgano weights audit-bundle ... gives you a single delivery gate for both. If you want one aggregated release check instead of calling the low-level validators individually, use pyimgano runs acceptance ...; it now auto-routes run directories and suite publication exports through the matching gate. For suite exports, the publication gate now also enforces benchmark provenance (benchmark_config.source + sha256), evaluation_contract, and citation instead of trusting a manually stamped publication_ready=true. It also expects audit refs back to report.json, config.json, and environment.json, plus matching sha256 digests for those files, so exported leaderboards remain traceable to the saved run. The exported leaderboard tables themselves now carry recorded sha256 digests too, so leaderboard.csv, best_by_baseline.csv, skipped.csv (and markdown variants when exported) are verified before a suite export is treated as publication-ready.


🧠 Model Zoo

pyimgano ships 120+ registered model entry points spanning classical statistics to modern vision-language models.

Algorithm Capability Matrix

Algorithm Capability Matrix

Recommended Baselines

Goal Model Tags Notes
🎯 Strong pixel localization vision_patchcore numpy,pixel_map Best default for MVTec/VisA-style data
🛡️ Robust to noisy normals vision_softpatch numpy,pixel_map Filters outlier patches in memory bank
🪶 Lightweight pixel baseline vision_padim / vision_spade numpy,pixel_map Simpler, easier to tune
📸 Few-shot / small normal set vision_anomalydino numpy,pixel_map DINOv2-based, downloads weights on first run
💻 CPU-only / precomputed vision_ecod / vision_copod classical Fast, parameter-free, score-only
🔌 Anomalib integration vision_*_anomalib deep Requires pyimgano[anomalib]
Full algorithm taxonomy
Category Type Algorithms Count
Statistical Density / Distribution ECOD, COPOD, HBOS, KDE, GMM, MCD, QMCD 24
Proximity Neighbor-based KNN, LOF, COF, LDOF, ODIN, INNE, LoOP 18
Subspace Projection PCA, KPCA, SOD, ROD, LODA 8
Tree / Graph Isolation Isolation Forest, RRCF, HST, MST, R-Graph 10
Ensemble Multi-detector Feature Bagging, LSCP, SUOD, Score Ensemble 6
Memory Bank Patch-based deep PatchCore, PaDiM, SPADE, SoftPatch, MemSeg 12
Student-Teacher Knowledge distill STFPM, Reverse Distillation, EfficientAD, AST 8
Flow-based Normalizing flows FastFlow, CFlow, CS-Flow 6
Reconstruction AE / VAE AE, VAE, VQ-VAE, DRAEM, DFM 10
VLM / Zero-shot Vision-Language WinCLIP, AnomalyDINO, PromptAD 6
Template Pixel statistics SSIM, NCC, Phase correlation, Pixel Gaussian 8
Industrial Pipeline wrappers ResNet18, ONNX, TorchScript pipelines 14+

📖 See docs/ALGORITHM_SELECTION_GUIDE.md for a detailed decision flowchart.


📋 API Cheatsheet

from pyimgano.models import create_model, list_models

# ╭──────────────────────────────────────────────╮
# │  Discovery                                   │
# ╰──────────────────────────────────────────────╯
list_models()                              # all registered names
list_models(tags=["vision", "pixel_map"])  # filter by tags

# ╭──────────────────────────────────────────────╮
# │  Core detector API                           │
# ╰──────────────────────────────────────────────╯
detector = create_model("vision_patchcore", device="cuda", contamination=0.1)

detector.fit(X_train)                      # train on normal images
scores = detector.decision_function(X)     # → np.ndarray of anomaly scores
labels = detector.predict(X)               # → 0 (normal) / 1 (anomaly)
labels, conf = detector.predict(X, return_confidence=True)

# ╭──────────────────────────────────────────────╮
# │  Pixel-level (models with pixel_map tag)     │
# ╰──────────────────────────────────────────────╯
anomaly_map = detector.predict_anomaly_map(image)  # → H×W float array

# ╭──────────────────────────────────────────────╮
# │  Industrial inference                        │
# ╰──────────────────────────────────────────────╯
from pyimgano.inference import infer, calibrate_threshold
from pyimgano.inputs import ImageFormat

calibrate_threshold(detector, X_train, input_format=ImageFormat.RGB_U8_HWC, quantile=0.995)
results = infer(detector, X_test, input_format=ImageFormat.RGB_U8_HWC, include_maps=True)
# results[i].score, results[i].label, results[i].anomaly_map

# ╭──────────────────────────────────────────────╮
# │  Evaluation                                  │
# ╰──────────────────────────────────────────────╯
from pyimgano import evaluate_detector, compute_auroc

metrics = evaluate_detector(detector, X_test, y_test)  # full report
auroc = compute_auroc(y_true, scores)                   # single metric

📊 Benchmarking

Run curated baseline suites with a single command and get aggregated leaderboard tables:

# Discover suites
pyimgano-benchmark --list-suites
pyimgano-benchmark --suite-info industrial-v4 --json

# Run a suite
pyimgano-benchmark \
  --dataset mvtec --root /path/to/mvtec_ad --category bottle \
  --suite industrial-v4 --device cpu --no-pretrained \
  --suite-export both --output-dir /tmp/suite_run

# Optional: small grid search
pyimgano-benchmark \
  --dataset mvtec --root /path/to/mvtec_ad --category bottle \
  --suite industrial-v4 --suite-sweep industrial-template-small \
  --suite-sweep-max-variants 1 --suite-export csv \
  --output-dir /tmp/suite_sweep
Run comparison
pyimgano-runs list --root runs
pyimgano-runs list --root runs --kind robustness --same-robustness-protocol-as runs/run_a --json
pyimgano-runs compare runs/run_a runs/run_b --json
pyimgano-runs compare runs/run_a runs/run_b --baseline runs/run_a --require-same-split --json
pyimgano-runs compare runs/run_a runs/run_b --baseline runs/run_a --require-same-robustness-protocol --json
pyimgano-runs acceptance /path/to/suite_export --json
pyimgano-runs publication /path/to/suite_export --json

Some suite entries are optional and are skipped if extras are missing (with hints like pip install 'pyimgano[torch]'). For reproducible publications, use built-in official presets via --config official_mvtec_industrial_v4_cpu_offline.json.


🎨 Synthetic Anomaly Generation

When real defects are scarce, generate controlled synthetic anomalies for smoke tests, robustness checks, and pixel-mask pipelines:

pyimgano-synthesize \
  --in-dir /path/to/normal_images \
  --out-root ./out_synth_dataset \
  --category synthetic_demo \
  --presets scratch stain tape edge_wear \
  --roi-mask /path/to/roi_mask.png \
  --blend alpha --alpha 0.9 \
  --n-train 50 --n-test-normal 20 --n-test-anomaly 20 \
  --seed 0

Supported presets: scratch · stain · tape · edge_wear · Perlin noise · CutPaste · custom

📖 Guide: docs/SYNTHETIC_ANOMALY_GENERATION.md


🏭 Industrial Outputs (Defects)

When --defects is enabled, pyimgano-infer derives structured defect information from the anomaly map:

graph LR
    A[Anomaly Map] --> B[Threshold]
    B --> C[Binary Mask]
    C --> D[Morphology<br/>open / close / fill]
    D --> E[Connected Components]
    E --> F[Defect Regions]

    F --> G["area · bbox · score"]
    F --> H[ROI Gating]

    style A fill:#1e293b,stroke:#f472b6,color:#e2e8f0
    style C fill:#1e293b,stroke:#818cf8,color:#e2e8f0
    style F fill:#1e293b,stroke:#34d399,color:#e2e8f0
  • Binary defect mask — optional artifact output
  • Connected-component regions — area, bbox, per-region score
  • ROI gating — only flag defects inside the region of interest
  • Morphology — open/close/fill holes to reduce noise
  • Stable triage metadata — per-record decision_summary for review routing and low-confidence rejection handling

📖 Guides: docs/INDUSTRIAL_INFERENCE.md · docs/FALSE_POSITIVE_DEBUGGING.md


🔧 CLI Reference

Command Purpose
pyimgano Top-level umbrella CLI (pyimgano --help, pyimgano list models)
pyimgano-demo Quick end-to-end demo
pyimgano-doctor Environment & dependency check
pyimgano-train Train + export infer_config.json
pyimgano-infer Inference → JSONL + masks
pyimgano-benchmark Suite / sweep benchmarking
pyimgano-synthesize Synthetic anomaly generation
pyimgano-runs Run listing & comparison
pyimgano-weights Weight manifest & model cards
pyimgano-features Feature extraction utilities
pyimgano-datasets Dataset management
pyimgano-defects Defect post-processing
pyim Unified discovery (pyim --list models)

📖 Full reference: docs/CLI_REFERENCE.md

pyimgano-runs quality, pyimgano-runs acceptance, and pyimgano-runs publication now expose structured trust metadata as well:

  • trust_summary for saved run artifacts
  • trust_signals for suite publication bundles

This makes it easier to gate CI/release automation on auditable machine-readable signals instead of parsing free-form warnings.


⚖️ Weights & Cache Policy

  • pyimgano does not ship model weights inside the wheel.
  • Weights are cached by upstream libraries (torchvision / OpenCLIP / HuggingFace).
  • Set cache env vars on servers: TORCH_HOME, HF_HOME, XDG_CACHE_HOME
# Auditable weight management
pyimgano-weights template manifest > ./weights_manifest.json
pyimgano-weights validate ./weights_manifest.json --check-files --json

📚 Documentation

Getting Started

Industrial / Production

Reference


🤝 Contributing

We welcome contributions! Please see:


📄 License

MIT


📝 Citation

GitHub citation metadata is provided via CITATION.cff.

@software{pyimgano2026,
  author    = {PyImgAno Contributors},
  title     = {pyimgano: Production-oriented Visual Anomaly Detection},
  year      = {2026},
  url       = {https://github.com/skygazer42/pyimgano}
}

Made with care for industrial inspection teams.
⭐ Star us on GitHub

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

pyimgano-0.6.38.tar.gz (1.7 MB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

pyimgano-0.6.38-py3-none-any.whl (1.2 MB view details)

Uploaded Python 3

File details

Details for the file pyimgano-0.6.38.tar.gz.

File metadata

  • Download URL: pyimgano-0.6.38.tar.gz
  • Upload date:
  • Size: 1.7 MB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.9.25

File hashes

Hashes for pyimgano-0.6.38.tar.gz
Algorithm Hash digest
SHA256 bceb075ff3e781430f6da2dc87fec8f308a650de87396c699dc3f113172fa2c6
MD5 fd0cded089a36e381b083c82c263ba67
BLAKE2b-256 8ffaac34505ef90fee2efdc0833a97879f07b2ec24d01431644b45f1a196308e

See more details on using hashes here.

File details

Details for the file pyimgano-0.6.38-py3-none-any.whl.

File metadata

  • Download URL: pyimgano-0.6.38-py3-none-any.whl
  • Upload date:
  • Size: 1.2 MB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.9.25

File hashes

Hashes for pyimgano-0.6.38-py3-none-any.whl
Algorithm Hash digest
SHA256 40f4e5a86f28499741543b5ea62a9c1a235c8eb98a6a9b6808cce6dab378078f
MD5 c659719e5b5fcad2c9173e05423bf876
BLAKE2b-256 ddef43db358bbb7da915e6d550cd88091b1a6a979eef07f86bb549a94d637b82

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page