hudaakram commited on
Commit
fa2fb5f
·
verified ·
1 Parent(s): 830251f

Create app.py

Browse files
Files changed (1) hide show
  1. app.py +74 -0
app.py ADDED
@@ -0,0 +1,74 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # FastAPI Space: username + image -> decision, score, threshold, jwt
2
+ import os, io, json, time
3
+ import numpy as np
4
+ from fastapi import FastAPI, UploadFile, File, Form
5
+ from fastapi.middleware.cors import CORSMiddleware
6
+ from PIL import Image
7
+ import jwt
8
+
9
+ # ---- config ----
10
+ MODELS_DIR = os.environ.get('MODELS_DIR', 'models') # put gallery/labels/threshold here
11
+ JWT_SECRET = os.environ.get('PORTAL_SECRET', 'change-me') # set a real secret in Space settings
12
+ JWT_EXP_SECS = int(os.environ.get('JWT_EXP_SECS', '600')) # 10 min
13
+
14
+ # ---- load artifacts ----
15
+ import json as _json
16
+ labels = _json.load(open(f"{MODELS_DIR}/labels.json","r",encoding="utf-8"))
17
+ gallery = np.load(f"{MODELS_DIR}/gallery_mean.npy")
18
+ thr = _json.load(open(f"{MODELS_DIR}/threshold.json","r"))["cosine_threshold"]
19
+
20
+ # ---- embedder ----
21
+ class FaceEmbedder:
22
+ def __init__(self, provider='CPUExecutionProvider'):
23
+ import insightface
24
+ from insightface.app import FaceAnalysis
25
+ self.fa = FaceAnalysis(name='buffalo_l', providers=[provider])
26
+ self.fa.prepare(ctx_id=-1, det_size=(640,640))
27
+ def __call__(self, img_rgb: np.ndarray):
28
+ faces = self.fa.get(img_rgb)
29
+ if not faces: return None
30
+ f = max(faces, key=lambda z: (z.bbox[2]-z.bbox[0])*(z.bbox[3]-z.bbox[1]))
31
+ return f.normed_embedding.astype('float32')
32
+
33
+ EMB = FaceEmbedder()
34
+
35
+ # ---- api ----
36
+ app = FastAPI(title="Access Gate")
37
+ app.add_middleware(
38
+ CORSMiddleware,
39
+ allow_origins=["*"], allow_credentials=True,
40
+ allow_methods=["*"], allow_headers=["*"]
41
+ )
42
+
43
+ def issue_token(username: str):
44
+ payload = {"sub": username, "iat": int(time.time()), "exp": int(time.time()) + JWT_EXP_SECS}
45
+ return jwt.encode(payload, JWT_SECRET, algorithm="HS256")
46
+
47
+ @app.get("/labels")
48
+ def get_labels():
49
+ return {"labels": labels}
50
+
51
+ @app.post("/verify")
52
+ async def verify(username: str = Form(...), image: UploadFile = File(...)):
53
+ # read image
54
+ arr = np.array(Image.open(io.BytesIO(await image.read())).convert("RGB"))
55
+ # checks
56
+ if username not in labels:
57
+ return {"decision": "Not Found", "score": 0.0, "threshold": thr, "reason": "Unknown user"}
58
+
59
+ emb = EMB(arr)
60
+ if emb is None:
61
+ return {"decision": "Invalid", "score": 0.0, "threshold": thr, "reason": "No face detected"}
62
+
63
+ idx = labels.index(username)
64
+ score = float(emb @ gallery[idx])
65
+ decision = "Allow" if score >= thr else "Deny"
66
+ token = issue_token(username) if decision == "Allow" else ""
67
+
68
+ return {
69
+ "decision": decision,
70
+ "score": score,
71
+ "threshold": thr,
72
+ "reason": "",
73
+ "token": token
74
+ }