@@ -4,7 +4,7 @@ This file provides guidance to Claude Code (claude.ai/code) when working with co
44
55## Project Overview
66
7- FaceVector Engine - A production-ready face recognition and vector similarity search engine. A Node.js/TypeScript system using ArcFace embeddings for face recognition, RetinaFace for face detection with landmarks, and PostgreSQL with pgvector extension for efficient vector similarity search.
7+ FaceVector Engine - A production-ready face recognition and vector similarity search engine. A Node.js/TypeScript system using InsightFace Buffalo-L embeddings for face recognition, RetinaFace for face detection with landmarks, and PostgreSQL with pgvector extension for efficient vector similarity search.
88
99** 📚 Technical Documentation:** See [ TECHNICAL_DETAILS.md] ( TECHNICAL_DETAILS.md ) for comprehensive technical documentation including image processing pipelines, coordinate transformations, model inference workflows, and performance optimizations.
1010
@@ -18,12 +18,12 @@ FaceVector Engine - A production-ready face recognition and vector similarity se
1818``` bash
1919make install # Install Node dependencies (production only)
2020make install-dev # Install all dependencies including dev tools
21- make models # Download ONNX models (arcface .onnx, retinaface_resnet50.onnx) to models/
21+ make models # Download ONNX models (face_recognition .onnx, retinaface_resnet50.onnx) to models/
2222make chmod-scripts # Make scripts in scripts/ executable
2323```
2424
2525** Model Downloads** (` make models ` ):
26- - ArcFace (arcfaceresnet100-8 .onnx) from HuggingFace → saved as ` models/arcface .onnx `
26+ - InsightFace Buffalo-L ( ` w600k_r50 .onnx` ) from HuggingFace → saved as ` models/face_recognition .onnx `
2727- RetinaFace ResNet50 from Google Storage → saved as ` models/retinaface_resnet50.onnx `
2828- Models only downloaded if they don't already exist
2929
@@ -56,9 +56,9 @@ make lint-fix # Auto-fix TypeScript code style issues
5656## Architecture
5757
5858### Core Flow
59- 1 . ** Server startup** (` src/server.ts ` ): Initialize DB connection → Load ONNX models (ArcFace + RetinaFace) → Start Express server
59+ 1 . ** Server startup** (` src/server.ts ` ): Initialize DB connection → Load ONNX models (InsightFace + RetinaFace) → Start Express server
60602 . ** Face detection** (` src/retinaface.ts ` , ` src/embedding.ts ` ): RetinaFace detects faces with configurable thresholds
61- 3 . ** Embedding generation** (` src/embedding.ts ` ): ArcFace generates 512-dim vectors from 112x112 RGB images
61+ 3 . ** Embedding generation** (` src/embedding.ts ` ): InsightFace generates 512-dim vectors from landmark-aligned 112x112 BGR images
62624 . ** Storage** (` src/db.ts ` ): PostgreSQL with pgvector extension for vector similarity search
6363 - ` detected_faces ` table: Face metadata and file paths from detection
6464 - ` enrolled_customers ` table: Customer info with face embeddings for recognition
@@ -67,15 +67,15 @@ make lint-fix # Auto-fix TypeScript code style issues
6767### Key Components
6868
6969** ONNX Model Pipeline** :
70- - ` initModels() ` (` src/embedding.ts ` ): Loads ArcFace (embedding) and RetinaFace (detection) ONNX models at startup
70+ - ` initModels() ` (` src/embedding.ts ` ): Loads InsightFace (embedding) and RetinaFace (detection) ONNX models at startup
7171- ` detectAllFacesWithRetinaFace(base64) ` (` src/embedding.ts ` ): RetinaFace inference returning all detected faces with bounding boxes
7272 - Input: 640x640 (mobile) or 840x840 (resnet50) resized image
7373 - Multi-scale detection with strides [ 8, 16, 32]
7474 - Default confidence threshold: 0.8 (VIS_THRESHOLD), configurable via env var FACE_DETECTION_CONFIDENCE_THRESHOLD
7575 - NMS (Non-Maximum Suppression) threshold: 0.4 to filter overlapping boxes
7676 - Returns array of faces sorted by area (largest first) with landmarks (eyes, nose, mouth)
77- - ` preprocessImage(base64) ` (` src/embedding.ts ` ): Resize to 112x112, normalize to [ -1, 1] per channel
78- - ` computeEmbedding(preprocessed) ` (` src/embedding.ts ` ): ArcFace inference → 512-dim Float32Array
77+ - ` preprocessImage(base64) ` (` src/embedding.ts ` ): Resize to 112x112, BGR channel-first layout, normalize to [ -1, 1] per channel
78+ - ` computeEmbedding(preprocessed) ` (` src/embedding.ts ` ): InsightFace inference → 512-dim Float32Array
7979- RetinaFace model (` src/retinaface.ts ` ): Detects faces with 5 facial landmarks per face
8080
8181** Database Layer** (` src/db.ts ` ):
@@ -86,15 +86,15 @@ make lint-fix # Auto-fix TypeScript code style issues
8686 - ` face_embeddings(id uuid, embedding vector(512), image_path text, created_at timestamptz) ` - Legacy table
8787- ivfflat index on ` enrolled_customers.embedding ` for fast similarity search
8888- Handles collation version mismatches (suggests ` make clean ` if detected)
89- - Images stored in MinIO S3 object storage, S3 keys stored in ` original_image_path ` and ` face_image_path ` columns
89+ - Images stored in RustFS S3-compatible object storage, S3 keys stored in ` original_image_path ` and ` face_image_path ` columns
9090
9191** Service Layer** :
9292- ` src/services/faceDetectionService.ts ` : Detect faces, crop, and store metadata
9393 - ` detectAndStoreFaces() ` : Main detection workflow
94- - Uploads original images to MinIO S3: ` originals/{uuid}.jpg `
95- - Uploads cropped faces to MinIO S3: ` faces/{face_id}.jpg `
94+ - Uploads normalized original images to RustFS S3: ` originals/{uuid}.jpg `
95+ - Uploads cropped faces to RustFS S3: ` faces/{face_id}.jpg `
9696 - Stores S3 keys (not file paths) in database
97- - ` src/services/s3Service.ts ` : MinIO S3 storage service
97+ - ` src/services/s3Service.ts ` : RustFS S3-compatible storage service
9898 - ` uploadImage() ` : Upload image buffer to S3
9999 - ` downloadImage() ` : Download image from S3 as buffer
100100 - ` deleteImage() ` : Delete image from S3
@@ -118,7 +118,7 @@ make lint-fix # Auto-fix TypeScript code style issues
118118** Middleware** :
119119- ` src/middleware/upload.ts ` : Multer configuration for multipart file uploads
120120 - Memory storage for file buffers
121- - Accepts PNG, JPG, WEBP (max 10MB)
121+ - Accepts PNG, JPG, WEBP, AVIF (max 10MB)
122122 - File type validation
123123
124124** Controllers** (` src/controllers/ ` ):
@@ -153,44 +153,47 @@ make lint-fix # Auto-fix TypeScript code style issues
153153
154154### Error Handling
155155- All face-processing endpoints throw ` {code: "NO_FACE"} ` errors → Returns ` {"error": "no_face_detected"} ` (400)
156- - Face detection configured to reject images without faces (e.g., ` examples/box .jpeg ` )
156+ - Face detection configured to reject images without faces (e.g., ` examples/no_face_box .jpeg ` )
157157- Standardized error responses via ` responseHelpers.sendErrorResponse() `
158158
159159### API Input Format & Storage
160160
161161** Multipart Upload Design:**
162162- Primary API accepts multipart form-data (actual file uploads)
163163- Scripts handle file path → multipart conversion automatically
164- - Images automatically scaled down (max 1920px) for performance
165- - Supports PNG, JPG, WEBP formats (max 10MB per file)
164+ - Images normalized through Sharp into auto-rotated JPEG buffers, then scaled down (max 1920px) for performance
165+ - Supports PNG, JPG, WEBP, AVIF formats (max 10MB per file)
166166- API is stateless and production-ready
167167
168168** ONNX Models:**
169- - ArcFace : ` models/arcface .onnx ` (face embeddings)
169+ - Face recognition : ` models/face_recognition .onnx ` (InsightFace embeddings)
170170- RetinaFace: ` models/retinaface_resnet50.onnx ` (face detection)
171171- Downloaded via ` make models ` from HuggingFace/Google Storage
172172
173173** Storage Architecture:**
174- - ** MinIO S3 Object Storage** (bucket: ` facevector-engine ` ):
175- - ` originals/{uuid}.jpg ` - Original uploaded images
174+ - ** RustFS S3-Compatible Object Storage** (bucket: ` facevector-engine ` ):
175+ - ` originals/{uuid}.jpg ` - Normalized uploaded images
176176 - ` faces/{face_id}.jpg ` - Cropped face images
177177 - S3 keys stored in ` detected_faces ` table columns
178- - Access MinIO Console at http://localhost:9001
178+ - Access RustFS Console at http://localhost:9001
179179- ** Temporary Files** (ephemeral, inside Docker):
180180 - ` /tmp/facevector/cropped_faces/ ` - Temporary face crops during processing
181181 - Auto-cleaned on container restart, no volume mount needed
182182
183183## Testing
184184Use example images in ` examples/ ` folder:
185- - ` elon_musk_1.jpg ` , ` elon_musk_2.jpg ` - Valid face images for testing (same person)
186- - ` elon_musk_trump.jpg ` - Multiple faces in one image
187- - ` xijingping.png ` , ` xijingping_trump.jpeg ` - Additional test images
188- - ` box.jpeg ` - No face (for testing detection rejection)
185+ - ` elon_musk_enroll.jpg ` , ` elon_musk_positive.jpg ` - Valid Elon images for testing (same person)
186+ - ` jensen_huang_enroll.jpg ` , ` jensen_huang_positive.jpg ` - Valid Jensen images for testing (same person)
187+ - ` elon_musk_trump_mixed_small.jpg ` , ` xi_jinping_trump_mixed_small.jpeg ` - Multiple faces in one image
188+ - ` elon_musk_jensen_huang_mixed_large.webp ` , ` elon_musk_jensen_huang_mixed_large.avif ` - Multi-format normalization fixtures
189+ - ` elon_musk_profile.jpg ` , ` trump_jensen_huang_mixed_profile.jpeg ` - Hard profile/angle examples
190+ - ` xi_jinping_solo.png ` - Additional negative test image
191+ - ` no_face_box.jpeg ` - No face (for testing detection rejection)
189192
190193Example scripts in ` scripts/ ` (run ` make chmod-scripts ` first):
191194``` bash
192195# Main workflow
193- ./scripts/faces-detect.sh examples/elon_musk_1 .jpg [identifier]
196+ ./scripts/faces-detect.sh examples/elon_musk_enroll .jpg [identifier]
194197./scripts/faces-get-image.sh < face_id>
195198./scripts/faces-enroll.sh < face_id> < customer_id> [name]
196199./scripts/faces-recognize.sh < face_id>
@@ -210,20 +213,20 @@ All scripts accept optional API URL as last parameter (default: http://localhost
210213** Workflow Example:**
211214``` bash
212215# 1. Detect face and get face_id
213- ./scripts/faces-detect.sh examples/elon_musk_1 .jpg CUST001
216+ ./scripts/faces-detect.sh examples/elon_musk_enroll .jpg CUST001
214217# Response: [{"face_id": "abc-123...", ...}]
215218
216219# 2. Enroll the customer
217220./scripts/faces-enroll.sh abc-123... CUST001 " Elon Musk"
218221# Response: {"customer_id": "xyz-789...", ...}
219222
220223# 3. Later, detect face in another image of the same person
221- ./scripts/faces-detect.sh examples/elon_musk_2 .jpg
224+ ./scripts/faces-detect.sh examples/elon_musk_positive .jpg
222225# Response: [{"face_id": "def-456...", ...}]
223226
224227# 4. Recognize who it is
225228./scripts/faces-recognize.sh def-456...
226- # Response: [{"customer_identifier": "CUST001", "confidence_score": 0.98 , ...}]
229+ # Response: [{"customer_identifier": "CUST001", "confidence_score": 0.6708 , ...}]
227230```
228231
229232## Configuration
@@ -232,15 +235,13 @@ All scripts accept optional API URL as last parameter (default: http://localhost
232235- ` DATABASE_URL ` : PostgreSQL connection string (default: ` postgres://postgres:postgres@localhost:5432/face_db ` )
233236- ` PORT ` : API server port (default: 3000)
234237- ` FACE_DETECTION_CONFIDENCE_THRESHOLD ` : Face detection confidence threshold 0.0-1.0 (default: 0.8)
235- - ** MinIO S3 Configuration:**
236- - ` MINIO_ROOT_USER ` : MinIO admin username (default: minioadmin)
237- - ` MINIO_ROOT_PASSWORD ` : MinIO admin password (default: minioadmin123)
238- - ` S3_ENDPOINT ` : S3 endpoint URL (default: http://localhost:9000 for local, http://minio:9000 inside Docker)
238+ - ** RustFS S3 Configuration:**
239+ - ` S3_ENDPOINT ` : S3 endpoint URL (default: http://localhost:9000 for local, http://rustfs:9000 inside Docker)
239240 - ` S3_BUCKET ` : S3 bucket name (default: facevector-engine)
240- - ` S3_ACCESS_KEY ` : S3 access key (default: minioadmin )
241- - ` S3_SECRET_KEY ` : S3 secret key (default: minioadmin123 )
241+ - ` S3_ACCESS_KEY ` : S3 access key (default: rustfsadmin )
242+ - ` S3_SECRET_KEY ` : S3 secret key (default: rustfsadmin )
242243 - ` S3_REGION ` : S3 region (default: us-east-1)
243- - ` S3_FORCE_PATH_STYLE ` : Use path-style URLs for MinIO (default: true)
244+ - ` S3_FORCE_PATH_STYLE ` : Use path-style URLs for RustFS (default: true)
244245
245246** Configuration Constants** (` src/config/constants.ts ` ):
246247- ` RETINAFACE.CONFIDENCE_THRESHOLD ` : 0.02 (initial detection threshold, filtered by VIS_THRESHOLD later)
@@ -279,8 +280,3 @@ All scripts accept optional API URL as last parameter (default: http://localhost
279280- ` tsx ` : TypeScript execution for development
280281- ` eslint ` : Code linting
281282- ` @types/* ` : TypeScript type definitions
282-
283- ** Removed (no longer used):**
284- - ` uuid ` : Replaced with Node.js built-in ` crypto.randomUUID() `
285- - ` body-parser ` : Replaced with Express built-in ` express.json() `
286- - ` zod ` : Validation removed (now done at application level)
0 commit comments