| # 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 |