| identities | ||
| metadata | ||
| model | ||
| negatives | ||
| reports/evaluation | ||
| scripts | ||
| src | ||
| videos | ||
| .dockerignore | ||
| .gitignore | ||
| bun.lock | ||
| bunfig.toml | ||
| docker-compose.yml | ||
| Dockerfile | ||
| eslint.config.js | ||
| global.d.ts | ||
| next-env.d.ts | ||
| next.config.ts | ||
| package.json | ||
| postcss.config.mjs | ||
| README.md | ||
| tsconfig.json | ||
OpenID
Small workbench for a visual search PoC as part of the IMT4126 course in Biometrics at NTNU Gjøvik.
Stack
- Next.js App Router for the web application
- TypeScript for the application and API layer
- Python for the model service
- Docker Compose for deployment
Application pages
/Workbench/benchmarkBenchmark runner for immediate baseline comparison and result visualization/feedsContinuous monitoring page for configured public feeds/dataset/imagesImage management/dataset/videosVideo management
Search flow
The application uses a service-backed search pipeline:
- The Next.js API loads the benchmark metadata from disk.
- The Python model service computes reference embeddings for each identity.
- A user can search by:
- public name or subject alias
- uploaded reference image
- watched live feed snapshot URLs
- a weighted mix of both
- Feedback from the training panel promotes or suppresses identities on subsequent searches.
The current model service uses a lightweight visual embedding pipeline that is compatible with the dataset and container-friendly. It is isolated behind a dedicated service so it can later be replaced by a stronger pretrained model without rewriting the app.
Current integrated retrieval models:
handcrafted_v1original histogram-and-edge baselinespatial_hybrid_v2stronger multi-region comparison descriptorcenter_focus_v1center-cropped comparison descriptor with less background influenceconservative_hybrid_v3center-weighted descriptor with stricter open-set behavior for unrelated imagery and the current default in the appopenclip_vit_b32_v1pretrained OpenCLIP baselineinsightface_buffalo_l_v1pretrained InsightFace face-embedding baseline
OpenCLIP and InsightFace both download model weights on first use. They are subsequently cached.
Identity labels
Only identity 1 retains a verified public name from the original material. The remaining entries use stable aliases such as Subject 014 because the source footage does not provide reliable verified names for every person. This keeps the benchmark usable without fabricating unsupported civil identity claims.
Each identity record includes:
display_namesexapprox_agereference_imagesreference_sourcenotes
The dataset contains more than thirty reference files in total.
Run with Docker Compose
The primary development and demo path is Docker Compose:
docker compose up --build
This starts:
openidon port3000openid_modelon the internal compose network at port8000
Then open:
http://localhost:3000
The dataset directories are mounted into both containers at runtime, so the build does not copy the full media corpus into the Docker image.
The model container now starts fast with only the core Python runtime installed in the image.
Heavy pretrained dependencies are bootstrapped into the mounted model_cache volume in the background after startup instead of blocking docker compose build.
Evaluation
The repository now includes a baseline evaluation script:
.venv-model/bin/python scripts/evaluate_benchmark.py
It currently runs a two-protocol benchmark suite and writes reports to:
reports/evaluation/benchmark_results.jsonreports/evaluation/benchmark_results.md
Protocols:
Reference Hold-Outleave-one-reference-out retrieval over the indexed galleryTarget Videos + Distractorsone sampled frame per target video plus 50 distractor clips for open-set false-positive pressure
Current measured baselines:
handcrafted_v1spatial_hybrid_v2center_focus_v1conservative_hybrid_v3
Latest saved results:
Reference Hold-Outhandcrafted_v1: Top-10.667, Top-50.667, MRR0.714spatial_hybrid_v2: Top-10.667, Top-50.667, MRR0.690conservative_hybrid_v3: Top-10.333, Top-50.667, MRR0.462
Target Videos + Distractorshandcrafted_v1: Top-10.800, Top-50.933, MRR0.846, negative rejection0.240spatial_hybrid_v2: Top-10.867, Top-51.000, MRR0.925, negative rejection0.640conservative_hybrid_v3: Top-10.733, Top-50.900, MRR0.829, negative rejection1.000
Important protocol note: only 3 of the 32 reference queries are currently eligible under leave-one-out, because most identities only have one reference image. The benchmark UI and reports surface this explicitly.
The most important current finding is the tradeoff between retrieval and safety:
spatial_hybrid_v2is the strongest measured retrieval baseline on target clipsconservative_hybrid_v3is the safest measured open-set baseline on distractors
OpenCLIP is also integrated as a stronger pretrained comparison model for local evaluation, but the latest saved report focuses on the three faster baselines above so iteration stays practical.
Run without Docker
To run without Docker:
npm install
npm run dev
In a separate shell, start the model service:
.venv-model/bin/pip install -r model/requirements.txt
.venv-model/bin/uvicorn model.app.main:app --host 0.0.0.0 --port 8000
Then open:
http://localhost:3000