Standalone face recognition pipeline inspired by Vision's robot brain enrolls faces, match a query image, multi-frame voting to CONFIRMED.
Note: This is a pure TypeScript demo. It runs with no native dependencies (no
canvasbuild). Default mode uses deterministic MOCK embeddings so install and tests work on Windows, WSL, and Bun. Same photo content always produces the same vector, so matching is reliable for learning the pipeline.
- Enroll from folders β each subfolder under
data/is a person; every image inside becomes a reference embedding. - Match a query β place a photo in
input/(or pass a path); the pipeline embeds it and finds the nearest person. - Distance threshold β Euclidean distance β€
0.5counts as a candidate match (configurable). - Multi-frame voting β one agreeing frame β
PROVISIONAL; 3 agreeing frames βCONFIRMED(same idea as Vision's live recognizer). - Terminal-first β one command runs the whole flow; no UI required.
| Path | What's there |
|---|---|
test.ts |
Root test β loads data/, processes input/, prints match + status |
input/ |
Query image(s) to recognize |
data/<person>/ |
Reference photos (2β3 per person is enough) |
src/config.ts |
Thresholds (matchDistance, requiredVotes, paths) |
src/pipeline.ts |
Embedding, gallery load, nearest-neighbor, multi-frame voter |
src/enroll.ts |
List how many faces are enrolled per person |
tsconfig.json |
TypeScript config |
# Install dependencies (TypeScript + tsx only β no native compile)
npm install
# or: bun installWorks from:
| Environment | Notes |
|---|---|
| Linux / macOS | npm install then npm test |
| WSL | Prefer project under ~/ (not only /mnt/c/...) to avoid symlink issues |
| Windows | npm install or bun install; run with npx tsx test.ts |
No .env required. No API keys. No model download required for the default MOCK path.
npm run download-modelsnpm test
# or: npx tsx test.ts
# or: bunx tsx test.tsOptional:
npm run enroll # list enrolled people and face counts
npm run typecheck # tsc --noEmitPass a specific image:
npx tsx test.ts path/to/photo.jpg| You do | What happens |
|---|---|
Put photos in data/alice/ and data/bob/ |
Gallery builds on next npm test |
Put a photo of Alice in input/test.jpg |
Best match β alice, status PROVISIONAL (1 frame) |
Put 3 similar frames in input/ |
After 3 agreeing votes β status CONFIRMED |
Use a photo of someone not in data/ |
Best match none / UNKNOWN |
Change matchDistance in src/config.ts |
Tighter or looser matching |
Enroll your own faces:
data/
yourname/
photo1.jpg
photo2.jpg
photo3.jpg β 2β3 angles/lighting is ideal
input/
test.jpg β the image to recognize
Then:
npm testinput image
β
embedding (128-d vector from file content in MOCK mode)
β
nearest-neighbor search against data/ gallery
β
distance β€ matchDistance? β candidate person
β
multi-frame voting β PROVISIONAL | CONFIRMED | UNKNOWN
| Stage | Behavior |
|---|---|
| Enrollment | Every image under data/<person>/ becomes one reference vector |
| Query | input/ images (or CLI paths) are embedded the same way |
| Match | Lowest Euclidean distance under threshold wins |
| Voting | Track accumulates votes; requiredVotes (default 3) β CONFIRMED |
This mirrors Vision's pipeline shape (embed β nearest neighbor β multi-frame identity voting), simplified into a single local project.
- MOCK by design: Embeddings are deterministic from file bytes. Identical content always matches; different files get different vectors. No GPU, no model weights, no
canvasnative build. - Why not real face-api by default?
canvas+ prebuilt binaries often fail on Windows Node 26, Bun, and WSL mounts under/mnt/c. Keeping zero native deps makesnpm installandnpm testreliable everywhere. - Status meanings:
CONFIRMED= enough agreeing frames to act on;PROVISIONAL= leaning toward a person but not yet confirmed;UNKNOWN= no usable match. - Config: All thresholds live in
src/config.tsβmatchDistance(default0.5),requiredVotes(default3),maxVotesPerTrack, paths todata/andinput/. - Safety of interpretation: A single frame never becomes
CONFIRMED. That matches Vision's conservative live recognizer (avoid trusting one lucky frame). - Sample data: The project includes placeholder JPEGs under
data/alice,data/bob, andinput/test.jpgso the firstnpm testproduces a visible match without your own photos.
