face-recognition-app / src /database.py
rahim-xelpmoc's picture
Update src/database.py
f4525ae verified
from typing import Any, Dict, List
import chromadb
import os
from deepface import DeepFace
from uuid import uuid4
from chromadb.utils.distance_functions import cosine
from chromadb.api.types import EmbeddingFunction,Documents,Embeddings
from config import EMBEDDING_MODEL,DETECTOR_BACKEND
class DeepFaceEmebeddingFunction(EmbeddingFunction[Documents]):
def __init__(self,model_name:str="VGG-Face",detector_backend:str="opencv",enforce_detection=False):
"""model_name (str): Model for face recognition. Options: VGG-Face, Facenet, Facenet512,
OpenFace, DeepFace, DeepID, Dlib, ArcFace, SFace and GhostFaceNet (default is VGG-Face).
detector_backend (string): face detector backend. Options: 'opencv', 'retinaface',
'mtcnn', 'ssd', 'dlib', 'mediapipe', 'yolov8', 'yolov11n', 'yolov11s', 'yolov11m',
'centerface' or 'skip' (default is opencv).
enforce_detection (boolean): If no face is detected in an image, raise an exception.
Set to False to avoid the exception for low-resolution images (default is True)."""
self.model_name=model_name
self.detector_backend=detector_backend
self.enforce_detection=enforce_detection
def get_embedding_with_metadata(self,input:Documents)->List[Dict[str,Any]]:
"""get un normalized embedding with metadata"""
embs=DeepFace.represent(img_path=input,
model_name=self.model_name,
detector_backend=self.detector_backend,
enforce_detection=self.enforce_detection)
for emb in embs:
emb['embedding']=DeepFace.verification.l2_normalize(emb['embedding'])
return embs
def __call__(self,input:Documents)->Embeddings:
embs=self.get_embedding_with_metadata(input=input)
embeddings=[]
for emb in embs:
embeddings.append(emb['embedding'])
return embeddings
@staticmethod
def name()->str:
return "deepface"
@staticmethod
def build_from_config(config: Dict[str, Any]) -> "EmbeddingFunction[Documents]":
model_name=config.get("model_name","VGG-Face")
detector_backend=config.get("detector_backend","opencv")
enforce_detection=config.get("enforce_detection",False)
return DeepFaceEmebeddingFunction(model_name=model_name,detector_backend=detector_backend,enforce_detection=enforce_detection)
def get_config(self) -> Dict[str, Any]:
config={"model_name":self.model_name,
"detector_backend":self.detector_backend,
"enforce_detection":self.enforce_detection}
return config
class Database:
def __init__(self, db_path: str):
self.client = chromadb.CloudClient(
api_key=os.getenv("api_key"),
tenant=os.getenv("tenant"),
database=os.getenv("database")
)
self.embedding_func=DeepFaceEmebeddingFunction(model_name=EMBEDDING_MODEL, detector_backend=DETECTOR_BACKEND)
self.collection = self.client.get_or_create_collection(
name="face-database",
embedding_function=self.embedding_func,
metadata={"hnsw:space": "cosine"}
)
def add_to_collection(self,img_path:str,metadata):
try:
embs=self.embedding_func.get_embedding_with_metadata(input=[img_path])
self.collection.add(
ids=str(uuid4()),
embeddings=embs[0]['embedding'],
metadatas={**metadata,
"facial_area":str(embs[0]['facial_area']),
"face_confidence":embs[0]['face_confidence']}
)
except Exception as e:
print(e)
def verify(self,img_path:str)->Dict[str,Any]:
input_emb=self.embedding_func([img_path])
threshold=DeepFace.verification.find_threshold(model_name=EMBEDDING_MODEL,distance_metric='cosine')
result=self.collection.query(query_embeddings=input_emb,include=['embeddings',"metadatas"],n_results=1)
metadata=result['metadatas'][0][0]
distance=cosine(result['embeddings'][0],input_emb[0])
result={'verified': distance<=threshold,
'distance': distance,
'threshold': threshold,
'confidence': DeepFace.verification.find_confidence(distance,EMBEDDING_MODEL,"cosine",distance<=threshold),
'model': EMBEDDING_MODEL,
'detector_backend': DETECTOR_BACKEND,
'similarity_metric': 'cosine',
'facial_areas': {**metadata},
"id":result['ids'][0][0]}
return result
def delete_record(self,id):
self.collection.delete(id)
return f"{id} deleted successfully"