Spaces:
Sleeping
Sleeping
| 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 | |
| def name()->str: | |
| return "deepface" | |
| 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" | |