JARVIS / app.py
hudaakram's picture
Update app.py
319af51 verified
# FastAPI face verification API (CPU)
import io, json, numpy as np, os
from typing import Optional
from fastapi import FastAPI, UploadFile, File, Form
from fastapi.middleware.cors import CORSMiddleware
from fastapi.responses import JSONResponse
from PIL import Image
import insightface
from insightface.app import FaceAnalysis
# --- Load artifacts ---
LABELS = json.load(open("models/labels.json"))
GALLERY = np.load("models/gallery_mean.npy").astype("float32")
THRESH = json.load(open("models/threshold.json")).get("cosine_threshold", 0.35)
# --- Embedder (CPU) ---
FA = FaceAnalysis(name="buffalo_l", providers=["CPUExecutionProvider"])
FA.prepare(ctx_id=-1, det_size=(640,640))
def embed_pil(img: Image.Image) -> Optional[np.ndarray]:
arr = np.array(img.convert("RGB"))
faces = FA.get(arr)
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") # already L2-normalized
def cosine_sim(a: np.ndarray, B: np.ndarray) -> np.ndarray:
return (B @ a) / (np.linalg.norm(a)*np.linalg.norm(B,axis=1) + 1e-12)
app = FastAPI(title="FaceVerify API")
app.add_middleware(CORSMiddleware, allow_origins=["*"], allow_methods=["*"], allow_headers=["*"])
@app.post("/verify")
async def verify(name: str = Form(...), image: UploadFile = File(...)):
try:
img = Image.open(io.BytesIO(await image.read())).convert("RGB")
except Exception as e:
return JSONResponse({"status":"error","reason":f"bad_image:{e}"}, 400)
emb = embed_pil(img)
if emb is None:
return JSONResponse({"status":"denied","reason":"no_face_detected"}, 200)
sims = cosine_sim(emb, GALLERY) # higher is better
i = int(np.argmax(sims))
score = float(sims[i])
matched = LABELS[i] if 0 <= i < len(LABELS) else None
ok = score >= THRESH
return JSONResponse({
"status": "accepted" if ok else "denied",
"score": score, "threshold": THRESH,
"claimed_name": name, "matched_name": matched
})