Spaces:
Runtime error
Runtime error
| # FastAPI Space: username + image -> decision, score, threshold, jwt | |
| import os, io, json, time | |
| import numpy as np | |
| from fastapi import FastAPI, UploadFile, File, Form | |
| from fastapi.middleware.cors import CORSMiddleware | |
| from PIL import Image | |
| import jwt | |
| # ---- config ---- | |
| MODELS_DIR = os.environ.get('MODELS_DIR', 'models') # put gallery/labels/threshold here | |
| JWT_SECRET = os.environ.get('PORTAL_SECRET', 'change-me') # set a real secret in Space settings | |
| JWT_EXP_SECS = int(os.environ.get('JWT_EXP_SECS', '600')) # 10 min | |
| # ---- load artifacts ---- | |
| import json as _json | |
| labels = _json.load(open(f"{MODELS_DIR}/labels.json","r",encoding="utf-8")) | |
| gallery = np.load(f"{MODELS_DIR}/gallery_mean.npy") | |
| thr = _json.load(open(f"{MODELS_DIR}/threshold.json","r"))["cosine_threshold"] | |
| # ---- embedder ---- | |
| class FaceEmbedder: | |
| def __init__(self, provider='CPUExecutionProvider'): | |
| import insightface | |
| from insightface.app import FaceAnalysis | |
| self.fa = FaceAnalysis(name='buffalo_l', providers=[provider]) | |
| self.fa.prepare(ctx_id=-1, det_size=(640,640)) | |
| def __call__(self, img_rgb: np.ndarray): | |
| faces = self.fa.get(img_rgb) | |
| if not faces: return None | |
| f = max(faces, key=lambda z: (z.bbox[2]-z.bbox[0])*(z.bbox[3]-z.bbox[1])) | |
| return f.normed_embedding.astype('float32') | |
| EMB = FaceEmbedder() | |
| # ---- api ---- | |
| app = FastAPI(title="Access Gate") | |
| app.add_middleware( | |
| CORSMiddleware, | |
| allow_origins=["*"], allow_credentials=True, | |
| allow_methods=["*"], allow_headers=["*"] | |
| ) | |
| def issue_token(username: str): | |
| payload = {"sub": username, "iat": int(time.time()), "exp": int(time.time()) + JWT_EXP_SECS} | |
| return jwt.encode(payload, JWT_SECRET, algorithm="HS256") | |
| def get_labels(): | |
| return {"labels": labels} | |
| async def verify(username: str = Form(...), image: UploadFile = File(...)): | |
| # read image | |
| arr = np.array(Image.open(io.BytesIO(await image.read())).convert("RGB")) | |
| # checks | |
| if username not in labels: | |
| return {"decision": "Not Found", "score": 0.0, "threshold": thr, "reason": "Unknown user"} | |
| emb = EMB(arr) | |
| if emb is None: | |
| return {"decision": "Invalid", "score": 0.0, "threshold": thr, "reason": "No face detected"} | |
| idx = labels.index(username) | |
| score = float(emb @ gallery[idx]) | |
| decision = "Allow" if score >= thr else "Deny" | |
| token = issue_token(username) if decision == "Allow" else "" | |
| return { | |
| "decision": decision, | |
| "score": score, | |
| "threshold": thr, | |
| "reason": "", | |
| "token": token | |
| } | |