PhotoRemovable / app.py
ksumhs's picture
Update app.py
ea3e859 verified
from fastapi import FastAPI, File, UploadFile
from fastapi.responses import Response, JSONResponse
from insightface.app import FaceAnalysis
from rembg import remove
from PIL import Image
import numpy as np
import io
app = FastAPI()
# Simple homepage (fixes 404 on HF Spaces)
@app.get("/")
def home():
return {"message": "ID Photo API is running. Use POST /process"}
# Load face detection model
face_app = FaceAnalysis(name="buffalo_l", providers=["CPUExecutionProvider"])
face_app.prepare(ctx_id=0, det_size=(640, 640))
def resize_to_4x6(img):
return img.resize((472, 709), Image.LANCZOS)
@app.post("/process")
async def process_img(file: UploadFile = File(...)):
try:
img_bytes = await file.read()
img = Image.open(io.BytesIO(img_bytes)).convert("RGB")
np_img = np.array(img)
faces = face_app.get(np_img)
if not faces:
return JSONResponse({"error": "No face detected"}, status_code=400)
face = faces[0]
# --- Extract face bounding box ---
x1, y1, x2, y2 = face.bbox.astype(int)
cropped = img.crop((x1, y1, x2, y2))
# --- Resize cropped face with preserved aspect ratio ---
max_face_height = int(709 * 0.75) # face occupies 75% of final height
w, h = cropped.size
scale_factor = max_face_height / h
new_w = int(w * scale_factor)
new_h = int(h * scale_factor)
resized_face = cropped.resize((new_w, new_h), Image.LANCZOS)
# --- Create final white 4x6 canvas ---
final_w, final_h = 472, 709
canvas = Image.new("RGB", (final_w, final_h), (255, 255, 255))
# --- Center image on canvas ---
paste_x = (final_w - new_w) // 2
paste_y = (final_h - new_h) // 2
canvas.paste(resized_face, (paste_x, paste_y))
# --- Output final image ---
buf = io.BytesIO()
canvas.save(buf, format="JPEG")
buf.seek(0)
return Response(buf.getvalue(), media_type="image/jpeg")
except Exception as e:
print("ERROR:", e)
return JSONResponse({"error": str(e)}, status_code=500)