Attender / face_recognition_module_PRODUCTION.py
chualinwei3's picture
Upload 30 files
f742815 verified
Raw
History Blame Contribute Delete
7.22 kB
"""
Production Face Recognition Module for Attendr
This is the REAL implementation using the face_recognition library
Use this file after installing dlib and face_recognition
To activate:
1. Install dlib and face_recognition
2. Rename face_recognition_module.py to face_recognition_module_MOCK.py
3. Rename this file to face_recognition_module.py
4. Restart the Flask application
"""
import face_recognition
import numpy as np
from config import Config
import logging
# Set up logging
logging.basicConfig(level=logging.INFO)
logger = logging.getLogger(__name__)
class FaceRecognitionModule:
"""Handles all face recognition operations using production library"""
def __init__(self, tolerance=None, model='hog'):
"""
Initialize face recognition module
Args:
tolerance: Face matching tolerance (lower = more strict)
model: Detection model ('hog' or 'cnn')
"""
self.tolerance = tolerance or Config.FACE_RECOGNITION_TOLERANCE
self.model = model or Config.FACE_DETECTION_MODEL
logger.info(f"PRODUCTION Face Recognition Module initialized with tolerance={self.tolerance}, model={self.model}")
def detect_faces(self, image_array):
"""
Detect faces in an image
Args:
image_array: numpy array of the image
Returns:
List of face locations [(top, right, bottom, left), ...]
"""
try:
face_locations = face_recognition.face_locations(image_array, model=self.model)
logger.info(f"Detected {len(face_locations)} face(s) in image")
return face_locations
except Exception as e:
logger.error(f"Face detection error: {str(e)}")
return []
def generate_face_encoding(self, image_array):
"""
Generate face encoding from an image
Implements: CapturedFace(x) - captures and encodes the face
Args:
image_array: numpy array of the image
Returns:
tuple: (success, encoding or error_message)
"""
try:
# Detect faces first
face_locations = self.detect_faces(image_array)
if len(face_locations) == 0:
return False, "No face detected in the image. Please ensure your face is clearly visible."
if len(face_locations) > 1:
return False, "Multiple faces detected. Please ensure only one person is in the frame."
# Generate encoding
encodings = face_recognition.face_encodings(image_array, face_locations)
if len(encodings) == 0:
return False, "Failed to generate face encoding. Please try again with better lighting."
encoding = encodings[0]
logger.info("Face encoding generated successfully")
return True, encoding
except Exception as e:
logger.error(f"Face encoding error: {str(e)}")
return False, f"Face encoding failed: {str(e)}"
def verify_face(self, captured_encoding, stored_encoding):
"""
Verify if captured face matches stored encoding
Implements: MatchStored(x) → FaceMatch(x)
Args:
captured_encoding: Face encoding from live capture
stored_encoding: Stored face encoding from database
Returns:
tuple: (is_match: bool, confidence: float)
"""
try:
if captured_encoding is None or stored_encoding is None:
logger.warning("One or both encodings are None")
return False, 0.0
# Convert to numpy arrays if needed
if not isinstance(captured_encoding, np.ndarray):
captured_encoding = np.array(captured_encoding)
if not isinstance(stored_encoding, np.ndarray):
stored_encoding = np.array(stored_encoding)
# Calculate face distance (lower = more similar)
face_distance = face_recognition.face_distance([stored_encoding], captured_encoding)[0]
# Convert distance to confidence percentage
confidence = (1 - face_distance) * 100
# Check if match is within tolerance
is_match = face_distance <= self.tolerance
logger.info(f"Face verification: match={is_match}, confidence={confidence:.2f}%, distance={face_distance:.4f}")
return is_match, confidence
except Exception as e:
logger.error(f"Face verification error: {str(e)}")
return False, 0.0
def register_face(self, image_array):
"""
Complete face registration process
Args:
image_array: numpy array of the image
Returns:
tuple: (success, encoding or error_message, face_location)
"""
try:
# Detect faces
face_locations = self.detect_faces(image_array)
if len(face_locations) == 0:
return False, "No face detected. Please ensure your face is clearly visible and well-lit.", None
if len(face_locations) > 1:
return False, "Multiple faces detected. Please ensure only one person is in the frame.", None
# Generate encoding
success, result = self.generate_face_encoding(image_array)
if success:
return True, result, face_locations[0]
else:
return False, result, None
except Exception as e:
logger.error(f"Face registration error: {str(e)}")
return False, f"Registration failed: {str(e)}", None
def compare_faces_batch(self, known_encodings, face_encoding_to_check):
"""
Compare a face encoding against multiple known encodings
Useful for identifying which student from a list
Args:
known_encodings: List of known face encodings
face_encoding_to_check: Face encoding to compare
Returns:
List of boolean matches
"""
try:
if not isinstance(face_encoding_to_check, np.ndarray):
face_encoding_to_check = np.array(face_encoding_to_check)
matches = face_recognition.compare_faces(
known_encodings,
face_encoding_to_check,
tolerance=self.tolerance
)
return matches
except Exception as e:
logger.error(f"Batch face comparison error: {str(e)}")
return []
# Singleton instance
face_recognition_module = FaceRecognitionModule()