Midnightar commited on
Commit
78cdb93
·
verified ·
1 Parent(s): 36865dc

Create app.py

Browse files
Files changed (1) hide show
  1. app.py +105 -0
app.py ADDED
@@ -0,0 +1,105 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # app.py
2
+ import base64
3
+ import cv2
4
+ import numpy as np
5
+ import requests
6
+ from fastapi import FastAPI
7
+ from pydantic import BaseModel
8
+ import insightface
9
+ import logging
10
+
11
+ # ---------------------------
12
+ # Reduce InsightFace logging
13
+ # ---------------------------
14
+ logging.getLogger("insightface").setLevel(logging.ERROR)
15
+
16
+ # ---------------------------
17
+ # Load face detector + recognition model
18
+ # ---------------------------
19
+ model = insightface.app.FaceAnalysis(name="buffalo_l")
20
+ model.prepare(ctx_id=-1, det_size=(640, 640)) # CPU only, avoid CUDA warnings
21
+
22
+ # ---------------------------
23
+ # FastAPI app
24
+ # ---------------------------
25
+ app = FastAPI(title="Face Compare API")
26
+
27
+ # ---------------------------
28
+ # Request schema
29
+ # ---------------------------
30
+ class CompareRequest(BaseModel):
31
+ image1: str # base64 string OR URL
32
+ image2: str # base64 string OR URL
33
+
34
+ # ---------------------------
35
+ # Helper: Load image from base64 or URL
36
+ # ---------------------------
37
+ def load_image(input_str):
38
+ if input_str.startswith("http://") or input_str.startswith("https://"):
39
+ try:
40
+ resp = requests.get(input_str, timeout=5)
41
+ if resp.status_code != 200:
42
+ return None
43
+ arr = np.frombuffer(resp.content, np.uint8)
44
+ img = cv2.imdecode(arr, cv2.IMREAD_COLOR)
45
+ return img
46
+ except:
47
+ return None
48
+ else:
49
+ try:
50
+ if "," in input_str:
51
+ b64 = input_str.split(",", 1)[1]
52
+ else:
53
+ b64 = input_str
54
+ data = base64.b64decode(b64)
55
+ arr = np.frombuffer(data, np.uint8)
56
+ img = cv2.imdecode(arr, cv2.IMREAD_COLOR)
57
+ return img
58
+ except:
59
+ return None
60
+
61
+ # ---------------------------
62
+ # Helper: Get face embedding
63
+ # ---------------------------
64
+ def get_embedding(img):
65
+ try:
66
+ faces = model.get(img)
67
+ if len(faces) == 0:
68
+ return None
69
+ return faces[0].embedding
70
+ except:
71
+ return None
72
+
73
+ # ---------------------------
74
+ # Helper: Cosine similarity
75
+ # ---------------------------
76
+ def cosine_similarity(a, b):
77
+ a = np.array(a)
78
+ b = np.array(b)
79
+ denom = np.linalg.norm(a) * np.linalg.norm(b)
80
+ if denom == 0:
81
+ return 0.0
82
+ return float(np.dot(a, b) / denom)
83
+
84
+ # ---------------------------
85
+ # API endpoint
86
+ # ---------------------------
87
+ @app.post("/compare")
88
+ async def compare_faces(req: CompareRequest):
89
+ img1 = load_image(req.image1)
90
+ img2 = load_image(req.image2)
91
+
92
+ if img1 is None or img2 is None:
93
+ return {"error": "Cannot load one or both images"}
94
+
95
+ emb1 = get_embedding(img1)
96
+ emb2 = get_embedding(img2)
97
+
98
+ if emb1 is None or emb2 is None:
99
+ return {"error": "No face detected in one or both images"}
100
+
101
+ similarity = cosine_similarity(emb1, emb2)
102
+ threshold = 0.55 # adjust threshold for stricter or looser matching
103
+ match = similarity >= threshold
104
+
105
+ return {"similarity": similarity, "match": match}