import streamlit as st from PIL import Image import numpy as np import cv2 import face_recognition import os from typing import List, Tuple import requests from urllib.parse import quote import logging # Set up logging logging.basicConfig(level=logging.INFO) logger = logging.getLogger(__name__) class FaceRecognitionApp: def __init__(self, image_directory: str = "facerecognition"): """Initialize the face recognition application.""" self.image_directory = image_directory self.images: List[np.ndarray] = [] self.classnames: List[str] = [] self.encode_list_known = None # Initialize Streamlit page st.set_page_config(page_title="Face Recognition System", page_icon="👤") st.title("Face Recognition System") # Load and encode known faces self._load_known_faces() def _load_known_faces(self) -> None: """Load and encode all known faces from the directory and predefined images.""" try: # Load predefined images predefined_images = { "sarwan.jpg": "Sarwan", "rattantata.png": "RattanTata", "Ravinder.jpg": "RavinderKaur" } for img_path, name in predefined_images.items(): if os.path.exists(img_path): img = cv2.imread(img_path) if img is not None: self.images.append(img) self.classnames.append(name) else: logger.warning(f"Failed to load image: {img_path}") # Load images from directory if os.path.exists(self.image_directory): for filename in os.listdir(self.image_directory): if filename.lower().endswith(('.jpg', '.jpeg', '.png')): img_path = os.path.join(self.image_directory, filename) img = cv2.imread(img_path) if img is not None: self.images.append(img) self.classnames.append(os.path.splitext(filename)[0]) else: logger.warning(f"Failed to load image: {img_path}") # Encode faces if self.images: self.encode_list_known = [] for img in self.images: rgb_img = cv2.cvtColor(img, cv2.COLOR_BGR2RGB) encodings = face_recognition.face_encodings(rgb_img) if encodings: self.encode_list_known.append(encodings[0]) else: logger.warning("No face detected in one of the reference images") logger.info(f"Loaded {len(self.images)} images for face recognition") except Exception as e: logger.error(f"Error loading known faces: {str(e)}") st.error("Error loading reference images. Please check the image files.") def _process_face(self, image: np.ndarray, scale: float = 0.25) -> Tuple[np.ndarray, bool]: """Process image and detect faces.""" img_small = cv2.resize(image, (0, 0), None, scale, scale) img_rgb = cv2.cvtColor(img_small, cv2.COLOR_BGR2RGB) face_locations = face_recognition.face_locations(img_rgb) face_encodings = face_recognition.face_encodings(img_rgb, face_locations) face_matched = False for encoding, (top, right, bottom, left) in zip(face_encodings, face_locations): if self.encode_list_known: matches = face_recognition.compare_faces(self.encode_list_known, encoding) face_distances = face_recognition.face_distance(self.encode_list_known, encoding) if any(matches): best_match_idx = np.argmin(face_distances) if matches[best_match_idx]: name = self.classnames[best_match_idx].upper() face_matched = True # Scale back the coordinates top, right, bottom, left = [coord * int(1/scale) for coord in (top, right, bottom, left)] # Draw rectangle and name cv2.rectangle(image, (left, top), (right, bottom), (0, 255, 0), 2) cv2.rectangle(image, (left, bottom - 35), (right, bottom), (0, 255, 0), cv2.FILLED) cv2.putText(image, name, (left + 6, bottom - 6), cv2.FONT_HERSHEY_COMPLEX, 1, (255, 255, 255), 2) # Update external service self._update_external_service(name) return image, face_matched def _update_external_service(self, name: str) -> None: """Update external service with recognition results.""" try: base_url = "https://fc11.glitch.me/submit" params = { "email": "pm", "message": "faceReco", "name": quote(name) } response = requests.get(base_url, params=params, timeout=5) response.raise_for_status() st.success(f"Successfully updated recognition for {name}") logger.info(f"External service updated for {name}") except requests.exceptions.RequestException as e: logger.error(f"Failed to update external service: {str(e)}") st.warning("Failed to update external service, but recognition completed successfully") def run(self) -> None: """Run the face recognition application.""" if not self.encode_list_known: st.error("No reference faces loaded. Please check the image directory.") return img_file_buffer = st.camera_input("Take Your Picture") if img_file_buffer is not None: try: image = np.array(Image.open(img_file_buffer)) processed_image, face_matched = self._process_face(image.copy()) st.image(processed_image, use_column_width=True, channels="BGR") if not face_matched: st.warning("No matching faces found in the image.") except Exception as e: logger.error(f"Error processing image: {str(e)}") st.error("Error processing the image. Please try again.") if __name__ == "__main__": app = FaceRecognitionApp() app.run()