An anomaly detection project built around mandarin images, originally developed as a final degree thesis and later rebuilt as a modern, reproducible anomalib pipeline.
This repository intentionally preserves both:
- a historical reconstruction of the original thesis work
- a modern implementation in
Python 3.12withanomalib 2.4.1
The original project studied visual anomaly detection through anomalib, benchmarked several image-based methods, and closed with a small IoT-style mandarin inspection scenario inspired by PYNQ-Z2.
Three years later, the project was revisited and rebuilt with a cleaner engineering setup:
src/-based package structure- deterministic dataset splits
- benchmark scripts
- final training and inference scripts
- report notebooks and exported HTML artifacts
The goal is not only to preserve the academic project, but to turn it into a public, readable, reproducible portfolio repository.
- Historical baseline traced back to
anomalib 0.3.7 - Modern pipeline built with
Python 3.12andanomalib 2.4.1 - Canonical mandarin dataset with normal and anomalous cropped images
- Reproducible multi-seed benchmark
- Final inference examples with visual anomaly outputs
- Public-ready repository structure with lightweight tracked artifacts
Models benchmarked on data/mandarins_pynq_cropped:
PatchCoreAnomalyDINO
Current leaderboard:
| Model | Mean AUROC | Mean AUPR | Mean F1 | Mean latency (ms) |
|---|---|---|---|---|
| PatchCore | 0.9333 | 0.9398 | 0.8407 | 173.66 |
| AnomalyDINO | 0.7867 | 0.8111 | 0.5516 | 106.28 |
Winner:
PatchCore
Final training summary on the locked seed=42 setup:
image_AUROC:0.9200image_AUPR:0.9267image_F1Score:0.8333latency_ms:220.39
Modern inference artifacts are already included in the repository:
Example visual outputs:
| Normal prediction | Anomalous prediction |
|---|---|
![]() |
![]() |
.
βββ artifacts/modern/ # Public benchmark summaries, prediction tables, lightweight visuals
βββ configs/modern/ # Dataset, model, benchmark and final-train YAML configs
βββ data/ # Mandarin datasets and inference samples
βββ docs/ # Thesis PDFs, extracted text, reconstruction notes, exported HTML
βββ legacy/ # Historical archived material, including the old anomalib snapshot
βββ notebooks/ # Historical notebooks + modern report notebooks
βββ notes/ # Small auxiliary notes/configs kept for context
βββ src/mandarine/ # Modern Python package
βββ tests/ # Lightweight tests for splits and configs
The canonical dataset for the modern experiment is:
data/mandarins_pynq_cropped
It contains:
33normal images7anomalous images
Other preserved data folders:
data/mandarins_pynq_raw: raw examples and historical contextdata/mandarins_pynq_augmented: legacy-only material, not used in the modern pipelinedata/webcam_inference_images: inference demo images
The historical part of the repository exists for traceability and documentation.
- Reference version:
anomalib 0.3.7 - Intended environment:
Python 3.8 - Dependency file:
requirements-legacy.txt
The old partial local anomalib copy was removed from the repository root and archived under:
That keeps the history available without polluting imports in the modern pipeline.
The modern layer uses:
Python 3.12anomalib 2.4.1- structured configs
- deterministic train/val/test splits
- scriptable benchmark, training, inference and reporting
- Base dataset:
data/mandarins_pynq_cropped - Fixed seeds:
13,23,42 - Per-seed split:
- normal images:
23train,5val,5test - anomalous images:
2val,5test
- normal images:
- No anomalous images are used during training
- Augmentations are applied only on-the-fly to normal training images
- Winner selection rule:
- highest mean
image_AUROC - tie-break on mean
image_AUPR - final tie-break on lower latency
- highest mean
py -3.12 -m venv .venv-modern
.venv-modern\Scripts\activate
python -m pip install --upgrade pip
python -m pip install -r requirements-modern.txtThe modern requirements install the local package in editable mode, so all python -m mandarine... commands work without manual PYTHONPATH setup.
py -3.8 -m venv .venv
.venv\Scripts\activate
python -m pip install --upgrade pip
python -m pip install -r requirements-legacy.txt
python -m pip install anomalib==0.3.7 --no-depspython -m mandarine.data.preparepython -m mandarine.experiments.benchmarkLighter CPU-only examples:
python -m mandarine.experiments.benchmark --models patchcore anomalydino
python -m mandarine.experiments.benchmark --models patchcore --seeds 42python -m mandarine.experiments.train_finalpython -m mandarine.inference.predict_folderpython -m mandarine.reporting.build_reportTo keep the repository public-friendly and lightweight, only compact and useful modern artifacts are tracked:
artifacts/modern/benchmark/*.csvartifacts/modern/benchmark/metrics_summary.jsonartifacts/modern/benchmark/figures/*.pngartifacts/modern/final_model/final_model_summary.jsonartifacts/modern/predictions/*.csvartifacts/modern/predictions/*.jsonartifacts/modern/predictions/visualizations/*.png
Heavy training directories, checkpoints, caches and duplicated generated images are intentionally ignored.
notebooks/tfg_experiments.ipynbnotebooks/model_boosting_experiments.ipynbnotebooks/iot_orange_experiments.ipynb
notebooks/modern_benchmark_report.ipynbnotebooks/modern_inference_demo.ipynb
The modern notebooks are report-oriented: they read generated artifacts rather than training models directly.
pytestCurrent tests cover:
- deterministic split generation
- expected split counts
- no anomaly leakage into train
- config loading and path resolution
- The current benchmark is CPU-first because no GPU is available in this machine context
EfficientAdis supported in the modern configuration but is heavier to prepare because it downloads auxiliary assets such asImagenette- The mandarin dataset does not include segmentation masks, so evaluation is image-level rather than pixel-level
docs/tfg_memoria.pdfdocs/tfg_memoria.full.txtdocs/tfg_presentacion.pdfdocs/tfg_presentacion.full.txtdocs/reconstruction_notes.md
This repository code is released under the MIT License.
The thesis PDFs and historical academic materials are preserved as project context.

