first commit
This commit is contained in:
commit
a16d736a5a
53
.gitignore
vendored
Normal file
53
.gitignore
vendored
Normal file
@ -0,0 +1,53 @@
|
||||
# Byte-compiled / optimized / DLL files
|
||||
__pycache__/
|
||||
*.py[cod]
|
||||
*$py.class
|
||||
|
||||
# Caches
|
||||
.cache/
|
||||
*.cache
|
||||
|
||||
# Virtual environment
|
||||
env/
|
||||
venv/
|
||||
ENV/
|
||||
.venv/
|
||||
|
||||
# Local environment configurations
|
||||
.env
|
||||
*.env
|
||||
|
||||
# Database files
|
||||
*.db
|
||||
*.sqlite3
|
||||
*.db-journal
|
||||
|
||||
# Images, temporary files, and uploads
|
||||
/tmp/
|
||||
*.png
|
||||
*.jpg
|
||||
*.jpeg
|
||||
*.gif
|
||||
*.bmp
|
||||
|
||||
# Logs
|
||||
*.log
|
||||
logs/
|
||||
|
||||
# Jupyter Notebook checkpoints
|
||||
.ipynb_checkpoints/
|
||||
|
||||
# Compiled C extensions
|
||||
*.so
|
||||
|
||||
# macOS specific files
|
||||
.DS_Store
|
||||
|
||||
# Windows specific files
|
||||
Thumbs.db
|
||||
ehthumbs.db
|
||||
Desktop.ini
|
||||
|
||||
# System files
|
||||
.vscode/
|
||||
.idea/
|
123
app.py
Normal file
123
app.py
Normal file
@ -0,0 +1,123 @@
|
||||
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)}")
|
2
migrations/pacedeep_fastapi.sql
Normal file
2
migrations/pacedeep_fastapi.sql
Normal file
@ -0,0 +1,2 @@
|
||||
DROP TABLE IF EXISTS users;
|
||||
CREATE TABLE users (user_id text, embeddings float_vector KNN_TYPE='hnsw' KNN_DIMS='512' HNSW_SIMILARITY='cosine');
|
74
requirements.txt
Normal file
74
requirements.txt
Normal file
@ -0,0 +1,74 @@
|
||||
absl-py==2.1.0
|
||||
annotated-types==0.7.0
|
||||
anyio==4.6.2.post1
|
||||
astunparse==1.6.3
|
||||
beautifulsoup4==4.12.3
|
||||
blinker==1.8.2
|
||||
certifi==2024.8.30
|
||||
charset-normalizer==3.4.0
|
||||
click==8.1.7
|
||||
deepface==0.0.93
|
||||
exceptiongroup==1.2.2
|
||||
fastapi==0.115.2
|
||||
filelock==3.16.1
|
||||
fire==0.7.0
|
||||
Flask==3.0.3
|
||||
Flask-Cors==5.0.0
|
||||
flatbuffers==24.3.25
|
||||
gast==0.6.0
|
||||
gdown==5.2.0
|
||||
google-pasta==0.2.0
|
||||
grpcio==1.67.0
|
||||
gunicorn==23.0.0
|
||||
h11==0.14.0
|
||||
h5py==3.12.1
|
||||
idna==3.10
|
||||
itsdangerous==2.2.0
|
||||
Jinja2==3.1.4
|
||||
joblib==1.4.2
|
||||
keras==3.6.0
|
||||
libclang==18.1.1
|
||||
lz4==4.3.3
|
||||
manticoresearch==4.0.0
|
||||
Markdown==3.7
|
||||
markdown-it-py==3.0.0
|
||||
MarkupSafe==3.0.2
|
||||
mdurl==0.1.2
|
||||
ml-dtypes==0.4.1
|
||||
mtcnn==1.0.0
|
||||
namex==0.0.8
|
||||
numpy==1.26.4
|
||||
opencv-python==4.10.0.84
|
||||
opt_einsum==3.4.0
|
||||
optree==0.13.0
|
||||
packaging==24.1
|
||||
pandas==2.2.3
|
||||
pillow==11.0.0
|
||||
protobuf==4.25.5
|
||||
pydantic==2.9.2
|
||||
pydantic_core==2.23.4
|
||||
Pygments==2.18.0
|
||||
PySocks==1.7.1
|
||||
python-dateutil==2.9.0.post0
|
||||
python-multipart==0.0.12
|
||||
pytz==2024.2
|
||||
requests==2.32.3
|
||||
retina-face==0.0.17
|
||||
rich==13.9.2
|
||||
six==1.16.0
|
||||
sniffio==1.3.1
|
||||
soupsieve==2.6
|
||||
starlette==0.40.0
|
||||
tensorboard==2.17.1
|
||||
tensorboard-data-server==0.7.2
|
||||
tensorflow==2.17.0
|
||||
tensorflow-io-gcs-filesystem==0.37.1
|
||||
termcolor==2.5.0
|
||||
tf_keras==2.17.0
|
||||
tqdm==4.66.5
|
||||
typing_extensions==4.12.2
|
||||
tzdata==2024.2
|
||||
urllib3==2.2.3
|
||||
uvicorn==0.32.0
|
||||
Werkzeug==3.0.4
|
||||
wrapt==1.16.0
|
Loading…
x
Reference in New Issue
Block a user