Spaces:
Sleeping
Sleeping
File size: 3,787 Bytes
78cdb93 5059f37 78cdb93 b136c7f 057f178 78cdb93 5059f37 78cdb93 b136c7f 78cdb93 18c23ed b136c7f 78cdb93 5059f37 78cdb93 5059f37 5f2c279 5059f37 b136c7f 5f2c279 b136c7f 5059f37 b136c7f 78cdb93 5f2c279 78cdb93 5059f37 b136c7f 5f2c279 b136c7f 5059f37 b136c7f 5059f37 78cdb93 b136c7f 5059f37 5f2c279 5059f37 5f2c279 78cdb93 18c23ed 78cdb93 5059f37 b136c7f 5059f37 b136c7f 18c23ed b136c7f 057f178 193f77c 057f178 5059f37 b136c7f 5059f37 b136c7f aece0c4 b136c7f 193f77c b136c7f 5059f37 78cdb93 5059f37 78cdb93 057f178 | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 | import base64
import cv2
import numpy as np
import requests
from fastapi import FastAPI
from pydantic import BaseModel
import uvicorn
import insightface
import gradio as gr
import threading
# ---------- Load Face Detector + Recognition Model ----------
model = insightface.app.FaceAnalysis(name="buffalo_l")
model.prepare(ctx_id=0, det_size=(640, 640))
# ---------- FastAPI App ----------
app = FastAPI()
# ---------- API Request Schema ----------
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
# ---------- Helper: Convert base64 to CV2 image ----------
def b64_to_img(b64_string):
try:
img_data = base64.b64decode(b64_string)
np_arr = np.frombuffer(img_data, np.uint8)
img = cv2.imdecode(np_arr, cv2.IMREAD_COLOR)
return img
except:
return None
# ---------- Helper: Convert URL to CV2 image ----------
def url_to_img(url):
try:
resp = requests.get(url, timeout=5)
np_arr = np.frombuffer(resp.content, np.uint8)
img = cv2.imdecode(np_arr, cv2.IMREAD_COLOR)
return img
except:
return None
# ---------- Helper: Extract face embedding ----------
def get_embedding(img):
faces = model.get(img)
if len(faces) == 0:
return None
return faces[0].embedding # first detected face
# ---------- POST /compare API ----------
@app.post("/compare")
async def compare_faces(req: CompareRequest):
# ---- Load Image 1 ----
if req.image1:
img1 = b64_to_img(req.image1)
elif req.image1_url:
img1 = url_to_img(req.image1_url)
else:
img1 = None
# ---- Load Image 2 ----
if req.image2:
img2 = b64_to_img(req.image2)
elif req.image2_url:
img2 = url_to_img(req.image2_url)
else:
img2 = 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 = np.dot(emb1, emb2) / (np.linalg.norm(emb1) * np.linalg.norm(emb2))
matched = similarity > 0.55 # threshold
return {
"similarity": float(similarity),
"match": matched
}
# ---------- Gradio UI ----------
def gradio_ui(img1_text, img2_text):
def load_any(input_str):
if input_str.startswith("http://") or input_str.startswith("https://"):
return url_to_img(input_str)
else:
return b64_to_img(input_str)
img1 = load_any(img1_text)
img2 = load_any(img2_text)
if img1 is None or img2 is None:
return "Invalid image data or URL."
emb1 = get_embedding(img1)
emb2 = get_embedding(img2)
if emb1 is None or emb2 is None:
return "Face not detected."
similarity = np.dot(emb1, emb2) / (np.linalg.norm(emb1) * np.linalg.norm(emb2))
matched = similarity > 0.55
return f"Similarity: {similarity:.3f} | Match: {matched}"
# ---------- Run Gradio in Background Thread ----------
def launch_gradio():
gr.Interface(
fn=gradio_ui,
inputs=[
gr.Textbox(label="Image 1 (base64 or URL)"),
gr.Textbox(label="Image 2 (base64 or URL)")
],
outputs="text",
title="Face Match API (Text Input)"
).launch(server_name="0.0.0.0", server_port=7860)
# ---------- MAIN ----------
if __name__ == "__main__":
# Start Gradio in a separate thread
threading.Thread(target=launch_gradio, daemon=True).start()
# Start FastAPI server
uvicorn.run(app, host="0.0.0.0", port=8000) |