File size: 7,208 Bytes
9040d50 668c77a 9040d50 668c77a 9040d50 668c77a 9040d50 668c77a 9040d50 668c77a 9040d50 668c77a 9040d50 668c77a 9040d50 668c77a 9040d50 668c77a 9040d50 668c77a 9040d50 668c77a 9040d50 668c77a 9040d50 668c77a 9040d50 668c77a 9040d50 668c77a 9040d50 668c77a 9040d50 668c77a 9040d50 668c77a 9040d50 668c77a | 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 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 | import sys
import os
import io
import traceback
from pathlib import Path
from typing import Any
import numpy as np
import cv2
from PIL import Image
from fastapi import FastAPI, Request, File, UploadFile, HTTPException
from fastapi.staticfiles import StaticFiles
from fastapi.templating import Jinja2Templates
from fastapi.middleware.cors import CORSMiddleware
# Add parent path so imports work (kept from your code)
sys.path.append(str(Path(__file__).resolve().parent.parent))
from app.config import settings
from app import __version__
from app.Hackathon_setup import face_recognition, exp_recognition
# -----------------------------------------------------------------------------
# App setup
# -----------------------------------------------------------------------------
app = FastAPI(
title=settings.PROJECT_NAME,
openapi_url=f"{settings.API_V1_STR}/openapi.json",
)
# Static and templates
STATIC_DIR = "app/static"
os.makedirs(STATIC_DIR, exist_ok=True)
app.mount("/static", StaticFiles(directory=STATIC_DIR), name="static")
templates = Jinja2Templates(directory="app/templates")
# -----------------------------------------------------------------------------
# Helpers
# -----------------------------------------------------------------------------
async def save_and_load_rgb(upload: UploadFile):
"""
Read upload ONCE -> save to app/static -> return (relative_name_for_html, rgb_np)
rgb_np: HxWx3 uint8 RGB numpy array
"""
if upload is None:
raise ValueError("No file uploaded")
if not upload.content_type or "image" not in upload.content_type:
raise ValueError(f"Invalid content_type: {upload.content_type}")
data = await upload.read()
if not data:
raise ValueError("Uploaded file is empty")
# Safe filename (avoid path traversal)
filename = os.path.basename(upload.filename) if upload.filename else "uploaded.png"
save_path = os.path.join(STATIC_DIR, filename)
# Save bytes for template display
with open(save_path, "wb") as f:
f.write(data)
# Decode image in memory for inference (ALWAYS convert to RGB)
pil_img = Image.open(io.BytesIO(data)).convert("RGB")
rgb_np = np.asarray(pil_img, dtype=np.uint8) # HxWx3 RGB
# Return the relative path expected by templates
rel_for_html = "../static/" + filename
return rel_for_html, rgb_np
def to_bgr(rgb_np: np.ndarray) -> np.ndarray:
"""Optional: convert RGB numpy to BGR for OpenCV-based pipelines."""
return cv2.cvtColor(rgb_np, cv2.COLOR_RGB2BGR)
# -----------------------------------------------------------------------------
# Home
# -----------------------------------------------------------------------------
@app.get("/")
async def root(request: Request):
return templates.TemplateResponse("index.html", {"request": request})
# -----------------------------------------------------------------------------
# Face Similarity
# -----------------------------------------------------------------------------
@app.get("/similarity/")
async def similarity_root(request: Request):
return templates.TemplateResponse("similarity.html", {"request": request})
@app.post("/predict_similarity/")
async def predict_similarity(request: Request, file1: UploadFile = File(...), file2: UploadFile = File(...)):
try:
simi_path1, img1_rgb = await save_and_load_rgb(file1)
simi_path2, img2_rgb = await save_and_load_rgb(file2)
# If your downstream expects BGR, uncomment these lines:
# img1 = to_bgr(img1_rgb)
# img2 = to_bgr(img2_rgb)
# If your face_recognition module handles RGB->BGR internally, keep as-is:
img1 = img1_rgb
img2 = img2_rgb
result = face_recognition.get_similarity(img1, img2)
return templates.TemplateResponse(
"predict_similarity.html",
{
"request": request,
"result": float(np.round(result, 3)),
"simi_filename1": simi_path1,
"simi_filename2": simi_path2,
},
)
except Exception as e:
print("ERROR in /predict_similarity/:", repr(e))
traceback.print_exc()
raise HTTPException(status_code=500, detail=str(e))
# -----------------------------------------------------------------------------
# Face Recognition
# -----------------------------------------------------------------------------
@app.get("/face_recognition/")
async def face_recognition_root(request: Request):
return templates.TemplateResponse("face_recognition.html", {"request": request})
@app.post("/predict_face_recognition/")
async def predict_face_recognition(request: Request, file3: UploadFile = File(...)):
try:
face_path, img_rgb = await save_and_load_rgb(file3)
# Optional BGR conversion if needed:
# img = to_bgr(img_rgb)
img = img_rgb
result = face_recognition.get_face_class(img)
return templates.TemplateResponse(
"predict_face_recognition.html",
{
"request": request,
"result": result,
"face_rec_filename": face_path,
},
)
except Exception as e:
print("ERROR in /predict_face_recognition/:", repr(e))
traceback.print_exc()
raise HTTPException(status_code=500, detail=str(e))
# -----------------------------------------------------------------------------
# Expression Recognition
# -----------------------------------------------------------------------------
@app.get("/expr_recognition/")
async def expr_recognition_root(request: Request):
return templates.TemplateResponse("expr_recognition.html", {"request": request})
@app.post("/predict_expr_recognition/")
async def predict_expr_recognition(request: Request, file4: UploadFile = File(...)):
try:
expr_path, img_rgb = await save_and_load_rgb(file4)
# Optional BGR conversion if needed:
# img = to_bgr(img_rgb)
img = img_rgb
result = exp_recognition.get_expression(img)
return templates.TemplateResponse(
"predict_expr_recognition.html",
{
"request": request,
"result": result,
"expr_rec_filename": expr_path,
},
)
except Exception as e:
print("ERROR in /predict_expr_recognition/:", repr(e))
traceback.print_exc()
raise HTTPException(status_code=500, detail=str(e))
# -----------------------------------------------------------------------------
# CORS
# -----------------------------------------------------------------------------
if settings.BACKEND_CORS_ORIGINS:
app.add_middleware(
CORSMiddleware,
allow_origins=[str(origin) for origin in settings.BACKEND_CORS_ORIGINS],
allow_credentials=True,
allow_methods=["*"],
allow_headers=["*"],
)
# -----------------------------------------------------------------------------
# Run locally
# -----------------------------------------------------------------------------
if __name__ == "__main__":
import uvicorn
uvicorn.run(app, host="0.0.0.0", port=8001) |