Spaces:
Running
Running
| """ | |
| Identity verification plugin using InsightFace (face recognition) for MorphGuard. | |
| """ | |
| import os | |
| import numpy as np | |
| from insightface.app import FaceAnalysis | |
| from PIL import Image | |
| from abc import ABC, abstractmethod | |
| class IdentityConnector(ABC): | |
| """Abstract interface for external identity verification connectors.""" | |
| def enroll(self, user_id: str, image_path: str) -> bool: | |
| """Enroll a user with given ID using the provided image.""" | |
| pass | |
| def verify(self, user_id: str, image_path: str) -> tuple: | |
| """Verify the provided image against enrolled identity; return (id, score).""" | |
| pass | |
| class IdentityVerifier: | |
| """Enroll and verify identities against a face gallery.""" | |
| def __init__(self, provider: str = 'insightface'): | |
| # Initialize InsightFace app for detection & recognition | |
| self.app = FaceAnalysis(allowed_modules=['detection', 'recognition']) | |
| self.app.prepare(ctx_id=0, det_size=(224, 224)) | |
| # Gallery: id -> embedding | |
| self.gallery = {} | |
| def enroll(self, identity: str, image_path: str) -> bool: | |
| """Add a face to the gallery under given identity.""" | |
| img = Image.open(image_path).convert('RGB') | |
| arr = np.array(img) | |
| faces = self.app.get(arr) | |
| if not faces: | |
| raise ValueError('No face detected during enrollment') | |
| emb = faces[0].embedding | |
| self.gallery[identity] = emb | |
| return True | |
| def verify(self, image_path: str) -> tuple: | |
| """Verify a face image against the enrolled gallery. | |
| Returns (best_identity, best_score) via cosine similarity. | |
| """ | |
| img = Image.open(image_path).convert('RGB') | |
| arr = np.array(img) | |
| faces = self.app.get(arr) | |
| if not faces: | |
| raise ValueError('No face detected during verification') | |
| emb = faces[0].embedding | |
| best_id, best_score = None, -1.0 | |
| for identity, g_emb in self.gallery.items(): | |
| # Cosine similarity | |
| sim = float(np.dot(emb, g_emb) / (np.linalg.norm(emb) * np.linalg.norm(g_emb))) | |
| if sim > best_score: | |
| best_score, best_id = sim, identity | |
| return best_id, best_score |