facereco / app.py
vikramjeetthakur's picture
Update app.py
7735e32 verified
raw
history blame
6.81 kB
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()