| """
|
| Mock Face Recognition Module for Testing (Windows-friendly)
|
| This is a simplified version that doesn't require dlib/face_recognition
|
| For production, install the full face_recognition library
|
| """
|
|
|
| import numpy as np
|
| import cv2
|
| from config import Config
|
| import logging
|
| import hashlib
|
|
|
|
|
| logging.basicConfig(level=logging.INFO)
|
| logger = logging.getLogger(__name__)
|
|
|
| logger.warning("Using MOCK face recognition module - for testing only!")
|
| logger.warning("Install face_recognition library for production use")
|
|
|
|
|
| class FaceRecognitionModule:
|
| """Mock face recognition for testing without dlib dependencies"""
|
|
|
| def __init__(self, tolerance=None, model='hog'):
|
| self.tolerance = tolerance or Config.FACE_RECOGNITION_TOLERANCE
|
| self.model = model
|
| logger.info(f"Mock Face Recognition Module initialized")
|
|
|
| def detect_faces(self, image_array):
|
| """Mock face detection using OpenCV Haar Cascades"""
|
| try:
|
|
|
| gray = cv2.cvtColor(image_array, cv2.COLOR_RGB2GRAY)
|
|
|
|
|
| face_cascade = cv2.CascadeClassifier(cv2.data.haarcascades + 'haarcascade_frontalface_default.xml')
|
|
|
|
|
| faces = face_cascade.detectMultiScale(gray, 1.3, 5)
|
|
|
|
|
| face_locations = [(y, x+w, y+h, x) for (x, y, w, h) in faces]
|
|
|
| logger.info(f"Detected {len(face_locations)} face(s)")
|
| return face_locations
|
| except Exception as e:
|
| logger.error(f"Face detection error: {str(e)}")
|
| return []
|
|
|
| def generate_face_encoding(self, image_array):
|
| """
|
| Mock encoding generation using image hash
|
| In production, this would use deep learning-based face encodings
|
| """
|
| try:
|
| 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."
|
|
|
|
|
|
|
| top, right, bottom, left = face_locations[0]
|
| face_region = image_array[top:bottom, left:right]
|
|
|
|
|
| face_resized = cv2.resize(face_region, (100, 100))
|
|
|
|
|
| face_bytes = face_resized.tobytes()
|
| hash_obj = hashlib.sha256(face_bytes)
|
| hash_digest = hash_obj.digest()
|
|
|
|
|
|
|
| encoding = np.array([float(b) for b in hash_digest[:128]] + [0.0] * (128 - len(hash_digest[:128])))
|
|
|
| logger.info("Mock face encoding generated")
|
| 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):
|
| """
|
| Mock face verification using encoding similarity
|
| In production, this would use Euclidean distance between face encodings
|
| """
|
| try:
|
| if captured_encoding is None or stored_encoding is None:
|
| return False, 0.0
|
|
|
|
|
| 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)
|
|
|
|
|
|
|
| correlation = np.corrcoef(captured_encoding, stored_encoding)[0, 1]
|
|
|
|
|
| distance = 1 - abs(correlation)
|
|
|
|
|
| confidence = (1 - distance) * 100
|
|
|
|
|
| is_match = distance <= self.tolerance
|
|
|
| logger.info(f"Mock verification: match={is_match}, confidence={confidence:.2f}%")
|
|
|
| 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"""
|
| try:
|
| 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
|
|
|
| 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 against multiple encodings"""
|
| try:
|
| matches = []
|
| for known_encoding in known_encodings:
|
| is_match, _ = self.verify_face(face_encoding_to_check, known_encoding)
|
| matches.append(is_match)
|
| return matches
|
| except Exception as e:
|
| logger.error(f"Batch comparison error: {str(e)}")
|
| return []
|
|
|
|
|
|
|
| face_recognition_module = FaceRecognitionModule()
|
|
|