face-verify / app.py
kadabengaran's picture
Update app.py
b328fc8 verified
import os
import json
import base64
import logging
from fastapi import FastAPI, HTTPException, Request
from fastapi.responses import HTMLResponse, JSONResponse
from fastapi.exceptions import RequestValidationError
from pydantic import BaseModel
import gradio as gr
from deepface import DeepFace
from gradio.routes import App as GradioApp
from uuid import uuid4
# Constants
UPLOAD_DIR = "uploads"
DEFAULT_MODEL = "Facenet"
DEFAULT_DIST = "cosine"
DEFAULT_DETECTOR = "ssd"
# Ensure uploads directory exists
os.makedirs(UPLOAD_DIR, exist_ok=True)
# Environment Configurations
os.environ["KMP_DUPLICATE_LIB_OK"] = "TRUE"
# Logging Setup
logging.basicConfig(level=logging.INFO, format="%(asctime)s - %(levelname)s - %(message)s")
logger = logging.getLogger(__name__)
# FastAPI instance
app = FastAPI()
# Request model
class ImageRequest(BaseModel):
img1_base64: str
img2_base64: str
dist: str = DEFAULT_DIST
model: str = DEFAULT_MODEL
detector: str = DEFAULT_DETECTOR
# Exception Handlers
@app.exception_handler(HTTPException)
async def http_exception_handler(request: Request, exc: HTTPException):
logger.error(f"HTTP error occurred: {exc.detail}")
return JSONResponse(status_code=exc.status_code, content={"detail": exc.detail})
@app.exception_handler(RequestValidationError)
async def validation_exception_handler(request: Request, exc: RequestValidationError):
body = await request.body()
try:
body_data = json.loads(body.decode("utf-8"))
# Log errors with truncated base64 fields
for key in ["img1_base64", "img2_base64"]:
if key in body_data:
body_data[key] = f"{body_data[key][:20]}... [truncated]"
logger.error(f"Validation error: {exc.errors()}")
logger.error(f"Request body: {json.dumps(body_data)}")
except Exception as e:
logger.warning(f"Error decoding request body: {e}")
return JSONResponse(status_code=400, content={"detail": exc.errors()})
# Utility Functions
def save_base64_image(base64_string: str, file_name: str) -> str:
"""
Decodes a base64 string and saves it to a file.
Returns the file path.
"""
file_path = os.path.join(UPLOAD_DIR, file_name)
with open(file_path, "wb") as f:
f.write(base64.b64decode(base64_string))
return file_path
def cleanup_files(*file_paths):
"""Deletes files from the file system."""
for path in file_paths:
if os.path.exists(path):
os.remove(path)
# Face Verification Endpoint
@app.post("/face_verification")
async def face_verification(request: ImageRequest):
try:
img1_path = save_base64_image(request.img1_base64, f"{uuid4()}_img1.png")
img2_path = save_base64_image(request.img2_base64, f"{uuid4()}_img2.png")
result = DeepFace.verify(
img1_path=img1_path,
img2_path=img2_path,
distance_metric=request.dist,
model_name=request.model,
detector_backend=request.detector,
enforce_detection=False,
)
cleanup_files(img1_path, img2_path)
return {
"verified": result["verified"],
"distance": result["distance"],
"threshold": result["threshold"],
"model": result["model"],
"detector_backend": result["detector_backend"],
"similarity_metric": result["similarity_metric"],
}
except Exception as e:
logger.error(f"An error occurred during face verification: {str(e)}")
raise HTTPException(status_code=500, detail="Internal server error during face verification.")
# Gradio Interface
def face_verification_ui(img1, img2, dist=DEFAULT_DIST, model=DEFAULT_MODEL, detector=DEFAULT_DETECTOR):
try:
result = DeepFace.verify(
img1_path=img1,
img2_path=img2,
distance_metric=dist,
model_name=model,
detector_backend=detector,
enforce_detection=False,
)
return {
"Verified": result["verified"],
"Distance": result["distance"],
"Threshold": result["threshold"],
"Model": result["model"],
"Detector Backend": result["detector_backend"],
"Similarity Metric": result["similarity_metric"],
}
except Exception as e:
return {"Error": str(e)}
# Gradio Blocks
with gr.Blocks() as demo:
with gr.Row():
img1 = gr.Image(label="Image 1", sources=["upload", "webcam", "clipboard"])
img2 = gr.Image(label="Image 2", sources=["upload", "webcam", "clipboard"])
with gr.Row():
dist = gr.Dropdown(choices=["cosine", "euclidean", "euclidean_l2"], label="Distance Metric", value=DEFAULT_DIST)
model = gr.Dropdown(choices=["VGG-Face", "Facenet", "Facenet512", "ArcFace"], label="Model", value=DEFAULT_MODEL)
detector = gr.Dropdown(choices=["opencv", "ssd", "mtcnn", "retinaface", "mediapipe"], label="Detector", value=DEFAULT_DETECTOR)
with gr.Row():
btn = gr.Button("Verify")
output = gr.Textbox(label="Output")
btn.click(face_verification_ui, inputs=[img1, img2, dist, model, detector], outputs=output)
# Running Server
if __name__ == "__main__":
import uvicorn
uvicorn.run(app, host="0.0.0.0", port=7860, reload=True)