Spaces:
Sleeping
Sleeping
File size: 2,267 Bytes
6b39516 | 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 | from fastapi import FastAPI, UploadFile, File, HTTPException
from fastapi.staticfiles import StaticFiles
from qdrant_client import QdrantClient
import face_recognition
import numpy as np
import io
import os
app = FastAPI(title="Face Search Engine API")
# CONFIGURATION
COLLECTION_NAME = "faces"
IMAGE_FOLDER = "stored_images"
# Initialize Qdrant (Must point to the same path as ingestion)
qdrant = QdrantClient(path="qdrant_db")
# Mount the image folder so the frontend can access images via URL
# e.g., http://localhost:8000/static/my_photo.jpg
os.makedirs(IMAGE_FOLDER, exist_ok=True)
app.mount("/static", StaticFiles(directory=IMAGE_FOLDER), name="static")
@app.post("/search")
async def search_faces(file: UploadFile = File(...)):
# 1. Read and Encode Input Image
image_bytes = await file.read()
image = face_recognition.load_image_file(io.BytesIO(image_bytes))
input_encodings = face_recognition.face_encodings(image)
if len(input_encodings) == 0:
return {"message": "No faces detected in input image.", "matches": []}
# Use the first face found
target_encoding = input_encodings[0]
# 2. Search in Qdrant
# Qdrant handles the vector math efficiently
search_result = qdrant.query_points(
collection_name=COLLECTION_NAME,
query =target_encoding.tolist(),
with_payload=True,
limit=5, # Return top 5 matches
score_threshold=0.6 # Equivalent to (1 - 0.4 distance). Adjust based on results.
).points
print(search_result)
# 3. Format Results
matches = []
seen_files = set()
for hit in search_result:
if not hit.payload:
continue
filename = hit.payload.get("filename")
# Deduplicate (if multiple faces from same image match)
if filename not in seen_files:
# Construct the URL pointing to this API's static mount
# In production, replace 'localhost:8000' with your domain
image_url = f"http://localhost:8000/static/{filename}"
matches.append(image_url)
seen_files.add(filename)
return {
"total_matches": len(matches),
"matches": matches
} |