Spaces:
Build error
Build error
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() |