124 lines
4.4 KiB
Python
Raw Normal View History

2024-10-22 17:12:57 -06:00
from fastapi import FastAPI, File, UploadFile, HTTPException, Form
from deepface import DeepFace
from manticoresearch import ApiClient, Configuration
from manticoresearch.api import IndexApi, SearchApi
from manticoresearch.model import SearchRequest
from manticoresearch.model import InsertDocumentRequest
import os
import shutil
from numpy import dot
from numpy.linalg import norm
# Configurar el cliente API
config = Configuration()
config.host = "http://localhost:9308"
client = ApiClient(configuration=config)
# Inicializar las APIs
index_api = IndexApi(client)
search_api = SearchApi(client)
app = FastAPI()
# Función para calcular similitud de coseno
def cosine_similarity(vec1, vec2):
return dot(vec1, vec2) / (norm(vec1) * norm(vec2))
# Ruta para registrar un nuevo usuario
@app.post("/register_user")
async def register_user(user_id: str = Form(...), image: UploadFile = File(...)):
try:
# Guardar la imagen temporalmente
img_path = f"/tmp/{image.filename}"
with open(img_path, "wb") as buffer:
shutil.copyfileobj(image.file, buffer)
# Obtener los embeddings faciales
embedding_result = DeepFace.represent(img_path, model_name="ArcFace")
# Extraer los embeddings
embeddings = embedding_result[0]['embedding'] # Extrae el vector de embeddings
# Verifica si embeddings tiene 512 valores
if len(embeddings) != 512:
raise HTTPException(status_code=400, detail=f"Los embeddings generados no tienen 512 valores: {len(embeddings)}")
# Almacenar los embeddings en Manticore Search
doc = {
"user_id": user_id,
"embeddings": embeddings
}
# Crea la solicitud de inserción de documento
insert_request = InsertDocumentRequest(index="users", doc=doc)
# Inserta el documento en Manticore Search
index_api.insert(insert_document_request=insert_request)
# Eliminar el archivo temporal
os.remove(img_path)
return {"status": "user registered successfully"}
except Exception as e:
raise HTTPException(status_code=500, detail=f"Error registering user: {str(e)}")
# Ruta para verificar una imagen
@app.post("/verify_user")
async def verify_user(image: UploadFile = File(...)):
try:
# Guardar la imagen temporalmente
img_path = f"/tmp/{image.filename}"
with open(img_path, "wb") as buffer:
shutil.copyfileobj(image.file, buffer)
# Obtener los embeddings faciales de la imagen
query_embeddings = DeepFace.represent(img_path, model_name="ArcFace")[0]['embedding']
# Consulta en Manticore Search para obtener los usuarios registrados
query = {
"size": 100, # Ajusta el tamaño si tienes muchos usuarios
"query": {
"match_all": {}
}
}
# Crear la solicitud de búsqueda
search_request = SearchRequest(index="users", query=query)
# Realizar la búsqueda
result = search_api.search(search_request)
# Recuperar todos los documentos (usuarios y sus embeddings)
hits = result.hits.hits
if not hits:
raise HTTPException(status_code=404, detail="No registered users found.")
# Calcular similitud de coseno con cada usuario registrado
max_similarity = -1
matched_user = None
for hit in hits:
stored_embeddings = hit['_source']['embeddings'] # Embeddings del usuario en la base de datos
similarity = cosine_similarity(query_embeddings, stored_embeddings)
# Imprimir la similitud de cada usuario para depuración
print(f"Similitud con {hit['_source']['user_id']}: {similarity}")
# Encontrar la mayor similitud
if similarity > max_similarity:
max_similarity = similarity
matched_user = hit['_source']['user_id']
# Establecer un umbral para decidir si hay coincidencia
similarity_threshold = 0.5 # Ajusta este valor según tus necesidades
if max_similarity < similarity_threshold:
raise HTTPException(status_code=404, detail="No matching user found")
# Eliminar el archivo temporal
os.remove(img_path)
return {"status": "success", "matched_user": matched_user, "similarity": max_similarity}
except Exception as e:
raise HTTPException(status_code=500, detail=f"Error verifying user: {str(e)}")