diff --git a/architecture-diagram.md b/architecture-diagram.md new file mode 100644 index 0000000..4e45a3d --- /dev/null +++ b/architecture-diagram.md @@ -0,0 +1,134 @@ +# Face Recognition Service - Architecture Diagram + +```mermaid +graph TB + %% External Layer + User[👤 User] --> GradioUI[🖥️ Gradio Web Interface] + + %% Presentation Layer + subgraph "Presentation Layer" + GradioUI --> |Web Requests| GradioApp[gradio_app.py] + end + + %% Application Layer + subgraph "Application Layer" + GradioApp --> RegisterUC[📝 RegisterFaceUseCase] + GradioApp --> VerifyUC[🔍 VerifyFaceUseCase] + GradioApp --> IdentifyUC[🔎 IdentifyFaceUseCase] + + RegisterUC --> FaceService[⚙️ FaceRecognitionService] + VerifyUC --> FaceService + IdentifyUC --> FaceService + end + + %% Domain Layer + subgraph "Domain Layer" + FaceService --> Face[👤 Face Entity] + FaceService --> User[👨‍💼 User Entity] + FaceService --> VResult[✅ VerificationResult] + FaceService --> IResult[🎯 IdentificationResult] + + FaceRepo[📊 FaceRepository Interface] + VectorStore[🗂️ VectorStore Interface] + end + + %% Infrastructure Layer + subgraph "Infrastructure Layer" + %% ML Components + subgraph "ML Components" + RetinaFace[📷 RetinaFaceDetector] + SFaceRec[🧠 SFaceRecognizer] + end + + %% Storage Components + subgraph "Storage Components" + MongoDB[🗄️ MongoDBFaceRepository] + ChromaDB[🔗 ChromaDBVectorStore] + FileSystem[📁 FileSystemStorage] + end + + %% Configuration & Logging + subgraph "Cross-cutting Concerns" + Config[⚙️ Settings] + Logger[📋 Logging System] + end + end + + %% External Systems + subgraph "External Systems" + MongoDBServer[(🗄️ MongoDB Database)] + ChromaDBServer[(🔗 ChromaDB Vector DB)] + FileStorage[(📁 File System)] + ONNXModel[🧠 SFace ONNX Model] + end + + %% Service Dependencies + FaceService --> RetinaFace + FaceService --> SFaceRec + FaceService --> FaceRepo + FaceService --> VectorStore + FaceService --> FileSystem + + %% Repository Implementations + FaceRepo -.->|implements| MongoDB + VectorStore -.->|implements| ChromaDB + + %% External Connections + MongoDB --> MongoDBServer + ChromaDB --> ChromaDBServer + FileSystem --> FileStorage + SFaceRec --> ONNXModel + + %% Use Case Dependencies + RegisterUC --> UserRepo[👨‍💼 MongoDBUserRepository] + VerifyUC --> UserRepo + IdentifyUC --> UserRepo + UserRepo --> MongoDBServer + + %% Logging Dependencies + RetinaFace -.-> Logger + SFaceRec -.-> Logger + FaceService -.-> Logger + + %% Configuration Dependencies + FaceService -.-> Config + MongoDB -.-> Config + ChromaDB -.-> Config + + %% Styling + classDef presentation fill:#e1f5fe + classDef application fill:#f3e5f5 + classDef domain fill:#e8f5e8 + classDef infrastructure fill:#fff3e0 + classDef external fill:#ffebee + + class GradioUI,GradioApp presentation + class RegisterUC,VerifyUC,IdentifyUC,FaceService application + class Face,User,VResult,IResult,FaceRepo,VectorStore domain + class RetinaFace,SFaceRec,MongoDB,ChromaDB,FileSystem,Config,Logger,UserRepo infrastructure + class MongoDBServer,ChromaDBServer,FileStorage,ONNXModel external +``` + +## Architecture Overview + +### Layers Description + +1. **Presentation Layer**: Gradio-based web interface for user interaction +2. **Application Layer**: Use cases and business logic orchestration +3. **Domain Layer**: Core business entities and repository interfaces +4. **Infrastructure Layer**: Technical implementations and external service adapters + +### Key Components + +- **Face Detection**: RetinaFace for accurate face detection and landmark extraction +- **Face Recognition**: SFace ONNX model for embedding extraction and similarity calculation +- **Storage**: MongoDB for metadata, ChromaDB for vector similarity search, filesystem for images +- **Web Interface**: Gradio provides registration, verification, and identification capabilities + +### Data Flow + +1. User uploads images through Gradio interface +2. Use cases orchestrate the business logic +3. FaceRecognitionService processes images using ML models +4. Data is persisted in MongoDB, ChromaDB, and filesystem +5. Results are returned to the user through the web interface \ No newline at end of file diff --git a/sequence-diagrams.md b/sequence-diagrams.md new file mode 100644 index 0000000..460dba4 --- /dev/null +++ b/sequence-diagrams.md @@ -0,0 +1,288 @@ +# Face Recognition Service - Sequence Diagrams + +## 1. Face Registration Flow + +```mermaid +sequenceDiagram + participant User + participant GradioUI as Gradio Interface + participant RegisterUC as RegisterFaceUseCase + participant UserRepo as MongoDBUserRepository + participant FaceService as FaceRecognitionService + participant Detector as RetinaFaceDetector + participant Recognizer as SFaceRecognizer + participant FaceRepo as MongoDBFaceRepository + participant VectorStore as ChromaDBVectorStore + participant FileStorage as FileSystemStorage + participant MongoDB as MongoDB Database + participant ChromaDB as ChromaDB Vector DB + + User->>GradioUI: Upload images + username + GradioUI->>RegisterUC: execute(username, images) + + RegisterUC->>UserRepo: get_user_by_name(username) + UserRepo->>MongoDB: Query user by name + MongoDB-->>UserRepo: User data or null + UserRepo-->>RegisterUC: User entity or null + + alt User doesn't exist + RegisterUC->>UserRepo: save(new_user) + UserRepo->>MongoDB: Insert new user + MongoDB-->>UserRepo: User ID + UserRepo-->>RegisterUC: User ID + end + + loop For each image + RegisterUC->>FaceService: register_face(user_id, image) + + FaceService->>Detector: detect_faces(image) + Detector-->>FaceService: List of detected faces + + alt No faces detected + FaceService-->>RegisterUC: null + else Face detected + FaceService->>Detector: calculate_quality_score(best_face) + Detector-->>FaceService: Quality score + + alt Quality too low + FaceService-->>RegisterUC: null + else Quality acceptable + FaceService->>Detector: align_face(image, landmarks) + Detector-->>FaceService: Aligned face image + + FaceService->>Recognizer: extract_embedding(aligned_face) + Recognizer-->>FaceService: Face embedding + + FaceService->>FileStorage: save_image(aligned_face, user_id) + FileStorage-->>FaceService: Image path + + FaceService->>FaceRepo: save(face_entity) + FaceRepo->>MongoDB: Insert face record + MongoDB-->>FaceRepo: Success + FaceRepo-->>FaceService: Success + + FaceService->>VectorStore: add(face_id, embedding, metadata) + VectorStore->>ChromaDB: Store embedding vector + ChromaDB-->>VectorStore: Success + VectorStore-->>FaceService: Success + + FaceService-->>RegisterUC: Face ID + end + end + end + + RegisterUC->>FaceService: update_user_mean_embedding(user_id) + FaceService->>FaceRepo: get_by_user_id(user_id) + FaceRepo->>MongoDB: Query faces by user_id + MongoDB-->>FaceRepo: Face records + FaceRepo-->>FaceService: Face entities + FaceService-->>RegisterUC: Mean embedding + + RegisterUC->>UserRepo: update_user(user) + UserRepo->>MongoDB: Update user record + MongoDB-->>UserRepo: Success + UserRepo-->>RegisterUC: Success + + RegisterUC-->>GradioUI: Success message + GradioUI-->>User: Registration result +``` + +## 2. Face Verification Flow + +```mermaid +sequenceDiagram + participant User + participant GradioUI as Gradio Interface + participant VerifyUC as VerifyFaceUseCase + participant UserRepo as MongoDBUserRepository + participant FaceService as FaceRecognitionService + participant Detector as RetinaFaceDetector + participant Recognizer as SFaceRecognizer + participant FaceRepo as MongoDBFaceRepository + participant MongoDB as MongoDB Database + + User->>GradioUI: Upload image + username + GradioUI->>VerifyUC: execute(username, image) + + VerifyUC->>UserRepo: get_user_by_name(username) + UserRepo->>MongoDB: Query user by name + MongoDB-->>UserRepo: User data or null + UserRepo-->>VerifyUC: User entity or null + + alt User not found + VerifyUC-->>GradioUI: VerificationResult(false, 0.0) + else User found + VerifyUC->>FaceService: verify_face(user_id, image) + + FaceService->>Detector: detect_faces(image) + Detector-->>FaceService: List of detected faces + + alt No faces detected + FaceService-->>VerifyUC: (false, 0.0) + else Face detected + FaceService->>Detector: align_face(image, landmarks) + Detector-->>FaceService: Aligned face image + + FaceService->>Recognizer: extract_embedding(aligned_face) + Recognizer-->>FaceService: Query embedding + + FaceService->>FaceRepo: get_by_user_id(user_id) + FaceRepo->>MongoDB: Query registered faces + MongoDB-->>FaceRepo: Face records + FaceRepo-->>FaceService: User's face entities + + alt No registered faces + FaceService-->>VerifyUC: (false, 0.0) + else Compare with registered faces + loop For each registered face + FaceService->>Recognizer: calculate_similarity(query_embedding, face_embedding) + Recognizer-->>FaceService: Similarity score + end + + FaceService-->>VerifyUC: (is_verified, max_similarity) + end + end + + VerifyUC-->>GradioUI: VerificationResult + end + + GradioUI-->>User: Verification result +``` + +## 3. Face Identification Flow + +```mermaid +sequenceDiagram + participant User + participant GradioUI as Gradio Interface + participant IdentifyUC as IdentifyFaceUseCase + participant UserRepo as MongoDBUserRepository + participant FaceService as FaceRecognitionService + participant Detector as RetinaFaceDetector + participant Recognizer as SFaceRecognizer + participant VectorStore as ChromaDBVectorStore + participant ChromaDB as ChromaDB Vector DB + participant MongoDB as MongoDB Database + + User->>GradioUI: Upload image + GradioUI->>IdentifyUC: execute(image) + + IdentifyUC->>FaceService: identify_face(image) + + FaceService->>Detector: detect_faces(image) + Detector-->>FaceService: List of detected faces + + alt No faces detected + FaceService-->>IdentifyUC: (null, 0.0, []) + else Face detected + FaceService->>Detector: align_face(image, landmarks) + Detector-->>FaceService: Aligned face image + + FaceService->>Recognizer: extract_embedding(aligned_face) + Recognizer-->>FaceService: Query embedding + + FaceService->>VectorStore: search_similar(query_embedding, top_k=10) + VectorStore->>ChromaDB: Vector similarity search + ChromaDB-->>VectorStore: Similar face vectors + VectorStore-->>FaceService: Similar faces with metadata + + alt No similar faces above threshold + FaceService-->>IdentifyUC: (null, 0.0, []) + else Similar faces found + note over FaceService: Group by user_id and calculate best scores + FaceService-->>IdentifyUC: (best_user_id, confidence, candidates) + end + end + + loop For each candidate user_id + IdentifyUC->>UserRepo: get_by_id(user_id) + UserRepo->>MongoDB: Query user by ID + MongoDB-->>UserRepo: User data + UserRepo-->>IdentifyUC: User entity + end + + alt User identified + IdentifyUC->>UserRepo: get_by_id(best_user_id) + UserRepo->>MongoDB: Query identified user + MongoDB-->>UserRepo: User data + UserRepo-->>IdentifyUC: User entity + end + + IdentifyUC-->>GradioUI: IdentificationResult + GradioUI-->>User: Identification result +``` + +## 4. System Initialization Flow + +```mermaid +sequenceDiagram + participant Main as main.py + participant Config as Settings + participant MongoDB as MongoDBFaceRepository + participant ChromaDB as ChromaDBVectorStore + participant FileStorage as FileSystemStorage + participant Detector as RetinaFaceDetector + participant Recognizer as SFaceRecognizer + participant FaceService as FaceRecognitionService + participant UseCases as Use Cases + participant GradioApp as Gradio Interface + + Main->>Config: Load configuration + Config-->>Main: Settings object + + Main->>MongoDB: Initialize with MongoDB URL + MongoDB-->>Main: Repository instance + + Main->>ChromaDB: Initialize with Chroma host/port + ChromaDB-->>Main: Vector store instance + + Main->>FileStorage: Initialize with upload directory + FileStorage-->>Main: File storage instance + + Main->>Detector: Initialize RetinaFace + note over Detector: Load ONNX models, prepare ctx + Detector-->>Main: Detector instance + + Main->>Recognizer: Initialize SFace + note over Recognizer: Download/load SFace ONNX model + Recognizer-->>Main: Recognizer instance + + Main->>FaceService: Initialize with dependencies + FaceService-->>Main: Service instance + + Main->>UseCases: Initialize use cases with service + UseCases-->>Main: Use case instances + + Main->>GradioApp: create_gradio_interface(use_cases) + GradioApp-->>Main: Gradio app instance + + Main->>GradioApp: launch(server_name, server_port) + note over GradioApp: Start web server on port 7860 + GradioApp-->>Main: Server running +``` + +## Flow Descriptions + +### Registration Flow +1. User uploads multiple images with username +2. System checks if user exists, creates if needed +3. For each image: detects faces, validates quality, extracts embeddings +4. Stores face metadata in MongoDB, embeddings in ChromaDB, images in filesystem +5. Updates user with mean embedding for faster verification + +### Verification Flow (1:1) +1. User provides image and username to verify against +2. System detects face in query image and extracts embedding +3. Retrieves all registered faces for the specified user +4. Compares query embedding with user's registered face embeddings +5. Returns verification result based on similarity threshold + +### Identification Flow (1:N) +1. User provides image without specifying identity +2. System detects face and extracts embedding +3. Performs vector similarity search across all registered faces +4. Groups results by user and calculates confidence scores +5. Returns best match if confidence exceeds threshold + +### Initialization Flow +System startup involves initializing all dependencies in correct order, loading ML models, and starting the web interface. \ No newline at end of file diff --git a/src/presentation/gradio_app.py b/src/presentation/gradio_app.py index f177b76..bd2ca2c 100644 --- a/src/presentation/gradio_app.py +++ b/src/presentation/gradio_app.py @@ -291,7 +291,6 @@ def create_gradio_interface( label="Live Webcam Feed", sources=["webcam"], type="numpy", - streaming=True, elem_classes=["webcam-container"] )