An educational collection of reproducible experiments in biometric verification and classical face recognition. The repository implements the core numerical steps explicitly with NumPy, making each method compact enough to study while still producing publication-ready plots, CSV summaries, and reusable projection artifacts.
The project covers score-based verification, Eigenfaces, Fisherfaces, illumination normalization, and local patch descriptors.
- Explicit implementations of ROC metrics, PCA, LDA, KNN, integral images, and patch-level voting.
- Deterministic dataset protocols and validation of the expected directory structure.
- A single command that regenerates every table, model artifact, and figure.
- Focused unit tests for the numerical building blocks.
- Generated results are versioned, so the repository remains browsable without access to the original image datasets.
| Experiment | Method | Dataset / input | Main output |
|---|---|---|---|
| Performance metrics | ROC, AUC, EER, d-prime | Client and impostor scores | Verification operating points |
| Eigenfaces | PCA + KNN | ORL | Error across PCA dimensions |
| Fisherfaces | PCA + LDA + KNN | ORL | Fisherfaces vs Eigenfaces |
| Local normalization | Local statistics + CLAHE | Extended Yale B | Illumination-distance analysis |
| Local face features | Patch PCA + local voting | ORL | Patch and window-size sweeps |
All experiments were regenerated on June 12, 2026 with Python 3.11.7.
| Experiment | Best or representative result |
|---|---|
| Verification system A | AUC 0.8832, EER 0.2013, d-prime 1.0747 |
| Verification system B | AUC 0.8831, EER 0.2010, d-prime 1.2353 |
| Eigenfaces | 89.5% accuracy with d'=80, k=1 |
| Fisherfaces | 85.5% accuracy with d'=39, k=1 |
| Local normalization | Mean cosine distance reduced from 0.1210 to 0.0696 with window 35 |
| Local features | 56.9% accuracy with sequential patches, window 16, and 12 patches |
These values describe the fixed protocols implemented in this repository; they should not be interpreted as general benchmarks for the underlying datasets.
| Eigenfaces | Fisherfaces |
|---|---|
![]() |
![]() |
Python 3.11 is recommended.
git clone https://github.com/JordiCan/biometry.git
cd biometry
python -m venv .venv
source .venv/bin/activate
python -m pip install --upgrade pip
python -m pip install -r requirements.txtThe main dependencies are NumPy, SciPy, Matplotlib, Pillow, and scikit-image. Matplotlib uses a non-interactive backend, so the experiments also run on headless systems and in CI environments.
The image datasets are intentionally excluded from Git because of their size
and licensing terms. Obtain them from their official or authorized source and
place them under data/ with this layout:
data/
├── IDENTIFICACION/
│ └── ORLProcessed/
│ ├── Train/
│ │ ├── s1/1.pgm ... 5.pgm
│ │ └── ...
│ └── Test/
│ ├── s1/6.pgm ... 10.pgm
│ └── ...
└── ILLUMINATION/
└── YaleB/
├── yaleB02/*.pgm
├── yaleB03/*.pgm
└── ...
The verification score files are small and are included in
performance_metrics/data/. The ORL scripts expect 40 subjects and the fixed
1-5 train / 6-10 test protocol. The local-feature experiment uses images
1-2 for training and 3-10 for testing. The illumination experiment selects
12 Yale B subjects and 24 images per subject.
Run every experiment and auxiliary plot generator in a stable order:
python run_all.pyOn the reference environment the full run takes roughly two minutes. Each script can also be executed independently:
python performance_metrics/evaluate.py
python performance_metrics/evaluate_heaviside.py
python eigenfaces/eigenfaces.py
python eigenfaces/aux.py
python fisherfaces/fisherfaces.py
python local_face_normalization/local_face_normalization.py
python local_face_normalization/aux.py
python local_face_features/local_face_features.pyOutputs are written to each experiment's plots/ directory. Eigenfaces and
Fisherfaces additionally save learned means, projection matrices, labels, and
projected vectors under outputs/.
The unit tests do not require the image datasets:
python -m unittest discover -s tests -vGitHub Actions runs the same tests on Python 3.10, 3.11, and 3.12.
.
├── performance_metrics/ # Verification metrics and score plots
├── eigenfaces/ # PCA face recognition
├── fisherfaces/ # PCA + LDA face recognition
├── local_face_normalization/ # Illumination preprocessing
├── local_face_features/ # Patch descriptors and local voting
├── tests/ # Dataset-independent regression tests
├── run_all.py # Full reproduction entry point
├── requirements.txt
└── LICENSE
Each experiment directory has its own README with method details, generated figures, output descriptions, and an interpretation of the results.
- The experiments contain no random sampling; repeated runs with the same dependency versions and datasets are deterministic.
- CSV values are rounded for presentation, while calculations use
float64. - AUC uses pairwise client/impostor comparisons with half credit for ties.
- The threshold convention is
score >= threshold. d-primeuses the pooled population variance:(mean_client - mean_impostor) / sqrt((var_client + var_impostor) / 2).- Generated binary arrays can vary at the last floating-point digits across BLAS/LAPACK implementations while preserving the reported metrics.
The source code is available under the MIT License. Dataset licenses remain with their respective owners and are not covered by this repository's license.



