# 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 @app.post("/compare") 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}