Spaces:
Sleeping
Sleeping
| # app.py | |
| import base64 | |
| import cv2 | |
| import numpy as np | |
| import requests | |
| from fastapi import FastAPI | |
| from pydantic import BaseModel | |
| import insightface | |
| # Load Face Detector + Recognition Model (first import may download weights) | |
| model = insightface.app.FaceAnalysis(name="buffalo_l") | |
| model.prepare(ctx_id=0, det_size=(640, 640)) | |
| app = FastAPI(title="Face Compare API") | |
| class CompareRequest(BaseModel): | |
| image1: str | None = None # base64 | |
| image2: str | None = None # base64 | |
| image1_url: str | None = None # URL | |
| image2_url: str | None = None # URL | |
| def b64_to_img(b64_string: str): | |
| try: | |
| img_data = base64.b64decode(b64_string) | |
| arr = np.frombuffer(img_data, np.uint8) | |
| img = cv2.imdecode(arr, cv2.IMREAD_COLOR) | |
| return img | |
| except Exception: | |
| return None | |
| def url_to_img(url: str): | |
| try: | |
| resp = requests.get(url, timeout=10) | |
| arr = np.frombuffer(resp.content, np.uint8) | |
| img = cv2.imdecode(arr, cv2.IMREAD_COLOR) | |
| return img | |
| except Exception: | |
| return None | |
| def get_embedding(img): | |
| faces = model.get(img) | |
| if len(faces) == 0: | |
| return None | |
| return faces[0].embedding | |
| async def compare_faces(req: CompareRequest): | |
| # Load images (prefer raw base64, else url) | |
| img1 = b64_to_img(req.image1) if req.image1 else (url_to_img(req.image1_url) if req.image1_url else None) | |
| img2 = b64_to_img(req.image2) if req.image2 else (url_to_img(req.image2_url) if req.image2_url else None) | |
| if img1 is None or img2 is None: | |
| return {"error": "Invalid image data or URL."} | |
| emb1 = get_embedding(img1) | |
| emb2 = get_embedding(img2) | |
| if emb1 is None or emb2 is None: | |
| return {"error": "No face detected in one or both images."} | |
| # cosine similarity | |
| similarity = float(np.dot(emb1, emb2) / (np.linalg.norm(emb1) * np.linalg.norm(emb2))) | |
| matched = similarity > 0.55 | |
| return {"similarity": similarity, "match": matched} |