ATTEND_B / face_recognition_system.py
17skb's picture
handling permission denied Error-[comment] Silly me :(
f53a95a
# 2:
import cv2
import numpy as np
import insightface
from insightface.app import FaceAnalysis
from insightface.utils import download_onnx
from pathlib import Path
from typing import Dict, List, Tuple
import pickle
import logging
import os
class FaceRecognitionSystem:
def __init__(self,
model_name: str = "buffalo_l",
model_root: str = "./models"):
# Set up logging
logging.basicConfig(level=logging.INFO)
self.logger = logging.getLogger(__name__)
# Create model directory if it doesn't exist
self.model_root = Path(model_root)
self.model_root.mkdir(parents=True, exist_ok=True)
# Set InsightFace model root
# insightface.utils.set_download_root(str(self.model_root))
# insightface.utils.download(root='./models_x', sub_dir='downloads', name='file')
# Initialize the face analysis model
try:
self.face_analyzer = FaceAnalysis(
name=model_name,
root=str(self.model_root),
download=True # Allow downloading if model doesn't exist
)
self.face_analyzer.prepare(ctx_id=-1, det_size=(640, 640)) # Using CPU
self.logger.info(f"Face analyzer initialized successfully in {self.model_root}")
except Exception as e:
self.logger.error(f"Error initializing face analyzer: {e}")
raise
# Dictionary to store known face embeddings
self.known_face_embeddings: Dict[str, np.ndarray] = {}
def process_known_faces(self, people_folder_path: str) -> None:
"""Process and store embeddings of known faces from a folder."""
embeddings_file = self.model_root / "known_faces_embeddings.pkl"
try:
# Load existing embeddings if available
if embeddings_file.exists():
with open(embeddings_file, 'rb') as f:
self.known_face_embeddings = pickle.load(f)
self.logger.info("Loaded existing face embeddings")
return
self.logger.info("Processing known faces...")
people_path = Path(people_folder_path)
if not people_path.exists():
self.logger.warning(f"Directory not found: {people_folder_path}")
return
for person_path in people_path.glob("*"):
if person_path.is_dir():
person_name = person_path.name
embeddings_list = []
for img_path in person_path.glob("*"):
if img_path.suffix.lower() in ['.jpg', '.jpeg', '.png']:
img = cv2.imread(str(img_path))
if img is None:
self.logger.warning(f"Could not read image: {img_path}")
continue
faces = self.face_analyzer.get(img)
if faces:
embeddings_list.append(faces[0].embedding)
else:
self.logger.warning(f"No face detected in {img_path}")
if embeddings_list:
self.known_face_embeddings[person_name] = np.mean(embeddings_list, axis=0)
self.logger.info(f"Processed {person_name}'s faces")
else:
self.logger.warning(f"No valid faces found for {person_name}")
# Save embeddings in model directory
with open(embeddings_file, 'wb') as f:
pickle.dump(self.known_face_embeddings, f)
self.logger.info(f"Face embeddings saved to {embeddings_file}")
except Exception as e:
self.logger.error(f"Error processing known faces: {e}")
raise
def identify_face(self, face_embedding: np.ndarray, threshold: float = 0.6) -> Tuple[str, float]:
"""Identify a face by comparing its embedding with known faces."""
try:
best_match = "Unknown"
best_score = float('inf')
for person_name, known_embedding in self.known_face_embeddings.items():
similarity = np.dot(face_embedding, known_embedding) / (
np.linalg.norm(face_embedding) * np.linalg.norm(known_embedding)
)
distance = 1 - similarity
if distance < best_score:
best_score = distance
best_match = person_name
return (best_match, best_score) if best_score < threshold else ("Unknown", best_score)
except Exception as e:
self.logger.error(f"Error in face identification: {e}")
return ("Error", 1.0)
def detect_and_identify(self, image_input) -> np.ndarray:
"""Detect and identify faces in an input image."""
try:
# Handle both string paths and numpy arrays
if isinstance(image_input, str):
img = cv2.imread(image_input)
else:
img = image_input
if img is None:
raise ValueError("Could not read input image")
faces = self.face_analyzer.get(img)
for face in faces:
bbox = face.bbox.astype(int)
embedding = face.embedding
name, score = self.identify_face(embedding)
cv2.rectangle(img, (bbox[0], bbox[1]), (bbox[2], bbox[3]), (0, 255, 0), 2)
label = f"{name} ({1-score:.2f})"
cv2.putText(img, label.upper(), (bbox[0], bbox[1]-10),
cv2.FONT_HERSHEY_PLAIN, 2.0, (0, 255, 0), 2)
return img
except Exception as e:
self.logger.error(f"Error in detection and identification: {e}")
raise
# 1:
# import cv2
# import numpy as np
# import insightface
# from insightface.app import FaceAnalysis
# from pathlib import Path
# from typing import Dict, List, Tuple
# import pickle
# import logging
# class FaceRecognitionSystem:
# def __init__(self, model_name: str = "buffalo_l"):
# # Set up logging
# logging.basicConfig(level=logging.INFO)
# self.logger = logging.getLogger(__name__)
# # Initialize the face analysis model
# try:
# self.face_analyzer = FaceAnalysis(name=model_name)
# self.face_analyzer.prepare(ctx_id=-1, det_size=(640, 640)) # Using CPU
# self.logger.info("Face analyzer initialized successfully")
# except Exception as e:
# self.logger.error(f"Error initializing face analyzer: {e}")
# raise
# # Dictionary to store known face embeddings
# self.known_face_embeddings: Dict[str, np.ndarray] = {}
# def process_known_faces(self, people_folder_path: str) -> None:
# """Process and store embeddings of known faces from a folder."""
# embeddings_file = Path("known_faces_embeddings.pkl")
# try:
# # Load existing embeddings if available
# if embeddings_file.exists():
# with open(embeddings_file, 'rb') as f:
# self.known_face_embeddings = pickle.load(f)
# self.logger.info("Loaded existing face embeddings")
# return
# self.logger.info("Processing known faces...")
# people_path = Path(people_folder_path)
# if not people_path.exists():
# self.logger.warning(f"Directory not found: {people_folder_path}")
# return
# for person_path in people_path.glob("*"):
# if person_path.is_dir():
# person_name = person_path.name
# embeddings_list = []
# for img_path in person_path.glob("*"):
# if img_path.suffix.lower() in ['.jpg', '.jpeg', '.png']:
# img = cv2.imread(str(img_path))
# if img is None:
# self.logger.warning(f"Could not read image: {img_path}")
# continue
# faces = self.face_analyzer.get(img)
# if faces:
# embeddings_list.append(faces[0].embedding)
# else:
# self.logger.warning(f"No face detected in {img_path}")
# if embeddings_list:
# self.known_face_embeddings[person_name] = np.mean(embeddings_list, axis=0)
# self.logger.info(f"Processed {person_name}'s faces")
# else:
# self.logger.warning(f"No valid faces found for {person_name}")
# # Save embeddings
# with open(embeddings_file, 'wb') as f:
# pickle.dump(self.known_face_embeddings, f)
# self.logger.info("Face processing complete")
# except Exception as e:
# self.logger.error(f"Error processing known faces: {e}")
# raise
# def identify_face(self, face_embedding: np.ndarray, threshold: float = 0.6) -> Tuple[str, float]:
# """Identify a face by comparing its embedding with known faces."""
# try:
# best_match = "Unknown"
# best_score = float('inf')
# for person_name, known_embedding in self.known_face_embeddings.items():
# similarity = np.dot(face_embedding, known_embedding) / (
# np.linalg.norm(face_embedding) * np.linalg.norm(known_embedding)
# )
# distance = 1 - similarity
# if distance < best_score:
# best_score = distance
# best_match = person_name
# return (best_match, best_score) if best_score < threshold else ("Unknown", best_score)
# except Exception as e:
# self.logger.error(f"Error in face identification: {e}")
# return ("Error", 1.0)
# def detect_and_identify(self, image_input) -> np.ndarray:
# """Detect and identify faces in an input image."""
# try:
# # Handle both string paths and numpy arrays
# if isinstance(image_input, str):
# img = cv2.imread(image_input)
# else:
# img = image_input
# if img is None:
# raise ValueError("Could not read input image")
# faces = self.face_analyzer.get(img)
# for face in faces:
# bbox = face.bbox.astype(int)
# embedding = face.embedding
# name, score = self.identify_face(embedding)
# cv2.rectangle(img, (bbox[0], bbox[1]), (bbox[2], bbox[3]), (0, 255, 0), 2)
# label = f"{name} ({1-score:.2f})"
# cv2.putText(img, label.upper(), (bbox[0], bbox[1]-10),
# cv2.FONT_HERSHEY_PLAIN, 2.0, (0, 255, 0), 2)
# return img
# except Exception as e:
# self.logger.error(f"Error in detection and identification: {e}")
# raise
# OLD:
# import cv2
# import numpy as np
# import insightface
# from insightface.app import FaceAnalysis
# from insightface.data import get_image as ins_get_image
# import os
# from pathlib import Path
# from typing import Dict, List, Tuple
# import pickle
# class FaceRecognitionSystem:
# def __init__(self, model_name: str = "buffalo_l"):
# # Initialize the face analysis model
# self.face_analyzer = FaceAnalysis(name=model_name)
# self.face_analyzer.prepare(ctx_id=0, det_size=(640, 640))
# # Dictionary to store known face embeddings
# self.known_face_embeddings: Dict[str, np.ndarray] = {}
# def process_known_faces(self, people_folder_path: str) -> None:
# """Process and store embeddings of known faces from a folder."""
# # Create embeddings file path
# # embeddings_file = Path("known_face_embeddings copy2.pkl")
# embeddings_file = Path("data/model/known_faces_embeddings.pkl")
# # Load existing embeddings if available
# if embeddings_file.exists():
# with open(embeddings_file, 'rb') as f:
# self.known_face_embeddings = pickle.load(f)
# print("Loaded existing face embeddings.")
# return
# print("Processing known faces...")
# for person_path in Path(people_folder_path).glob("*"):
# if person_path.is_dir():
# person_name = person_path.name
# embeddings_list = []
# # Process each image in person's folder
# for img_path in person_path.glob("*"):
# if img_path.suffix.lower() in ['.jpg', '.jpeg', '.png']:
# img = cv2.imread(str(img_path))
# if img is None:
# continue
# # Get face embedding
# faces = self.face_analyzer.get(img)
# if faces:
# embeddings_list.append(faces[0].embedding)
# if embeddings_list:
# # Average all embeddings for this person
# self.known_face_embeddings[person_name] = np.mean(embeddings_list, axis=0)
# print(f"Processed {person_name}'s faces")
# # Save embeddings for future use
# with open(embeddings_file, 'wb') as f:
# pickle.dump(self.known_face_embeddings, f)
# print("Face processing complete.")
# # OLD:
# def identify_face(self, face_embedding: np.ndarray, threshold: float = 0.6) -> Tuple[str, float]:
# """Identify a face by comparing its embedding with known faces."""
# best_match = "Unknown"
# best_score = float('inf')
# for person_name, known_embedding in self.known_face_embeddings.items():
# # Calculate cosine similarity
# similarity = np.dot(face_embedding, known_embedding) / (
# np.linalg.norm(face_embedding) * np.linalg.norm(known_embedding)
# )
# distance = 1 - similarity
# if distance < best_score:
# best_score = distance
# best_match = person_name
# return (best_match, best_score) if best_score < threshold else ("Unknown", best_score)
# def detect_and_identify(self, image_input, output_path: str = None) -> np.ndarray:
# """Detect and identify faces in an input image."""
# # Handle both string paths and numpy arrays
# if isinstance(image_input, str):
# img = cv2.imread(image_input)
# else:
# img = image_input
# if img is None:
# raise ValueError("Could not read input image")
# # Rest of the code remains the same
# faces = self.face_analyzer.get(img)
# for face in faces:
# bbox = face.bbox.astype(int)
# embedding = face.embedding
# name, score = self.identify_face(embedding)
# cv2.rectangle(img, (bbox[0], bbox[1]), (bbox[2], bbox[3]), (0, 255, 0), 2)
# label = f"{name} ({1-score:.2f})"
# cv2.putText(img, label.upper(), (bbox[0], bbox[1]-10),
# cv2.FONT_HERSHEY_PLAIN, 4.2, (0, 255, 0), 2)
# # cv2.FONT_HERSHEY_SIMPLEX, 0.6, (0, 255, 0), 2)
# if output_path:
# cv2.imwrite(output_path, img)
# return img
# # def detect_and_identify(self, image_path: str, output_path: str = None) -> np.ndarray:
# # """Detect and identify faces in an input image."""
# # # Read input image
# # img = cv2.imread(image_path)
# # if img is None:
# # raise ValueError("Could not read input image")
# # # Detect faces
# # faces = self.face_analyzer.get(img)
# # # Draw results on image
# # for face in faces:
# # bbox = face.bbox.astype(int)
# # embedding = face.embedding
# # name, score = self.identify_face(embedding)
# # # Draw rectangle around face
# # cv2.rectangle(img, (bbox[0], bbox[1]), (bbox[2], bbox[3]), (0, 255, 0), 2)
# # # Add name and confidence score
# # label = f"{name} ({1-score:.2f})"
# # cv2.putText(img, label, (bbox[0], bbox[1]-10),
# # cv2.FONT_HERSHEY_PLAIN, 1.5, (0, 255, 0), 2)
# # # Save output image if path provided
# # if output_path:
# # cv2.imwrite(output_path, img)
# # return img