|
|
import os |
|
|
import face_recognition as fr |
|
|
import pickle |
|
|
import shutil |
|
|
|
|
|
|
|
|
DATA_DIR = "/data" |
|
|
KNOWN_USER_DIR = os.path.join(DATA_DIR, "known_users") |
|
|
UNKNOWN_USER_DIR = os.path.join(DATA_DIR, "unknown_users") |
|
|
ENCODINGS_DIR = os.path.join(DATA_DIR, "encodings") |
|
|
|
|
|
|
|
|
os.makedirs(KNOWN_USER_DIR, exist_ok=True) |
|
|
os.makedirs(UNKNOWN_USER_DIR, exist_ok=True) |
|
|
os.makedirs(ENCODINGS_DIR, exist_ok=True) |
|
|
|
|
|
|
|
|
def save_image_from_path(image_path, student_id): |
|
|
"""Save student image from file path and compute face encoding""" |
|
|
try: |
|
|
if not image_path or not os.path.exists(image_path): |
|
|
return False, "No image provided" |
|
|
|
|
|
|
|
|
dest_path = os.path.join(KNOWN_USER_DIR, f"{student_id}.jpg") |
|
|
|
|
|
|
|
|
shutil.copy2(image_path, dest_path) |
|
|
|
|
|
|
|
|
image = fr.load_image_file(dest_path) |
|
|
face_encodings = fr.face_encodings(image) |
|
|
|
|
|
if len(face_encodings) > 0: |
|
|
encoding = face_encodings[0] |
|
|
encoding_path = os.path.join(ENCODINGS_DIR, f"{student_id}.pkl") |
|
|
|
|
|
with open(encoding_path, "wb") as f: |
|
|
pickle.dump(encoding, f) |
|
|
|
|
|
return True, "Image and face encoding saved successfully!" |
|
|
else: |
|
|
|
|
|
if os.path.exists(dest_path): |
|
|
os.remove(dest_path) |
|
|
return False, "No face detected in the image. Please upload a clear face photo." |
|
|
|
|
|
except Exception as e: |
|
|
return False, f"Error processing image: {str(e)}" |
|
|
|
|
|
|
|
|
def save_temp_image_from_path(image_path): |
|
|
"""Save temporary image from file path for login""" |
|
|
try: |
|
|
if not image_path or not os.path.exists(image_path): |
|
|
return None |
|
|
|
|
|
temp_path = os.path.join(UNKNOWN_USER_DIR, "temp_login.jpg") |
|
|
shutil.copy2(image_path, temp_path) |
|
|
return temp_path |
|
|
|
|
|
except Exception as e: |
|
|
print(f"Error saving temp image: {e}") |
|
|
return None |
|
|
|
|
|
|
|
|
def delete_temp_image(): |
|
|
"""Delete temporary login image""" |
|
|
temp_path = os.path.join(UNKNOWN_USER_DIR, "temp_login.jpg") |
|
|
if os.path.exists(temp_path): |
|
|
try: |
|
|
os.remove(temp_path) |
|
|
except Exception as e: |
|
|
print(f"Error deleting temp image: {e}") |
|
|
|
|
|
|
|
|
def recognize_face(unknown_image_path, tolerance=0.5): |
|
|
""" |
|
|
Recognize face by comparing with stored encodings |
|
|
Returns: (is_match, student_id, confidence, message) |
|
|
""" |
|
|
try: |
|
|
|
|
|
if not os.path.exists(unknown_image_path): |
|
|
return False, None, 0, "Image file not found" |
|
|
|
|
|
unknown_image = fr.load_image_file(unknown_image_path) |
|
|
unknown_encodings = fr.face_encodings(unknown_image) |
|
|
|
|
|
if len(unknown_encodings) == 0: |
|
|
return False, None, 0, "No face detected in the image" |
|
|
|
|
|
unknown_encoding = unknown_encodings[0] |
|
|
|
|
|
|
|
|
best_match_id = None |
|
|
best_distance = float('inf') |
|
|
|
|
|
encoding_files = [f for f in os.listdir(ENCODINGS_DIR) if f.endswith('.pkl')] |
|
|
|
|
|
if not encoding_files: |
|
|
return False, None, 0, "No registered students found in database" |
|
|
|
|
|
for encoding_file in encoding_files: |
|
|
student_id = encoding_file.replace('.pkl', '') |
|
|
encoding_path = os.path.join(ENCODINGS_DIR, encoding_file) |
|
|
|
|
|
with open(encoding_path, 'rb') as f: |
|
|
known_encoding = pickle.load(f) |
|
|
|
|
|
distance = fr.face_distance([known_encoding], unknown_encoding)[0] |
|
|
|
|
|
if distance < best_distance: |
|
|
best_distance = distance |
|
|
best_match_id = student_id |
|
|
|
|
|
|
|
|
if best_distance < tolerance: |
|
|
confidence = (1 - best_distance) * 100 |
|
|
return True, best_match_id, confidence, "Face matched successfully!" |
|
|
else: |
|
|
return False, None, 0, "No matching face found in database" |
|
|
|
|
|
except Exception as e: |
|
|
return False, None, 0, f"Error during recognition: {str(e)}" |
|
|
|
|
|
|
|
|
def get_image_path(student_id): |
|
|
"""Get path to student's image""" |
|
|
return os.path.join(KNOWN_USER_DIR, f"{student_id}.jpg") |
|
|
|
|
|
|
|
|
def image_exists(student_id): |
|
|
"""Check if student's image exists""" |
|
|
return os.path.exists(get_image_path(student_id)) |
|
|
|
|
|
|
|
|
def delete_image(student_id): |
|
|
"""Delete student's image and encoding""" |
|
|
image_path = os.path.join(KNOWN_USER_DIR, f"{student_id}.jpg") |
|
|
encoding_path = os.path.join(ENCODINGS_DIR, f"{student_id}.pkl") |
|
|
|
|
|
if os.path.exists(image_path): |
|
|
os.remove(image_path) |
|
|
if os.path.exists(encoding_path): |
|
|
os.remove(encoding_path) |
|
|
|
|
|
|
|
|
def get_all_images(): |
|
|
"""Get list of all student IDs with images""" |
|
|
return [f.replace('.jpg', '') for f in os.listdir(KNOWN_USER_DIR) if f.endswith('.jpg')] |
|
|
|